Showing posts with label Patterns. Show all posts
Showing posts with label Patterns. Show all posts

2016-02-06

Fresh Book for Django Developers

This week the post office delivered a package that made me very satisfied. It was a box with three paper versions of my "Web Development with Django Cookbook - Second Edition". The book was published at the end of January after months of hard, but fulfilling work in the late evenings and at weekends.

The first Django Cookbook was dealing with Django 1.6. Unfortunately, the support for that version is over. So it made sense to write an update for a newer Django version. The second edition was adapted for Django 1.8 which has a long-term support until April 2018 or later. This edition introduces new features added to Django 1.7 and Django 1.8, such as database migrations, QuerySet expressions, or System Check Framework. Most concepts in this new book should also be working with Django 1.9.

My top 5 favourite new recipes are these:

  • Configuring settings for development, testing, staging, and production environments
  • Using database query expressions
  • Implementing a multilingual search with Haystack
  • Testing pages with Selenium
  • Releasing a reusable Django app

The book is worth reading for any Django developer, but will be best understood by those who already know the basics of web development with Django. You can learn more about the book and buy it at the Packt website or Amazon.

I thank the Packt Publishing very much for long cooperation in the development of this book. I am especially thankful to acquisition editor Nadeem N. Bagban, content development editors Arwa Manasawala and Sumeet Sawant, and technical editor Bharat Patil. Also I am grateful for insightful feedback from the reviewer Jake Kronika.

What 5 recipes do you find the most useful?

2014-10-27

Contributing Back to the Community - Django Cookbook

In the early beginning of year 2014, the IT book publishing company "Packt Publishing" contacted me with an interesting offer: to share my Django experience in a form of a book. I thought it might be a good challenge for me and also value for the Django community, as I had been working with Django for 7 years or so, and during that time there was quite a lot of knowledge gathered and used practically. So for the next 9 months on late evenings and weekends I was adapting some of the most useful code snippets and describing them in the book. The great staff from the Packt Publishing helped me to structure the content, make everything clear and understandable, and get the grammar correct. Finally, the book was released and it's called "Web Development with Django Cookbook".

Word cloud of the Web Development with Django Cookbook

This book is written for intermediate or advanced Django web developers. When writing the book, my own purpose was not to fully cover every possible web development task, but rather to have enough useful bits of knowledge for those who seek information about web development with Django. The book was written in the format of recipes. There are over 70 recipes giving you instructions how to deal with different challenges of web development. The code mentioned in the book is optimized for Django 1.6, but most of it should also work with older Django versions as well as with Django 1.7.

The cookbook consists of 10 chapters:

  1. Getting started with Django 1.6. This chapter will guide you through the basic configuration which is necessary to start any Django project. It will cover topics like virtual environment, version control, and project settings.
  2. Database Structure. When you create a new app, the first thing to do is to define your models. In this chapter you will learn how to write reusable pieces of code to use in your models. You will learn how to deal with multilingual data in your database. Also you will be told how to manage database schema changes using South migrations.
  3. Forms and Views. To show your data or let one create it, you need views and forms. This chapter will show you some patterns for creating them.
  4. Templates and JavaScript. Information is presented to the user by rendered templates. In modern websites, JavaScript is a must for richer user experience. This chapter shows practical examples of using templates and JavaScript together.
  5. Custom Template Filters and Tags. The default Django template system is quite extensive, but there are more things to add for different cases. This chapter shows you how to create and use own template tags and filters.
  6. Model Administration. Django framework comes with a handy pre-build administration. This chapter shows how to extend the default administration with your own functionality.
  7. Django CMS. Django CMS is the most popular open source content management system made in Django. This chapter deals with best practices using Django CMS and extending it for your needs.
  8. Hierarchical Structures. When you need to create a tree-like structure in Django, django-mptt module comes to hand. This chapter shows you how to use it and how to set administration for hierarchical structures.
  9. Data Import and Export. Very often there are cases when you need to transfer data from and to different formats, retrieve it from and provide it to different sources. This chapter deals with management commands for data import and also APIs for data export.
  10. Bells and Whistles. There is more to Django. This chapter shows additional snippets and tricks useful in web development with Django. Also you will learn about deployment of Django projects.

Get a copy of this book at Packt Publishing and tell me what you think about it in the comments below. Which recipes did you find the most useful? What would you like to read more in this blog or another edition of the cookbook?

Web Development with Django Cookbook

2009-04-12

Design Pattern for Reusable Apps: Getting into Details

This article is an attempt to explain a technique for creating reusable and overridable apps that were partly mentioned in my last post.

First of all, let's remember the presentation by James Bennett about reusable apps from DjangoCon 2008:



Also the upgraded version Real World Django by Jacob Kaplan-Moss presented at PyCon 2009 should be checked.

Imagine, that you have a bunch of predefined apps somewhere under your python path. Some of them have models with relations to models from other apps. You will surely want to reuse those apps for different projects. You'll want to be able to activate the necessary set of apps. Probably sometimes you'll want to use an extended version of an existing app. As shown in the presentations given above, reusable apps should allow you easy overrides. Although all apps should be either under python path directly or under a package, nothing should be set in stone. The method get_model() should be used to import models from installed apps. But apps consist of more components than just models. There are urls, views, forms, template tags, context processors, middlewares, etc.

