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('.', '_').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.

Updates

Django 2.0

admin: To include the admin URLs, replace:

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

with:

from django.urls import path
urlpatterns = [
    path('admin/', admin.site.urls),

braces: Use the 2.0 branch:

git+https://github.com/brack3t/django-braces.git@2.0#egg=braces

on_delete: For a ForeignKey, add on_delete:

user_deleted = models.ForeignKey(
    ...
    on_delete=models.CASCADE,

Note

The default is models.CASCADE

pytest: If pytest-django is looking for manage.py, add the following to setup.cfg:

[tool:pytest]
django_find_project = false

pytest error:

INTERNALERROR> AttributeError: 'NoneType' object has no attribute 'testscollected'
pip install pytest==3.3.2

pytest-django:

If you get django.core.urlresolvers from pytest-django, then add the following to your requirements:

git+https://github.com/pytest-dev/pytest-django.git@94cccb956435dd7a719606744ee7608397e1eafb#egg=pytest_django

taggit: https://github.com/alex/django-taggit/issues/520:

AttributeError: 'TaggableRel' object has no attribute 'related_query_name'

To fix the issue, install:

django-taggit==0.22.2

urls: The import for reverse is just django.urls:

from django.urls import reverse
from django.urls import reverse_lazy

WSGIRequest:

AttributeError: 'WSGIRequest' object has no attribute 'user'

MIDDLEWARE: Use MIDDLEWARE in the settings file rather than MIDDLEWARE_CLASSES.

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)