Web Development With Django Cookbook - Second Edition - Sample Chapter
Web Development With Django Cookbook - Second Edition - Sample Chapter
ee
By the end you'll have a good understanding of the new features added to Django 1.8 and you will be an
expert at web development processes.
model mixins
Manage forms and views and get to know
Django CMS
and problems
problems efficiently
real-world problems
Haystack
$ 49.99 US
31.99 UK
Aidas Bendoraitis
P U B L I S H I N G
Throughout this book, you'll discover how to collect data from different sources and provide it on a
website in different formats. The book follows a task-based approach to guide you through all the web
development processes using the Django framework. You'll learn to write reusable pieces of code for
your models and find out how to manage database schema changes using Django migrations. Towards
the end of the book you'll be introduced to some programming and debugging tricks, and you will be
shown how to test and deploy the project to a remote dedicated server.
P U B L I S H I N G
Sa
pl
e
Aidas Bendoraitis
Preface
Django framework is relatively easy to learn and it solves many web-related questions, such as
project structure, database object-relational mapping, templating, form validation, sessions,
authentication, security, cookie management, internationalization, basic administration,
interface to access data from scripts, and so on. Django is based on the Python programming
language, where the code is clear and easy to read. Also, Django has a lot of third-party
modules that can be used in conjunction with your own apps. Django has an established and
vibrant community, where you can find source code, get help, and contribute.
Web Development with Django Cookbook - Second Edition will guide you through all the
web development process with Django 1.8 framework. You will get started with the virtual
environment and configuration of the project. Then, you will learn how to define the database
structure with reusable components. The book will move on to the forms and views to enter
and list the data. Then, you will continue with responsive templates and JavaScript to create
the best user experience. After this, you will find out how to tweak administration in order to
make the website editors happy. You will also learn how to integrate your own functionality
in Django CMS. The next step will be to learn how to use hierarchical structures. You will
find out that collecting data from different sources and providing data to others in different
formats isn't as difficult as you thought. Then, you'll be introduced to some programming and
debugging tricks. Finally, you will be shown how to test and deploy the project to a remote
dedicated server.
In contrast to other Django books, this book will deal not only with the code of the framework
itself, but also with some important third-party modules that are necessary for fully-equipped
web development. Also, the book gives examples of rich user interfaces using Bootstrap
frontend framework and jQuery JavaScript library.
Preface
Chapter 2, Database Structure, teaches how to write reusable pieces of code to use in your
models. When you create a new app, the first thing to do is to define your models. Also, you
will be asked how to manage the database schema changes using Django migrations.
Chapter 3, Forms and Views, shows you some patterns used to create the views and forms for
your data.
Chapter 4, Templates and JavaScript, covers practical examples of using templates and
JavaScript together. We will bring together templates and JavaScript as information is always
presented to the user by rendered templates and in modern website, JavaScript is a must for
a rich user experience.
Chapter 5, Custom Template Filters and Tags, explains how to create and use your own
template filters and tags. As you will see, the default Django template system can be
extended to match template developers' needs.
Chapter 6, Model Administration, guides you through extending the default administration
with your own functionality as the Django framework comes with a handy pre-built model
administration.
Chapter 7, Django CMS, deals with the best practices of using Django CMS, which is the most
popular open source content management system made with Django, and adapting it to your
project's requirements.
Chapter 8, Hierarchical Structures, shows that whenever you need to create a tree-like
structure in Django, the django-mptt module comes in handy. This chapter shows you how
to use it and set administration for hierarchical structures.
Chapter 9, Data Import and Export, demonstrates how to transfer data from and to different
formats, as well as retrieve it from and provide it to different sources. This chapter deals with
the management commands for data import and also APIs for data export.
Chapter 10, Bells and Whistles, shows some additional snippets and tricks useful in everyday
web development and debugging.
Chapter 11, Testing and Deployment, teaches how to test your project and deploy it on the
remote server.
Making your code compatible with both Python 2.7 and Python 3
Introduction
In this chapter, we will see a few good practices when starting a new project with Django 1.8
on Python 2.7 or Python 3. Some of the tricks introduced here are the best ways to deal with
the project layout, settings, and configurations. However, for some tricks, you might have to
find some alternatives online or in other books about Django. Feel free to evaluate and choose
the best bits and pieces for yourself while digging deep into the Django world.
I am assuming that you are already familiar with the basics of Django, Subversion and Git
version control, MySQL and PostgreSQL databases, and command-line usage. Also, I am
assuming that you are probably using a Unix-based operating system, such as Mac OS X or
Linux. It makes more sense to develop with Django on Unix-based platforms as the websites
will most likely be published on a Linux server, therefore, you can establish routines that work
the same while developing as well as deploying. If you are locally working with Django on
Windows, the routines are similar; however, they are not always the same.
Getting ready
To manage Python packages, you will need pip. It is included in your Python installation if
you are using Python 2.7.9 or Python 3.4+. If you are using another version of Python, install
pip by executing the installation instructions at http://pip.readthedocs.org/en/
stable/installing/. Let's install the shared Python modules Pillow and MySQLdb, and
the virtualenv utility, using the following commands:
$ sudo pip install Pillow
$ sudo pip install MySQL-python
$ sudo pip install virtualenv
Chapter 1
How to do it
Once you have your prerequisites installed, create a directory where all your Django projects
will be stored, for example, virtualenvs under your home directory. Perform the following
steps after creating the directory:
1. Go to the newly created directory and create a virtual environment that uses the
shared system site packages:
$ cd ~/virtualenvs
$ mkdir myproject_env
$ cd myproject_env
$ virtualenv --system-site-packages .
New python executable in ./bin/python
Installing setuptools.done.
Installing pipdone.
2. To use your newly created virtual environment, you need to execute the activation
script in your current shell. This can be done with the following command:
$ source bin/activate
You can also use the following command one for the same (note the space between
the dot and bin):
$ . bin/activate
3. You will see that the prompt of the command-line tool gets a prefix of the project
name, as follows:
(myproject_env)$
How it works
When you create a virtual environment, a few specific directories (bin, build, include, and
lib) are created in order to store a copy of the Python installation and some shared Python
paths are defined. When the virtual environment is activated, whatever you have installed
with pip or easy_install will be put in and used by the site packages of the virtual
environment, and not the global site packages of your Python installation.
To install Django 1.8 in your virtual environment, type the following command:
(myproject_env)$ pip install Django==1.8
See also
The Deploying on Apache with mod_wsgi recipe in Chapter 11, Testing and Deployment
Getting ready
If you haven't done this yet, create a virtualenvs directory, where you will keep all your
virtual environments (read about this in the Working with a virtual environment recipe).
This can be created under your home directory.
Then, create a directory for your project's environment, for example, myproject_env. Start
the virtual environment in it. I would suggest adding the commands directory for local bash
scripts that are related to the project, the db_backups directory for database dumps, and the
project directory for your Django project. Also, install Django in your virtual environment.
How to do it
Follow these steps in order to create a file structure for your project:
1. With the virtual environment activated, go to the project directory and start a new
Django project as follows:
(myproject_env)$ django-admin.py startproject myproject
For clarity, we will rename the newly created directory as django-myproject. This
is the directory that you will put under version control, therefore, it will have the .git,
.svn, or similar directories.
Chapter 1
2. In the django-myproject directory, create a README.md file to describe your
project to the new developers. You can also put the pip requirements with the
Django version and include other external dependencies (read about this in the
Handling project dependencies with pip recipe). Also, this directory will contain your
project's Python package named myproject; Django apps (I recommend having
an app called utils for different functionalities that are shared throughout the
project); a locale directory for your project translations if it is multilingual; a Fabric
deployment script named fabfile.py, as suggested in the Creating and using the
Fabric deployment script recipe in Chapter 11, Testing and Deployment; and the
externals directory for external dependencies that are included in this project if
you decide not to use pip requirements.
3. In your project's Python package, myproject, create the media directory for project
uploads, the site_static directory for project-specific static files, the static
directory for collected static files, the tmp directory for the upload procedure, and the
templates directory for project templates. Also, the myproject directory should
contain your project settings, the settings.py and conf directories (read about
this in the Configuring settings for development, testing, staging, and production
environments recipe), as well as the urls.py URL configuration.
4. In your site_static directory, create the site directory as a namespace for sitespecific static files. Then, separate the separated static files in directories in it. For
instance, scss for Sass files (optional), css for the generated minified Cascading
Style Sheets, img for styling images and logos, js for JavaScript, and any third-party
module combining all types of files such as the tinymce rich-text editor. Besides the
site directory, the site_static directory might also contain overwritten static
directories of third-party apps, for example, cms overwriting static files from Django
CMS. To generate the CSS files from Sass and minify the JavaScript files, you can use
the CodeKit or Prepros applications with a graphical user interface.
5. Put your templates that are separated by the apps in your templates directory. If a
template file represents a page (for example, change_item.html or item_list.
html), then directly put it in the app's template directory. If the template is included
in another template (for example, similar_items.html), put it in the includes
subdirectory. Also, your templates directory can contain a directory called utils for
globally reusable snippets, such as pagination, language chooser, and others.
How it works
The whole file structure for a complete project in a virtual environment will look similar to
the following:
Chapter 1
See also
The Deploying on Apache with mod_wsgi recipe in Chapter 11, Testing and Deployment
The Creating and using the Fabric deployment script recipe in Chapter 11, Testing
and Deployment
Getting ready
Before using this recipe, you need to have pip installed and a virtual environment activated.
For more information on how to do this, read the Working with a virtual environment recipe.
How to do it
Execute the following steps one by one to prepare pip requirements for your Django project:
1. Let's go to your Django project that you have under version control and create the
requirements directory with these text files: base.txt for shared modules, dev.
txt for development environment, test.txt for testing environment, staging.
txt for staging environment, and prod.txt for production.
3. If the requirements of a specific environment are the same as in the base.txt, add the
line including the base.txt in the requirements file of that environment, for example:
# prod.txt
-r base.txt
4. If there are specific requirements for an environment, add them as shown in the
following:
# dev.txt
-r base.txt
django-debug-toolbar
selenium
5. Now, you can run the following command in order to install all the required
dependencies for development environment (or analogous command for other
environments), as follows:
(myproject_env)$ pip install -r requirements/dev.txt
How it works
The preceding command downloads and installs all your project dependencies from
requirements/base.txt and requirements/dev.txt in your virtual environment. As
you can see, you can specify a version of the module that you need for the Django framework
and even directly install from a specific commit at the Git repository for the python-socialauth in our example. In practice, installing from a specific commit would rarely be useful, for
instance, only when having third-party dependencies in your project with specific functionality
that are not supported in the recent versions anymore.
When you have many dependencies in your project, it is good practice to stick to specific
versions of the Python modules as you can then be sure that when you deploy your project
or give it to a new developer, the integrity doesn't get broken and all the modules function
without conflicts.
If you have already manually installed the project requirements with pip one by one, you
can generate the requirements/base.txt file using the following command:
(myproject_env)$ pip freeze > requirements/base.txt
8
Chapter 1
There's more
If you want to keep things simple and are sure that, for all environments, you will be using the
same dependencies, you can use just one file for your requirements named requirements.
txt, by definition:
(myproject_env)$ pip freeze > requirements.txt
To install the modules in a new environment simply call the following command:
(myproject_env)$ pip install -r requirements.txt
See also
Getting ready
When creating a new Django project or upgrading an old existing project, consider following
the rules given in this recipe.
How to do it
Making your code compatible with both Python versions consists of the following steps:
1. At the top of each module, add from __future__ import unicode_literals
and then use usual quotes without a u prefix for Unicode strings and a b prefix for
bytestrings.
2. To ensure that a value is bytestring, use the django.utils.encoding.smart_
bytes function. To ensure that a value is Unicode, use the django.utils.
encoding.smart_text or django.utils.encoding.force_text function.
3. For your models, instead of the __unicode__ method, use the __str__ method
and add the python_2_unicode_compatible decorator, as follows:
# models.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import \
python_2_unicode_compatible
@python_2_unicode_compatible
class NewsArticle(models.Model):
title = models.CharField(_("Title"), max_length=200)
content = models.TextField(_("Content"))
def __str__(self):
return self.title
class Meta:
verbose_name = _("News Article")
verbose_name_plural = _("News Articles")
Chapter 1
pass
except NewsArticle.MultipleObjectsReturned as exc:
pass
7.
8. To check whether the current version is Python 2 or Python 3, you can use the
following conditions:
from django.utils import six
if six.PY2:
print("This is Python 2")
if six.PY3:
print("This is Python 3")
How it works
All strings in Django projects should be considered as Unicode strings. Only the input of
HttpRequest and output of HttpResponse is usually in the UTF-8 encoded bytestring.
Many functions and methods in Python 3 now return the iterators instead of lists, which make
the language more efficient. To make the code compatible with both the Python versions, you
can use the six library that is bundled in Django.
Read more about writing compatible code in the official Django documentation at
https://docs.djangoproject.com/en/1.8/topics/python3/.
Downloading the example code
You can download the example code files for all Packt books that you have
purchased from your account at http://www.packtpub.com. If you
purchased this book elsewhere, you can visit http://www.packtpub.
com/support and register in order to have the files e-mailed directly to you.
11
Getting ready
Start with a virtual environment with a Django project in it.
How to do it
Execute the following steps one by one:
1. If you haven't done this already, create an externals directory under your Django
project django-myproject directory. Then, create the libs and apps directories
under it.
The libs directory is for the Python modules that are required by your project, for
example, boto, Requests, Twython, Whoosh, and so on. The apps directory is for
third-party Django apps, for example, django-cms, django-haystack, django-storages,
and so on.
I highly recommend that you create the README.txt files in
the libs and apps directories, where you mention what each
module is for, what the used version or revision is, and where it is
taken from.
12
Chapter 1
2. The directory structure should look something similar to the following:
3. The next step is to put the external libraries and apps under the Python path so that
they are recognized as if they were installed. This can be done by adding the following
code in the settings:
# settings.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
import os
import sys
BASE_DIR = os.path.abspath(os.path.join(
os.path.dirname(__file__), ".."
))
EXTERNAL_LIBS_PATH = os.path.join(
BASE_DIR, "externals", "libs"
)
EXTERNAL_APPS_PATH = os.path.join(
BASE_DIR, "externals", "apps"
)
sys.path = ["", EXTERNAL_LIBS_PATH, EXTERNAL_APPS_PATH] + \
sys.path
How it works
A module is meant to be under the Python path if you can run Python and import that module.
One of the ways to put a module under the Python path is to modify the sys.path variable
before importing a module that is in an unusual location. The value of sys.path is a list of
directories starting with an empty string for the current directory, followed by the directories in
the virtual environment, and finally the globally shared directories of the Python installation.
You can see the value of sys.path in the Python shell, as follows:
(myproject_env)$ python
>>> import sys
>>> sys.path
13
See also
The Using the Django shell recipe in Chapter 10, Bells and Whistles
Getting ready
In a Django project, we'll create settings for each environment: development, testing, staging,
and production.
14
Chapter 1
How to do it
Follow these steps to configure project settings:
1. In myproject directory, create a conf Python module with the following files:
__init__.py, base.py for shared settings, dev.py for development settings,
test.py for testing settings, staging.py for staging settings, and prod.py for
production settings.
2. Put all your shared settings in conf/base.py.
3. If the settings of an environment are the same as the shared settings, then just
import everything from base.py there, as follows:
# myproject/conf/prod.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from .base import *
4. Apply the settings that you want to attach or overwrite for your specific environment in
the other files, for example, the development environment settings should go to dev.
py as shown in the following:
# myproject/conf/dev.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from .base import *
EMAIL_BACKEND = \
"django.core.mail.backends.console.EmailBackend"
How it works
By default, the Django management commands use the settings from myproject/
settings.py. Using the method that is defined in this recipe, we can keep all the required
non-sensitive settings for all environments under version control in the conf directory.
Whereas, the settings.py file itself would be ignored by version control and will only
contain the settings that are necessary for the current development, testing, staging, or
production environments.
See also
Getting ready
To start with, open settings.py.
How to do it
Modify your path-related settings accordingly instead of hardcoding the paths to your local
directories, as follows:
# settings.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
import os
BASE_DIR = os.path.abspath(
16
Chapter 1
os.path.join(os.path.dirname(__file__), "..")
)
MEDIA_ROOT = os.path.join(BASE_DIR, "myproject", "media")
STATIC_ROOT = os.path.join(BASE_DIR, "myproject", "static")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "myproject", "site_static"),
)
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, "myproject", "templates"),
)
LOCALE_PATHS = (
os.path.join(BASE_DIR, "locale"),
)
FILE_UPLOAD_TEMP_DIR = os.path.join(
BASE_DIR, "myproject", "tmp"
)
How it works
At first, we define BASE_DIR, which is an absolute path to one level higher than the
settings.py file. Then, we set all the paths relative to BASE_DIR using the os.path.join
function.
See also
17
Getting ready
Most of the settings for different environments will be shared and saved in version control.
However, there will be some settings that are specific to the environment of the project instance,
for example, database or e-mail settings. We will put them in the local_settings.py file.
How to do it
To use local settings in your project, perform the following steps:
1. At the end of settings.py, add a version of local_settings.py that claims to
be in the same directory, as follows:
# settings.py
# put this at the end of the file
try:
execfile(os.path.join(
os.path.dirname(__file__), "local_settings.py"
))
except IOError:
pass
18
Chapter 1
How it works
As you can see, the local settings are not normally imported, they are rather included and
executed in the settings.py file itself. This allows you to not only create or overwrite the
existing settings, but also adjust the tuples or lists from the settings.py file. For example,
we add debug_toolbar to INSTALLED_APPS here in order to be able to debug the SQL
queries, template context variables, and so on.
See also
The Toggling the Debug Toolbar recipe in Chapter 10, Bells and Whistles
Getting ready
Make sure that your project is under the subversion version control and you have BASE_DIR
defined in your settings, as shown in the Defining relative paths in the settings recipe.
Then, create the utils module in your Django project, and also create a file called misc.py
there.
How to do it
The procedure to put the revision number in the STATIC_URL setting consists of the following
two steps:
1. Insert the following content:
# utils/misc.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
19
2. Then, modify the settings.py file and add the following lines:
# settings.py
# somewhere after BASE_DIR definition
from utils.misc import get_media_svn_revision
STATIC_URL = "/static/%s/" % get_media_svn_revision(BASE_DIR)
How it works
The get_media_svn_revision() function takes the absolute_path directory as a
parameter and calls the svn info shell command in that directory to find out the current
revision. We pass BASE_DIR to the function as we are sure that it is under version control.
Then, the revision is parsed, returned, and included in the STATIC_URL definition.
See also
Getting ready
Make sure that your project is under the Git version control and you have BASE_DIR defined
in your settings, as shown in the Defining relative paths in the settings recipe.
20
Chapter 1
If you haven't done it yet, create the utils module in your Django project. Also, create a
misc.py file there.
How to do it
The procedure to put the Git timestamp in the STATIC_URL setting consists of the following
two steps:
1. Add the following content to the misc.py file placed in utils/:
# utils/misc.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
import subprocess
from datetime import datetime
def get_git_changeset(absolute_path):
repo_dir = absolute_path
git_show = subprocess.Popen(
'git show --pretty=format:%ct --quiet HEAD',
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
shell=True, cwd=repo_dir, universal_newlines=True,
)
timestamp = git_show.communicate()[0].partition('\n')[0]
try:
timestamp = \
datetime.utcfromtimestamp(int(timestamp))
except ValueError:
return ""
changeset = timestamp.strftime('%Y%m%d%H%M%S')
return changeset
2. Then, import the newly created get_git_changeset() function in the settings and
use it for the STATIC_URL path, as follows:
# settings.py
# somewhere after BASE_DIR definition
from utils.misc import get_git_changeset
STATIC_URL = "/static/%s/" % get_git_changeset(BASE_DIR)
21
How it works
The get_git_changeset() function takes the absolute_path directory as a parameter
and calls the git show shell command with the parameters to show the Unix timestamp of
the HEAD revision in the directory. As stated in the previous recipe, we pass BASE_DIR to the
function as we are sure that it is under version control. The timestamp is parsed; converted to
a string consisting of year, month, day, hour, minutes, and seconds; returned; and included in
the definition of STATIC_URL.
See also
Getting ready
Make sure that the MySQL database management system and the MySQLdb Python module
are installed and you are using the MySQL engine in your project's settings.
How to do it
Open the /etc/mysql/my.cnf MySQL configuration file in your favorite editor and ensure
that the following settings are set in the sections: [client], [mysql], and [mysqld],
as follows:
# /etc/mysql/my.cnf
[client]
default-character-set = utf8
[mysql]
22
Chapter 1
default-character-set = utf8
[mysqld]
collation-server = utf8_unicode_ci
init-connect = 'SET NAMES utf8'
character-set-server = utf8
If any of the sections don't exist, create them in the file. Then, restart MySQL in your
command-line tool, as follows:
$ /etc/init.d/mysql restart
How it works
Now, whenever you create a new MySQL database, the databases and all their tables will be
set in UTF-8 encoding by default.
Don't forget to set this in all computers where your project is developed or published.
Getting ready
Make sure that your Django project is under the Subversion version control.
How to do it
Open your command-line tool and set your default editor as nano, vi, vim or any other that
you prefer, as follows:
$ export EDITOR=nano
23
# C extensions
*.so
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov
.tox
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
# Translations
*.pot
# Django stuff:
*.log
# PyBuilder
target
24
Chapter 1
Save the file and exit the editor. For every other Python package in your project, you will
need to ignore several files and directories too. Just go to a directory and type the following
command:
$ svn propedit svn:ignore .
Then, put this in the temporary file, save it, and close the editor, as follows:
# Byte-compiled / optimized / DLL files
__pycache__
*.py[cod]
*$py.class
# C extensions
*.so
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov
.tox
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
# Translations
*.pot
# Django stuff:
*.log
# PyBuilder
target
25
How it works
In Subversion, you need to define the ignore properties for each directory of your project.
Mainly, we don't want to track the Python-compiled files, for instance, *.pyc. We also want to
ignore local_settings.py that is specific for each environment, static that replicates
collected static files from different apps, media that contains uploaded files and changes
together with the database, and tmp that is temporarily used for file uploads.
If you keep all your settings in a conf Python package
as described in the Configuring settings for development,
testing, staging, and production environments recipe, add
settings.py to the ignored files too.
See also
Getting ready
Make sure that your Django project is under the Git version control.
How to do it
Using your favorite text editor, create a .gitignore file at the root of your Django project and
put these files and directories there, as follows:
# .gitignore
# Project files and directories
/myproject/local_settings.py
/myproject/static/
/myproject/tmp/
/myproject/media/
# Byte-compiled / optimized / DLL files
__pycache__/
26
Chapter 1
*.py[cod]
*$py.class
# C extensions
*.so
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
# Translations
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
How it works
The .gitignore file specifies the paths that should intentionally be untracked by the
Git version control system. The .gitignore file that we created in this recipe will ignore
the Python-compiled files, local settings, collected static files, temporary directory for
uploads, and media directory with the uploaded files.
27
See also
Getting ready
Use your favorite editor and edit or create a .bash_profile file in your home directory.
How to do it
Add this alias at the end of .bash_profile, as follows:
# ~/.bash_profile
alias delpyc="find . -name \"*.pyc\" -delete"
Now, to clean the Python-compiled files, go to your project directory and type the following
command in the command line:
$ delpyc
How it works
At first, we create a Unix alias that searches for the *.pyc files and deletes them in the
current directory and its children. The .bash_profile file is executed when you start
a new session in the command-line tool.
28
Chapter 1
See also
Getting ready
Create a virtual environment and a Django project in it.
How to do it
Use the following structure in a Python file that you create. Just after the first line that defines
UTF-8 as the default Python file encoding, put the imports categorized in sections, as follows:
# -*- coding: UTF-8 -*# System libraries
from __future__ import unicode_literals
import os
import re
from datetime import datetime
# Third-party libraries
import boto
from PIL import Image
# Django modules
from django.db import models
from django.conf import settings
# Django apps
from cms.models import Page
# Current-app modules
from . import app_settings
29
How it works
We have five main categories for the imports, as follows:
There's more
When coding in Python and Django, use the official style guide for Python code, PEP 8. You
can find it at https://www.python.org/dev/peps/pep-0008/.
See also
Getting ready
Either create your Django app manually or using this command in your virtual environment
(learn how to use virtual environments in the Working with a virtual environment recipe),
as follows:
(myproject_env)$ django-admin.py startapp magazine
30
Chapter 1
Add some NewsArticle model to models.py, create administration for the model
in admin.py, and put "magazine" in INSTALLED_APPS in the settings. If you are
not yet familiar with these tasks, study the official Django tutorial at https://docs.
djangoproject.com/en/1.8/intro/tutorial01/.
How to do it
Follow these steps to create and use the app configuration:
1. First of all, create the apps.py file and put this content in it, as follows:
# magazine/apps.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
class MagazineAppConfig(AppConfig):
name = "magazine"
verbose_name = _("Magazine")
def ready(self):
from . import signals
2. Then, edit the __init__.py file of the app and put the following content:
# magazine/__init__.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
default_app_config = "magazine.apps.MagazineAppConfig"
3. Lastly, let's create a signals.py file and add some signal handlers there:
# magazine/signals.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.conf import settings
from .models import NewsArticle
@receiver(post_save, sender=NewsArticle)
def news_save_handler(sender, **kwargs):
if settings.DEBUG:
print("%s saved." % kwargs['instance'])
@receiver(post_delete, sender=NewsArticle)
31
How it works
When you run an HTTP server or invoke a management command, django.setup() is
called. It loads the settings, sets up logging, and initializes app registry. The app registry is
initialized in three steps, as shown in the following:
Django tries to import models.py from each app in INSTALLED_APPS and collect
all the models.
Finally, Django runs the ready() method for each app configuration. This method
is a correct place to register signal handlers, if you have any. The ready() method
is optional.
In our example, the MagazineAppConfig class sets the configuration for the
magazine app. The name parameter defines the name of the current app. The
verbose_name parameter is used in the Django model administration, where
models are presented and grouped by apps. The ready() method imports and
activates the signal handlers that, when in DEBUG mode, print in the terminal
that a NewsArticle was saved or deleted.
There is more
After calling django.setup(), you can load the app configurations and models from the
registry as follows:
>>> from django.apps import apps as django_apps
>>> magazine_app_config = django_apps.get_app_config("magazine")
>>> magazine_app_config
<MagazineAppConfig: magazine>
>>> magazine_app_config.models_module
<module 'magazine.models' from 'magazine/models.pyc'>
NewsArticle = django_apps.get_model("magazine", "NewsArticle")
You can read more about app configuration in the official Django documentation at
https://docs.djangoproject.com/en/1.8/ref/applications/
32
Chapter 1
See also
Getting ready
Either create your Django app manually or using the following command:
(myproject_env)$ django-admin.py startapp myapp1
How to do it
If you just have one or two settings, you can use the following pattern in your models.py
file. If the settings are extensive and you want to have them organized better, create an
app_settings.py file in the app and put the settings in the following way:
# models.py or app_settings.py
# -*- coding: UTF-8 -*from __future__ import unicode_literals
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
SETTING1 = getattr(settings, "MYAPP1_SETTING1", u"default value")
MEANING_OF_LIFE = getattr(settings, "MYAPP1_MEANING_OF_LIFE", 42)
STATUS_CHOICES = getattr(settings, "MYAPP1_STATUS_CHOICES", (
("draft", _("Draft")),
("published", _("Published")),
("not_listed", _("Not Listed")),
))
33
If you want to overwrite the STATUS_CHOICES setting for just one project, you simply open
settings.py and add the following:
# settings.py
#
from django.utils.translation import ugettext_lazy as _
MYAPP1_STATUS_CHOICES = (
("imported", _("Imported")),
("draft", _("Draft")),
("published", _("Published")),
("not_listed", _("Not Listed")),
("expired", _("Expired")),
)
How it works
The getattr(object, attribute_name[, default_value]) Python function tries
to get the attribute_name attribute from object and returns default_value if it is not
found. In this case, different settings are tried in order to be taken from the Django project
settings module, and if they are not found, the default values are assigned.
34
Get more information Web Development with Django Cookbook - Second Edition
www.PacktPub.com
Stay Connected: