Django

Exceptions

from django.core.exceptions import ObjectDoesNotExist

Fields

Parameters

blank

If True, the field is allowed to be blank. Default is False.

Note: See null notes below. To allow a date to be empty, you will need to set both blank and null (see Sample below):

Sample:

completed = models.DateTimeField(blank=True, null=True)
notes = models.TextField(blank=True)

null

If True, Django will store empty values as NULL in the database. The default is False.

Note:

  • Empty string values will always get stored as empty strings, not as NULL.
  • Only use null=True for non-string fields such as integers, booleans and dates.
  • For both types of fields, you will also need to set blank=True if you wish to permit empty values in forms, as the null parameter only affects database storage (see blank above).

Sample:

num_pages = models.IntegerField(blank=True, null=True)

Field Types

Django Field Types

Settings

In your settings/production.py file:

if get_env_variable_bool('SSL'):
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True

ALLOWED_HOSTS = [get_env_variable('ALLOWED_HOSTS').split(',')]
# https://docs.djangoproject.com/en/1.10/releases/1.9/#csrf
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS

DOMAIN = get_env_variable('DOMAIN')
DATABASE = DOMAIN.replace('.', '_')

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': DATABASE,
        'USER': DATABASE,
        'PASSWORD': get_env_variable('DB_PASS'),
        'HOST': get_env_variable('DB_IP'),
        'PORT': '',
    }
}

Run development environment without debug

In settings/local.py set:

DEBUG = False

Then run development server:

django-admin runserver 0.0.0.0:8000 --insecure

Migrations

Django Migrations

Transactions

I have started using transaction.atomic in several of the views. Make sure the transaction is committed before adding a task to the queue or returning the HTTP response.

This is the pattern I am using:

from django.http import HttpResponseRedirect

def form_valid(self, form):
    with transaction.atomic():
        self.object = form.save(commit=False)
        self.object.deleted = True
        self.object = form.save()
    # add a task to the queue
    transaction.on_commit(lambda: sync_task.delay(self.object.pk))
    # and/or return the response
    return HttpResponseRedirect(self.get_success_url())

For more information, see on_commit

Updates

Django 1.11

To include the admin URLs in Django 1.11:

url(regex=r'^admin/',
    view=admin.site.urls
    ),

Older versions of easy-thumbnails and django-bootstrap3 have compatiblity issues with version 1.11. Upgrade to easy-thumbnails==2.4.1 and django-bootstrap3==8.2.2.

There is a change to the build_attrs method signature from django.forms.Widget. Whereas before we could do this:

from django.forms import Widget

widget = Widget()
final_attrs = widget.build_attrs(attrs, type='file', name='image')

We now need to do this:

from django.forms import Widget

widget = Widget()
extra_attrs = attrs.copy() if attr else {}
extra_attrs.update(name='image', type='file')
final_attrs = widget.build_attrs(widget.attrs, extra_attrs)

Use MIDDLEWARE in the settings file rather than MIDDLEWARE_CLASSES.

In old migrations, the on_delete parameter is now required, so change:

('mail', models.ForeignKey(to='mail.Mail')),

to:

('mail', models.ForeignKey(to='mail.Mail', on_delete=models.CASCADE)),

Django 1.10

from django.conf.urls import patterns, url

urlpatterns = patterns(
    '',

Is now:

from django.conf.urls import url

urlpatterns = [

Note

Make sure you remove ''

The use of strings to define a view in the URLConf has been removed see this stackoverflow post

A url definition such as this:

url(regex=r'^sitemap\.xml$',
    view='django.contrib.sitemaps.views.sitemap',
    kwargs={'sitemaps': sitemaps},
    ),

should be replaced with:

from django.contrib.sitemaps.views import sitemap
...

url(regex=r'^sitemap\.xml$',
    view=sitemap,
    kwargs={'sitemaps': sitemaps},
    ),

Django 1.9

The contenttypes framework:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()

Database

postgresql_psycopg2 is now postgresql:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',

Forms

Using a forms.ModelForm with a FormView will raise this error:

TypeError: isinstance() arg 2 must be a type or tuple of types

To solve the issue use a forms.Form with a FormView.

Logging

From Cannot resolve ‘django.utils.log.NullHandler’:

'handlers': {
  'null': {
     'level': 'DEBUG',
     'class': 'logging.NullHandler',
  },

Django 1.8

Remove TEMPLATE_DIRS and replace with:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.template.context_processors.debug',
                'django.template.context_processors.i18n',
                'django.template.context_processors.media',
                'django.template.context_processors.static',
                'django.template.context_processors.tz',
                'django.contrib.messages.context_processors.messages',
            ],
            'string_if_invalid': '**** INVALID EXPRESSION: %s ****',
        },
    },
]

Remove:

TEMPLATE_DEBUG = DEBUG
TEMPLATE_STRING_IF_INVALID = '**** INVALID EXPRESSION: %s ****'

formtools

The formtools package has been removed, so if you need wizards replace:

from django.contrib.formtools.wizard.views import SessionWizardView

with:

from formtools.wizard.views import SessionWizardView

Install:

django-formtools

Add formtools to INSTALLED_APPS:

INSTALLED_APPS = (
    # ...
    'formtools',
)

get_model

from django.apps import apps
model = apps.get_model('compose', 'Article')

Management Commands

Django 1.8 uses argparse rather than optparse. For details, see Custom Management Commands and Argparse Tutorial. You are encouraged to exclusively use **options for new commands:

def add_arguments(self, parser):
    parser.add_argument(
        '--path',
        help="path to the 'name.csv' file"
    )

def handle(self, *args, **options):
    file_name = options['path']

Django 1.7

Remove south from requirements and INSTALLED_APPS

Update django and reversion in the requirements:

django-reversion==1.8.5
Django==1.7.1

To get rid of (1_6.W001) Some project unittests may not execute as expected remove the following from your settings:

SITE_ID = 1
DJANGO_APPS = (
    'django.contrib.sites',

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    # 'django.template.loaders.eggs.Loader',
)

Note

only remove the SITE_ID and sites if you are not using Site in your project (I am using Site in hatherleigh_net).

Remove migrations folders… then create new version 1.7 migrations: Django Migrations.

Deploy

If you get the error:

relation "easy_thumbnails_thumbnaildimensions" already exists

Then, just drop the table:

DROP TABLE easy_thumbnails_thumbnaildimensions;

Users

from django.contrib.auth import get_user_model
get_user_model().objects.get(username=user_name)