Let's have a look at a simple example. Two reusable apps could be events and venues where events would contain an Event model with a foreign key to Venue model from the venues app. In order to make both models overridable, I'll put the definitions in abstract base classes in the files base.py. The files models.py will import from base.py and create the leaf classes which will be the models to use further in forms and elsewhere.


  • venues

    • __init__.py

    • base.py
      from django.db import models

      class VenueBase(models.Model):
      title = models.CharField(...)
      street_address = models.CharField(...)
      postal_code = models.CharField(...)
      city = models.CharField(...)
      country = models.CharField(...)

      class Meta:
      abstract = True


    • models.py
      from venues.base import *

      class Venue(VenueBase):
      pass





  • events

    • __init__.py

    • base.py
      from django.db import models

      Venue = models.get_model("venues", "Venue")

      class EventBase(models.Model):
      title = models.CharField(...)
      venue = models.ForeignKey(Venue)
      from_date = models.DateField(...)
      to_date = models.DateField(...)

      class Meta:
      abstract = True



    • models.py
      from events.base import *

      class Event(EventBase):
      pass






Venues (as well as events) will probably have some urls, views, and forms which should be extensible too.


  • venues

    • ...

    • forms.py
      from django.db import models
      from django.forms import ModelForm
      Venue = models.get_model("venues", "Venue")

      class VenueForm(ModelForm):
      class Meta:
      model = Venue



    • views.py

      from django.db import models
      from django.utils import importlib
      from django.shortcuts import render_to_response

      # importing the form depending on the path of installed app
      venues_app = models.get_app("venues")
      venues_forms = importlib.import_module(venues_app.__name__[:-6] + "forms")
      VenueForm = venues_forms.VenueForm

      def add_venue(request):
      if request.method == "POST":
      form = VenueForm(request.POST, request.FILES)
      if form.is_valid():
      form.save()
      else:
      form = VenueForm()
      return render_to_response("venues/add_venue.html", {
      "form": form,
      })

      def change_venue(request, pk):
      ...



    • urls.py

      from django.conf.urls.defaults import *
      from django.db import models
      from django.utils import importlib

      # importing the form depending on the path of installed app
      venues_app = models.get_app("venues")
      venues_views = importlib.import_module(venues_app.__name__[:-6] + "views")

      urlpatterns = patterns('',
      ...
      url(r'^add/$', venues_views.add_venue, name='add_venue'),
      url(r'^(\d+)/$', venues_views.change_venue, name='change_venue'),
      ...
      )






You might ask why such a strange and tricky importing is done in the views and urls. If we know the path to the app, it is not going to change or something. Even James Bennett himself didn't see any advantages of importing forms and views dynamically when closing ticket #10703 for Django:
I don't really see the utility of this – a properly-written Django application is just a Python module, and is importable the same as any other Python module. It's not like that module is suddenly going to have a different path (and if it does, you're doing something wrong).


The answer hides in the overriding apps.

The combo of current events and venues might fit most of your projects. But then you might need a specific venues app with additional features for a specific project. Note, that you probably don't want to change or recreate the events app just because of the relation to the venues. The app and model names can be still the same, just put the new app under your new project and include the new app into INSTALLED_APPS instead of the original app. Project name will serve as a namespace for distinguishing the original app and the overridden app.

If you want to extend just the model, but not the other components, your specific app might look like this:


  • myproject

    • venues

      • __init__.py

      • models.py
        from venues.base import VenueBase

        class Venue(VenueBase):
        description = models.TextField(...)



      • forms.py
        from venues.forms import *



      • views.py
        from venues.views import *



      • urls.py
        from venues.urls import *







If the model is OK as is, but you need an additional behavior for the form, like saving an image for each venue, you can extend the form instead:


  • myproject

    • venues

      • __init__.py

      • models.py
        from venues.models import *



      • forms.py
        from django import forms
        from venues.forms import VenueForm as VenueFormBase

        class VenueForm(VenueFormBase):
        image = forms.ImageField(...)
        def save(self, *args, **kwargs):
        super(VenueForm, self).save(*args, **kwargs)
        ...



      • views.py
        from venues.views import *



      • urls.py
        from venues.urls import *







If models and forms are alright, but you want to add an additional view, you can do that too:


  • myproject

    • venues

      • __init__.py

      • models.py
        from venues.models import *



      • forms.py
        from venues.forms import *



      • views.py
        from venues.views import *

        def delete_venue(request, pk):
        ...



      • urls.py
        from venues.urls import *

        urlpatterns += patterns('',
        url(r'^(\d+)/delete/$', venues_views.delete_venue, name='delete_venue'),
        )







As you see from the case examples above, you don't have to duplicate any code of the original app. Still you can now enhance or overwrite just specific parts that you need very flexibly. The events could be extended in the same manner. If the original extensible apps live under a specific package, then the imports in the extending app should be changed appropriately.

Ufff.. That's about all what I wanted to explain this time. If you have any questions, suggestions or disagree with some concepts, please write a comment bellow.

If you reside in Berlin or going to be here next Wednesday by accident or so, don't miss the Django meetup at Schleusenkrug at 19:30.

Also have a nice Easter Holiday!

Django Easter Egg