All notes
Model

Fields

Field options

null

jodyboucher.com: django how - null and blank.

null defines whether empty (NULL) values are allowed to be stored in the database.

The default value of null=False raises IntegrityError when an empty value is attempted to be written to a non-string-based field. For string-based fields an empty string is written to the database column.

Avoid using null on string-based fields such as CharField and TextField because empty string values will always be stored as empty strings, not as NULL. If a string-based field has null=True, that means it has two possible values for "no data" - redundancy.

When using the Oracle database backend, the value NULL will be stored to denote the empty string regardless of this attribute.

If you want to accept null values with BooleanField, use NullBooleanField instead.

blank

Unlike the null field option, the blank field option is unrelated to the data stored in the database. blank is used solely for form validation of the field.

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

choices

An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use for this field. If this is given, the default form widget will be a select box.

The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name. For example:


YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
)

Generally, it's best to define choices inside a model class, and to define a suitably-named constant for each value:


from django.db import models

class Student(models.Model):
    FRESHMAN = 'FR'
    SOPHOMORE = 'SO'
    JUNIOR = 'JR'
    SENIOR = 'SR'
    YEAR_IN_SCHOOL_CHOICES = (
        (FRESHMAN, 'Freshman'),
        (SOPHOMORE, 'Sophomore'),
        (JUNIOR, 'Junior'),
        (SENIOR, 'Senior'),
    )
    year_in_school = models.CharField(max_length=2,
                                      choices=YEAR_IN_SCHOOL_CHOICES,
                                      default=FRESHMAN)

    def is_upperclass(self):
        return self.year_in_school in (self.JUNIOR, self.SENIOR)

Student.SOPHOMORE will work anywhere that the Student model has been imported.

You can also collect your available choices into named groups that can be used for organizational purposes:


MEDIA_CHOICES = (
    ('Audio', (
            ('vinyl', 'Vinyl'),
            ('cd', 'CD'),
        )
    ),
    ('Video', (
            ('vhs', 'VHS Tape'),
            ('dvd', 'DVD'),
        )
    ),
    ('unknown', 'Unknown'),
)

The first element in each tuple is the name to apply to the group. Grouped options may be combined with ungrouped options within a single list (such as the unknown option in this example).

For each model field that has choices set, Django will add a method to retrieve the human-readable name for the field's current value: get_FOO_display().

Note that choices can be any iterable object – not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you're probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn't change much, if ever.

Unless blank=False is set on the field along with a default, then a label containing "---------" will be rendered with the select box. To override this behavior, add a tuple to choices containing None; e.g. (None, 'Your String For Display'). Alternatively, you can use an empty string instead of None where this makes sense - such as on a CharField.

db_column

The name of the database column to use for this field. If this isn't given, Django will use the field's name.

db_index

If True, django-admin sqlindexes will output a CREATE INDEX statement for this field.

db_tablespace

The name of the database tablespace to use for this field's index. The default is the project's DEFAULT_INDEX_TABLESPACE setting. If the backend doesn't support tablespaces for indexes, this option is ignored.

djangoProject docs: tablespace. PostgreSQL and Oracle support tablespaces. SQLite and MySQL don't.

wikipedia. By using tablespaces, an administrator can control the disk layout of an installation. A common use of tablespaces is to optimize performance. For example, a heavily used index can be placed on a fast SCSI disk. On the other hand, a database table which contains archived data that is rarely accessed could be stored on a less expensive but slower SATA disk.

default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

The default cannot be a mutable object (model instance, list, set, etc.), as a reference to the same instance of that object would be used as the default value in all new model instances. Instead, wrap the desired default in a callable. For example, if you had a custom JSONField and wanted to specify a dictionary as the default, use a function as follows:


def contact_default():
    return {"email": "[email protected]"}

contact_info = JSONField("ContactInfo", default=contact_default)

Note that lambdas cannot be used for field options like default because they cannot be serialized by migrations.

The default value is used when new model instances are created and a value isn't provided for the field. When the field is a primary key, the default is also used when the field is set to None.

editable

If False, the field will not be displayed in the admin or any other ModelForm. They are also skipped during model validation.

Default is True.

error_messages

The error_messages argument lets you override the default messages that the field will raise. Pass in a dictionary with keys matching the error messages you want to override.

Error message keys include: null, blank, invalid, invalid_choice, unique, and unique_for_date.

help_text

Extra "help" text to be displayed with the form widget. It's useful for documentation even if your field isn't used on a form.

Note that this value is not HTML-escaped in automatically-generated forms. This lets you include HTML in help_text if you so desire. For example:


help_text="Please use the following format: <em>YYYY-MM-DD</em>."

Alternatively you can use plain text and django.utils.html.escape() to escape any HTML special characters. Ensure that you escape any help text that may come from untrusted users to avoid a cross-site scripting attack.

primary_key

If True, this field is the primary key for the model.

If you don't specify primary_key=True for any field in your model, Django will automatically add an AutoField to hold the primary key, so you don't need to set primary_key=True on any of your fields. By default, Django gives each model the following field (topics: models):


id = models.AutoField(primary_key=True)

primary_key=True implies null=False and unique=True. Only one primary key is allowed on an object.

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one.

unique

If True, this field must be unique throughout the table.

This is enforced at the database level and by model validation. If you try to save a model with a duplicate value in a unique field, a django.db.IntegrityError will be raised.

This option is valid on all field types except ManyToManyField, OneToOneField, and FileField.

Note that when unique is True, you don't need to specify db_index, because unique implies the creation of an index.

unique_for_date

Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field.

For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn't allow the entry of two records with the same title and pub_date.

Note that if you set this to point to a DateTimeField, only the date portion of the field will be considered.

This is enforced by Model.validate_unique() during model validation but not at the database level. If any unique_for_date constraint involves fields that are not part of a ModelForm (for example, if one of the fields is listed in exclude or has editable=False), Model.validate_unique() will skip validation for that particular constraint.

unique_for_month

Like unique_for_date, but requires the field to be unique with respect to the month.

unique_for_year

Like unique_for_date and unique_for_month.

verbose_name

A human-readable name for the field. If the verbose name isn't given, Django will automatically create it using the field's attribute name, converting underscores to spaces.


# the verbose name is "person's first name":
first_name = models.CharField("person's first name", max_length=30)

# In this example, the verbose name is "first name":
first_name = models.CharField(max_length=30)

# ForeignKey, ManyToManyField and OneToOneField require the first argument to be a model class, so use the verbose_name keyword argument:

poll = models.ForeignKey(
    Poll,
    on_delete=models.CASCADE,
    verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
    Place,
    on_delete=models.CASCADE,
    verbose_name="related place",
)

The convention is not to capitalize the first letter of the verbose_name. Django will automatically capitalize the first letter where it needs to.

validators

A list of validators to run for this field. See the validators documentation for more information.

Field Types

DjangoDoc.

FileField

class FileField(upload_to=None, max_length=100, **options)[source].

FileField instances are created in your database as varchar columns with a default max length of 100 characters.

The primary_key and unique arguments are not supported, and will raise a TypeError if used.

The default form widget for this field is a ClearableFileInput.

Using a FileField or an ImageField (see below) in a model requires: in your settings file, you'll need to define MEDIA_ROOT as the full path to a directory where you'd like Django to store uploaded files, define MEDIA_URL as the base public URL of that directory. Make sure that this directory is writable by the Web server's user account.

All that will be stored in your database is a path to the file (relative to MEDIA_ROOT). The uploaded file's relative URL can be obtained using the url attribute. For example, if your ImageField is called mug_shot, you can get the absolute path to your image in a template with {{ object.mug_shot.url }}.

upload_to

The value of upload_to is passed to the Storage.save() method.

If you specify a string value, it may contain strftime() formatting, which will be replaced by the date/time of the file upload (so that uploaded files don't fill up the given directory). For example:


class MyModel(models.Model):
    # file will be uploaded to MEDIA_ROOT/uploads
    upload = models.FileField(upload_to='uploads/')
    # or...
    # file will be saved to MEDIA_ROOT/uploads/2015/01/30
    upload = models.FileField(upload_to='uploads/%Y/%m/%d/')

If you are using the default FileSystemStorage, the string value will be appended to your MEDIA_ROOT path to form the location on the local filesystem where uploaded files will be stored.

upload_to may also be a callable, such as a function. This callable must accept two arguments and return a Unix-style path (with forward slashes):


def user_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class MyModel(models.Model):
    upload = models.FileField(upload_to=user_directory_path)

Security

Somebody could upload a CGI or PHP script and execute that script by visiting its URL on your site. Don't allow that.

Also note that even an uploaded HTML file, since it can be executed by the browser, can pose security threats that are equivalent to XSS or CSRF attacks.

FieldFile

When you access a FileField on a model, you are given an instance of FieldFile as a proxy.

The API of FieldFile mirrors that of File, which is a wrapper around the result of the Storage.open() method, which may be a django.core.files.File object, or it may be a custom storage's implementation of the File API.

Note that when a model is deleted, related files are not deleted.

FilePathField

class FilePathField(path=None, match=None, recursive=False, max_length=100, **options)[source]

A CharField whose choices are limited to the filenames in a certain directory on the filesystem.

Relationships

ManyToOne

A Manufacturer makes multiple cars but each Car only has one Manufacturer:


from django.db import models

class Manufacturer(models.Model):
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)

You can also create recursive relationships (an object with a many-to-one relationship to itself).

Following relationships backward

djangoProject docs.

If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets.


b = Blog.objects.get(id=1)
b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()

# You can override the FOO_set name by setting the related_name parameter in the ForeignKey definition.
# For example, if the Entry model was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'), the above example code would look like this:

b = Blog.objects.get(id=1)
b.entries.all() # Returns all Entry objects related to Blog.

b.entries.filter(headline__contains='Lennon')
b.entries.count()

ManyToManyField

A Topping can be on multiple pizzas and each Pizza has multiple toppings:


from django.db import models

class Topping(models.Model):
    pass

class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

It's suggested, but not required, that the name of a ManyToManyField (toppings in the example above) be a plural.

It doesn't matter which model has the ManyToManyField, but you should only put it in one of the models – not both.

Generally, ManyToManyField instances should go in the object that's going to be edited on a form. In the above example, toppings is in Pizza (rather than Topping having a pizzas ManyToManyField ) because it's more natural to think about a pizza having toppings than a topping being on multiple pizzas. The way it's set up above, the Pizza form would let users select the toppings.

DjangoDoc.


class Article(models.Model):
	publications = models.ManyToManyField(Publication)

p1 = Publication(title='The Python Journal')
p1.save()
p2 = Publication(title='Science News')
p2.save()
p3 = Publication(title='Science Weekly')
p3.save()
a1 = Article(headline='Django lets you build Web apps easily')

# You can't associate a1 with a Publication until it's been saved:
a1.save()
a1.publications.add(p1)

# Create and add a Publication to an Article in one step using create():
new_publication = a1.publications.create(title='Highlights for Children')

# Article objects have access to their related Publication objects:
a1.publications.all()
# [Publication: The Python Journal]
# Publication objects have access to their related Article objects:
p2.article_set.all()
# [Article: NASA uses Python]

# First validate the model.
python manage.py validate

python manage.py sqlall APPName
python manage.py syncdb
python manage.py inspectdb

Django: Catching Integrity Error and showing a customized message using template. StackOverflow.


from django.db import IntegrityError
from django.shortcuts import render_to_response

try:
	# code that produces error
except IntegrityError as e:
	return render_to_response("template.html", {"message": e.message})

Insert with foreign key. StackOverflow.


class Mp3(models.Model):
	title=models.CharField(max_length=30)
	artist=models.ForeignKey('Artist')

class Artist(models.Model):
	name=models.CharField(max_length=100,default="Unknown")

artist = Artist.objects.get(id=1)  
newMp3 = Mp3(title="sth", artist=artist)
newMp3.save(force_insert=True)

######
# GoogleGroups.
# Use primary key directly.

class Item(models.Model):
	name = models.CharField()

class Manager(models.Model):
	item = models.ForeignKey(Item)

# TableName_id, is automatically generated column as foreignKey when creating tables.
manager = Manager(item_id=item_pk)

Extra fields on many-to-many relationships

Sometimes you may need to associate data with the relationship between two models.

For example, consider the case of an application tracking the musical groups which musicians belong to. There is a many-to-many relationship between a person and the groups, so you could use a ManyToManyField to represent this relationship. However, there is a lot of detail about the membership that you might want to collect, such as the date at which the person joined the group.

For these situations, Django allows you to specify a governor/intermediate model that will be used to govern the many-to-many relationship. You can then put extra fields on the intermediate model.

The intermediate model is associated with the ManyToManyField using the through argument to point to the model that will act as an intermediary.


from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

When you set up the intermediary model, you explicitly specify foreign keys to the models that are involved in the many-to-many relationship. This explicit declaration defines how the two models are related.

There are a few restrictions on the intermediate model:

Now that you have set up your ManyToManyField to use your intermediary model (Membership, in this case), you're ready to start creating some many-to-many relationships. You do this by creating instances of the intermediate model:


ringo = Person.objects.create(name="Ringo Starr")
paul = Person.objects.create(name="Paul McCartney")
beatles = Group.objects.create(name="The Beatles")
m1 = Membership(person=ringo, group=beatles,
    date_joined=date(1962, 8, 16),
    invite_reason="Needed a new drummer.")
m1.save()

beatles.members.all()
# <QuerySet [<Person: Ringo Starr>]>
ringo.group_set.all()
# <QuerySet [<Group: The Beatles>]>

m2 = Membership.objects.create(person=paul, group=beatles,
    date_joined=date(1960, 8, 1),
    invite_reason="Wanted to form a band.")
beatles.members.all()
# <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>

Unlike normal many-to-many fields, you can't use add(), create(), or set() to create relationships:


# THIS WILL NOT WORK
beatles.members.add(john)
# NEITHER WILL THIS
beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
beatles.members.set([john, paul, ringo, george])

Why? You can't just create a relationship between a Person and a Group - you need to specify all the detail for the relationship required by the Membership model. The simple add, create and assignment calls don't provide a way to specify this extra detail. As a result, they are disabled for many-to-many relationships that use an intermediate model. The only way to create this type of relationship is to create instances of the intermediate model.

The remove() method is disabled for similar reasons. For example, if the custom through table defined by the intermediate model does not enforce uniqueness on the (model1, model2) pair, a remove() call would not provide enough information as to which intermediate model instance should be deleted:


Membership.objects.create(person=ringo, group=beatles,
    date_joined=date(1968, 9, 4),
    invite_reason="You've been gone for a month and we miss you.")
beatles.members.all()
# <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]>
# THIS WILL NOT WORK BECAUSE IT CANNOT TELL WHICH MEMBERSHIP TO REMOVE
beatles.members.remove(ringo)

However, the clear() method can be used to remove all many-to-many relationships for an instance:


# Beatles have broken up
beatles.members.clear()
# Note that this deletes the intermediate model instances
Membership.objects.all()
# <QuerySet []>

Once you have established the many-to-many relationships by creating instances of your intermediate model, you can issue queries.


# Find all the groups with a member whose name starts with 'Paul'
Group.objects.filter(members__name__startswith='Paul')
# <QuerySet [<Group: The Beatles>]>

# As you are using an intermediate model, you can also query on its attributes:

# Find all the members of the Beatles that joined after 1 Jan 1961
Person.objects.filter(
    group__name='The Beatles',
    membership__date_joined__gt=date(1961,1,1))
# <QuerySet [<Person: Ringo Starr]>

ringos_membership = Membership.objects.get(group=beatles, person=ringo)
ringos_membership.date_joined
# datetime.date(1962, 8, 16)
ringos_membership.invite_reason
# 'Needed a new drummer.'

# Another way to access the same information is by querying the many-to-many reverse relationship from a Person object:

ringos_membership = ringo.membership_set.get(group=beatles)
ringos_membership.date_joined
# datetime.date(1962, 8, 16)
ringos_membership.invite_reason
# 'Needed a new drummer.'

OneToOne

For example, if you were building a database of "places", you would build pretty standard stuff such as address, phone number, etc. in the database. Then, if you wanted to build a database of restaurants on top of the places, instead of repeating yourself and replicating those fields in the Restaurant model, you could make Restaurant have a OneToOneField to Place (because a restaurant "is a" place; in fact, to handle this you'd typically use inheritance, which involves an implicit one-to-one relation).

Query

DjangoDocs.

We use the following model as example:


from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __str__(self):              # __unicode__ on Python 2
        return self.headline

Creating objects


from blog.models import Blog

# This performs an INSERT SQL statement
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()

# To create and save an object in a single step, use the create() method.
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
# p.save() is not needed here.

# Update record in the database:
# This performs an UPDATE SQL statement
b.name = 'New name'
b.save()

Saving ForeignKey and ManyToManyField fields

Updating a ForeignKey field works exactly the same way as saving a normal field:


from blog.models import Entry

entry = Entry.objects.get(pk=1)
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog
entry.save()

Updating a ManyToManyField:


from blog.models import Author

john = Author.objects.create(name="John")
paul = Author.objects.create(name="Paul")
george = Author.objects.create(name="George")
ringo = Author.objects.create(name="Ringo")
entry.authors.add(john, paul, george, ringo)

Retrieving objects

To retrieve objects from your database, construct a QuerySet via a Manager on your model class.

A QuerySet represents a collection of objects from your database. It can have zero, one or many filters. In SQL terms, a QuerySet equates to a SELECT statement, and a filter is a limiting clause such as WHERE or LIMIT.

You get a QuerySet by using your model's Manager. Each model has at least one Manager, and it's called objects by default.

Managers are accessible only via model classes, rather than from model instances, to enforce a separation between "table-level" operations and "record-level" operations.


# Get all objects.
all_entries = Entry.objects.all()

# Filter.
Entry.objects.filter(pub_date__year=2006)
# With the default manager class, it is the same as:
Entry.objects.all().filter(pub_date__year=2006)

# Chaining filters. The result of refining a QuerySet is itself a QuerySet.
# The following finds all entries with a headline that starts with "What", that were published between January 30, 2005, and the current day.
Entry.objects.filter(
        headline__startswith='What'
    ).exclude(
        pub_date__gte=datetime.date.today()
    ).filter(
        pub_date__gte=datetime(2005, 1, 30)
    )

# filter() will always give you a QuerySet, you can use the get() method which returns the object directly:
one_entry = Entry.objects.get(pk=1)

get() VS filter()

You can use any query expression with get(), just like with filter().

There is a difference between using get(), and using filter() with a slice of [0]:

Slicing: Limiting QuerySets


# Limit 5.
Entry.objects.all()[:5]
# OFFSET 5 LIMIT 5:
Entry.objects.all()[5:10]

# Negative indexing (i.e. Entry.objects.all()[-1]) is not supported.

# return a list of every second object of the first 10:
Entry.objects.all()[:10:2]

# Use a simple index instead of a slice:
Entry.objects.order_by('headline')[0]
# This is roughly equivalent to:
Entry.objects.order_by('headline')[0:1].get()
# The first of these will raise IndexError while the second will raise DoesNotExist if no objects match the given criteria.

# Multiple order_by, desc.
Reserved.objects.all().filter(client=client_id).order_by('-check_in', '-hehe')

Field lookups

Field lookups are how you specify the meat of an SQL WHERE clause.

Basic lookups keyword arguments take the form field__lookuptype=value (double-underscore).

How this is possible? Python has the ability to define functions that accept arbitrary name-value arguments whose names and values are evaluated at runtime (Keyword Arguments).

The field specified in a lookup has to be the name of a model field. There's one exception though, in case of a ForeignKey you can specify the field name suffixed with _id: Entry.objects.filter(blog_id=4).


Entry.objects.filter(pub_date__lte='2006-01-01')
# translates (roughly) into the following SQL:
# SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

# The database API

# exact
Entry.objects.get(headline__exact="Man bites dog")
# SELECT ... WHERE headline = 'Man bites dog';
Blog.objects.get(id__exact=14)  # Explicit form
Blog.objects.get(id=14)         # __exact is implied

# iexact
# Case insensitive.
Blog.objects.get(name__iexact="beatles blog")

# contains
Entry.objects.get(headline__contains='Lennon')
# SELECT ... WHERE headline LIKE '%Lennon%';
# Case-insensitive: icontains

# More commands:
# startswith, endswith
# istartswith, iendswith (case-insensitive)

Joins

To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.


# Retrieves all Entry objects with a Blog whose name is 'Beatles Blog':
Entry.objects.filter(blog__name='Beatles Blog')

It works backwards, too. To refer to a "reverse" relationship, just use the lowercase name of the model.


# Retrieves all Blog objects which have at least one Entry whose headline contains 'Lennon':
Blog.objects.filter(entry__headline__contains='Lennon') # entry is lowercase.

# ------ Missing

# If there was no author associated with an entry, it would be treated as if there was also no name attached, rather than raising an error:
Blog.objects.filter(entry__authors__name='Lennon')

# Return Blog objects that have an empty name on the author and also those which have an empty author on the entry.
Blog.objects.filter(entry__authors__name__isnull=True)

# If you don’t want those latter objects, you could write:
Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)

Spanning multi-valued relationships

When you are filtering an object based on a ManyToManyField or a reverse ForeignKey, there are two different sorts of filter you may be interested in. Consider the Blog/Entry relationship (Blog to Entry is a one-to-many relation).


# Select all blogs that contain entries with both "Lennon" in the headline and that were published in 2008 (AND)
Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

# Select all blogs that contain an entry with "Lennon" in the headline as well as an entry that was published in 2008 (OR)
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

The entries selected by the second filter may or may not be the same as the entries in the first filter. We are filtering the Blog items with each filter statement, not the Entry items.

The behavior of filter() for queries that span multi-value relationships, as described above, is not implemented equivalently for exclude().


# The query would exclude blogs that contain both entries with "Lennon" in the headline and entries published in 2008,
# but will not limit blogs based on entries that satisfy both conditions:
Blog.objects.exclude(
    entry__headline__contains='Lennon',
    entry__pub_date__year=2008,
)

# Select all blogs that do not contain entries published with "Lennon" that were published in 2008, you need to make two queries:
Blog.objects.exclude(
    entry=Entry.objects.filter(
        headline__contains='Lennon',
        pub_date__year=2008,
    ),
)

Related objects

When you define a relationship in a model (i.e., a ForeignKey, OneToOneField, or ManyToManyField), instances of that model will have a convenient API to access the related object(s). For example, an Entry object e can get its associated Blog object by accessing the blog attribute: e.blog. Behind the scenes, this functionality is implemented by Python descriptors.

Django also creates API accessors for the "other" side of the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().

One-to-many relationships

Forward

e = Entry.objects.get(id=2)
e.blog # Returns the related Blog object.
e.blog = some_blog
e.save()

# If a ForeignKey field has null=True set (i.e., it allows NULL values), you can assign None to remove the relation.
e = Entry.objects.get(id=2)
e.blog = None
e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Forward access to one-to-many relationships is cached the first time the related object is accessed. Subsequent accesses to the foreign key on the same object instance are cached.


e = Entry.objects.get(id=2)
print(e.blog)  # Hits the database to retrieve the associated Blog.
print(e.blog)  # Doesn't hit the database; uses cached version.

Note that the select_related() QuerySet method recursively prepopulates the cache of all one-to-many relationships ahead of time.


e = Entry.objects.select_related().get(id=2)
print(e.blog)  # Doesn't hit the database; uses cached version.
print(e.blog)  # Doesn't hit the database; uses cached version.
Backward

If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets.


b = Blog.objects.get(id=1)
b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

You can override the FOO_set name by setting the related_name parameter in the ForeignKey definition. For example, if the Entry model was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'), the above example code would look like this:


b = Blog.objects.get(id=1)
b.entries.all() # Returns all Entry objects related to Blog.

# b.entries is a Manager that returns QuerySets.
b.entries.filter(headline__contains='Lennon')
b.entries.count()
Using a custom reverse manager

By default the RelatedManager used for reverse relations is a subclass of the default manager for that model. If you would like to specify a different manager for a given query you can use the following syntax:


from django.db import models

class Entry(models.Model):
    objects = models.Manager()  # Default Manager
    entries = EntryManager()    # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()

If EntryManager performed default filtering in its get_queryset() method, that filtering would apply to the all() call.

Of course, specifying a custom reverse manager also enables you to call its custom methods: b.entry_set(manager='entries').is_published().

Additional methods to handle related objects

In addition to the QuerySet methods defined in "Retrieving objects" above, the ForeignKey Manager has additional methods used to handle the set of related objects. A synopsis of each is below, and complete details can be found in the related objects reference.

add(obj1, obj2, ...)
    Adds the specified model objects to the related object set.
create(**kwargs)
    Creates a new object, saves it and puts it in the related object set. Returns the newly created object.
remove(obj1, obj2, ...)
    Removes the specified model objects from the related object set.
clear()
    Removes all objects from the related object set.
set(objs)
    Replace the set of related objects.

To assign the members of a related set, use the set() method with an iterable of object instances or a list of primary key values.


b = Blog.objects.get(id=1)
b.entry_set.set([e1, e2])
# e1 and e2 can be full Entry instances, or integer primary key values.

If the clear() method is available, any pre-existing objects will be removed from the entry_set before all objects in the iterable (in this case, a list) are added to the set. If the clear() method is not available, all objects in the iterable will be added without removing any existing elements.

Each "reverse" operation described in this section has an immediate effect on the database. Every addition, creation and deletion is immediately and automatically saved to the database.

Many-to-many relationships

Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a "backward" one-to-many relationship, above.

The only difference is in the attribute naming: The model that defines the ManyToManyField uses the attribute name of that field itself, whereas the "reverse" model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships).


e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

Like ForeignKey, ManyToManyField can specify related_name.

One-to-one relationships

One-to-one relationships are very similar to many-to-one relationships. If you define a OneToOneField on your model, instances of that model will have access to the related object via a simple attribute of the model.


class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
    details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

The difference comes in "reverse" queries. The related model in a one-to-one relationship also has access to a Manager object, but that Manager represents a single object, rather than a collection of objects:


e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object

If no object has been assigned to this relationship, Django will raise a DoesNotExist exception.

Instances can be assigned to the reverse relationship in the same way as you would assign the forward relationship: e.entrydetail = ed.

How are the backward relationships possible?

Other object-relational mappers require you to define relationships on both sides. The Django developers believe this is a violation of the DRY (Don’t Repeat Yourself) principle, so Django only requires you to define the relationship on one end.

But how is this possible, given that a model class doesn’t know which other model classes are related to it until those other model classes are loaded?

The answer lies in the app registry. When Django starts, it imports each application listed in INSTALLED_APPS, and then the models module inside each application. Whenever a new model class is created, Django adds backward-relationships to any related models. If the related models haven’t been imported yet, Django keeps tracks of the relationships and adds them when the related models eventually are imported.

For this reason, it’s particularly important that all the models you’re using be defined in applications listed in INSTALLED_APPS. Otherwise, backwards relations may not work properly.

Queries over related objects

Queries involving related objects follow the same rules as queries involving normal value fields. When specifying the value for a query to match, you may use either an object instance itself, or the primary key value for the object.


# If you have a Blog object b with id=5, the following three queries would be identical:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly

F expression

It is used to compare the value of a model field with another field on the same model.


from django.db.models import F

# Find a list of all blog entries that have had more comments than pingbacks:
Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

# Find all the blog entries with more than twice as many comments as pingbacks:
Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

# Find all the entries where the rating of the entry is less than the sum of the pingback count and comment count
Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

# JOIN: Retrieve all the entries where the author’s name is the same as the blog name
Entry.objects.filter(authors__name=F('blog__name'))

# Find all entries that were modified more than 3 days after they were published:
from datetime import timedelta
Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

Q objects for complex lookups

Keyword argument queries in filter(), etc. are "AND"ed together. If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects (used to encapsulate a collection of keyword arguments).

Each lookup function that takes keyword-arguments (e.g. filter(), exclude(), get()) can also be passed one or more Q objects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be "AND"ed together.

If a Q object is provided, it must precede the definition of any keyword arguments


from django.db.models import Q

# Encapsulates a single LIKE query:
Q(question__startswith='What')

# "OR" of two "question__startswith" queries:
Q(question__startswith='Who') | Q(question__startswith='What')
# WHERE question LIKE 'Who%' OR question LIKE 'What%'

# a normal query and a negated (NOT) query:
Q(question__startswith='Who') | ~Q(pub_date__year=2005)

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
# roughly translates into the SQL:
# SELECT * from polls WHERE question LIKE 'Who%'
#     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

# The Q object must precede the definition of any keyword arguments
Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith='Who',
)
# INVALID QUERY
# Poll.objects.get(
#     question__startswith='Who',
#     Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
# )

The pk lookup shortcut


# If the primary key is the id field, the three statements are equivalent:
Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact

# Get blogs entries with id 1, 4 and 7
Blog.objects.filter(pk__in=[1,4,7])

# Get all blog entries with id > 14
Blog.objects.filter(pk__gt=14)

Implementation

QuerySets are lazy

QuerySets are lazy. The act of creating a QuerySet doesn't involve any database activity. You can stack filters together all day long, and Django won't actually run the query until the QuerySet is evaluated.

djangoProject: when querysets are evaluated. You can evaluate a QuerySet in the following ways:

Escaping percent signs and underscores in LIKE statements

The field lookups that equate to LIKE SQL statements (iexact, contains, icontains, startswith, istartswith, endswith and iendswith) will automatically escape the two special characters used in LIKE statements – the percent sign and the underscore.


Entry.objects.filter(headline__contains='%')
# Django takes care of the quoting for you; the resulting SQL will look something like this:
# SELECT ... WHERE headline LIKE '%\%%';

QuerySets caching

Each QuerySet contains a cache to minimize database access.

In a newly created QuerySet, the cache is empty. The first time a QuerySet is evaluated, Django saves the query results in the QuerySet’s cache and returns the results that have been explicitly requested. Subsequent evaluations of the QuerySet reuse the cached results.


queryset = Entry.objects.all()
print([p.headline for p in queryset]) # Evaluate the query set.
print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.
When QuerySets are not cached

When evaluating only part of the queryset, and if the cache is not populated before, then the query is not cached. Specifically, this means that limiting the queryset using an array slice or an index will not populate the cache.


queryset = Entry.objects.all()
# Evaluating only part of the querySet will not trigger caching
print queryset[5] # Queries the database
print queryset[5] # Queries the database again

# However if the entire queryset has already been evaluated, the cache will be checked instead:
queryset = Entry.objects.all()
[entry for entry in queryset] # Queries the database
print queryset[5] # Uses cache
print queryset[5] # Uses cache

NOTE: Simply printing the queryset will not populate the cache. This is because the call to __repr__() only returns a slice of the entire queryset.

Other

Comparing objects

Comparisons will always use the primary key, whatever it’s called.


some_entry == other_entry
# Same as
some_entry.id == other_entry.id

StackOverflow: Get the SQL from a Django QuerySet.


queryset = MyModel.objects.all()
print queryset.query
# SELECT "myapp_mymodel"."id", ... FROM "myapp_mymodel"

Set Django's time zone in settings.py.

Deleting objects

delete() method immediately deletes the object and returns the number of objects deleted and a dictionary with the number of deletions per object type.


e.delete()
# (1, {'weblog.Entry': 1})

You can also delete objects in bulk. Every QuerySet has a delete() method, which deletes all members of that QuerySet.


# deletes all Entry objects with a pub_date year of 2005:
Entry.objects.filter(pub_date__year=2005).delete()
# (5, {'webapp.Entry': 5})

Keep in mind that this will, whenever possible, be executed purely in SQL, and so the delete() methods of individual object instances will not necessarily be called during the process. If you’ve provided a custom delete() method on a model class and want to ensure that it is called, you will need to "manually" delete instances of that model (e.g., by iterating over a QuerySet and calling delete() on each object individually) rather than using the bulk delete() method of a QuerySet.

When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE – in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.


b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

This cascade behavior is customizable via the on_delete argument to the ForeignKey.

Note that delete() is the only QuerySet method that is not exposed on a Manager itself. This is a safety mechanism to prevent you from accidentally requesting Entry.objects.delete(), and deleting all the entries. If you do want to delete all the objects, then you have to explicitly request a complete query set: Entry.objects.all().delete().

Copying objects

It is possible to easily create new instance with all fields’ values copied. In the simplest case, you can just set pk to None.


blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1

blog.pk = None
blog.save() # blog.pk == 2

Things get more complicated if you use inheritance. Due to how inheritance works, you have to set both pk and id to None.


class ThemeBlog(Blog):
    theme = models.CharField(max_length=200)

django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

django_blog.pk = None
django_blog.id = None
django_blog.save() # django_blog.pk == 4

This process does not copy related objects. If you want to copy relations, you have to write a little bit more code.


entry = Entry.objects.all()[0] # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry.save()
entry.authors = old_authors # saves new many2many relations

Updating objects

The update() method is applied instantly and returns the number of rows matched by the query (which may not be equal to the number of rows updated if some rows already have the new value).

You can only set non-relation fields and ForeignKey fields using this method.


# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

b = Blog.objects.get(pk=1)
# Change every Entry so that it belongs to this Blog.
Entry.objects.all().update(blog=b)

The only restriction on the QuerySet being updated is that it can only access one database table: the model’s main table. You can filter based on related fields, but you can only update columns in the model’s main table.


b = Blog.objects.get(pk=1)

# Update all the headlines belonging to this Blog.
Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

# To increment the pingback count for every entry in the blog:
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

Be aware that the update() method is converted directly to an SQL statement. It is a bulk operation for direct updates. It doesn’t run any save() methods on your models, or emit the pre_save or post_save signals (which are a consequence of calling save()), or honor the auto_now field option.

If you want to save every item in a QuerySet and make sure that the save() method is called on each instance, you don’t need any special function to handle that. Just loop over them and call save():


for item in my_queryset:
    item.save()

Unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldError will be raised:


# THIS WILL RAISE A FieldError
Entry.objects.update(headline=F('blog__name'))

General

Meta

Give your model metadata by using an inner class Meta:


from django.db import models

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

Model metadata is "anything that's not a field", such as ordering options (ordering), database table name (db_table), or human-readable singular and plural names (verbose_name and verbose_name_plural). None are required, and adding class Meta to a model is completely optional.

DjangoProject.


class aModel(models.Model):
	class Meta:

		abstract = True # this model will be an abstract base class.

		app_label = 'myapp' # Model exists outside of the standard locations, such as other apps. Deprecated.

		db_table = 'tableName' # Use the specified table name instead of the auto-generated "APPName_ClassName".
		# It is strongly advised that you use lowercase table names when you override the table name via db_table, particularly if you are using the MySQL backend.
		# Because, By default, with a UTF-8 database, MySQL will use the utf8_general_ci collation. This results in all string equality comparisons being done in a case-insensitive manner. That is, "Fred" and "freD" are considered equal at the database level. MySQLNotes.

		get_latest_by = "order_date"
		# The name of an orderable field in the model, typically a DateField, DateTimeField, or IntegerField. This specifies the default field to use in your model Manager's latest() and earliest() methods.

		managed = True
		# Defaults to True, meaning Django will create the appropriate database tables in migrate or as part of migrations and remove them as part of a flush management command. That is, Django manages the database tables' lifecycles.
		# If False, no database table creation or deletion operations will be performed for this model. This is the only difference.

		order_with_respect_to = 'question'
		# Makes this object orderable with respect to the given field, usually a ForeignKey.

		ordering = ['-pub_date', 'author']
		# a tuple or list of strings. Each string is a field name with an optional "-" prefix, which indicates descending order. Fields without a leading "-" will be ordered ascending.
		# Use the string "?" to order randomly.
		# Warning: Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database. Each foreign key you add will implicitly include all of its default orderings as well.

		permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
		# This is a list or tuple of 2-tuples in the format (permission_code, human_readable_permission_name).

		default_permissions = ('add', 'change', 'delete')
		# The previous is default.
		# It must be specified on the model before the model is created by migrate in order to prevent any omitted permissions from being created.

		proxy = True
		# a model which subclasses another model will be treated as a proxy model.

		unique_together = (("driver", "restaurant"),)
		# Sets of field names that, taken together, must be unique.

		index_together = [
			["pub_date", "deadline"],
		]
		# Sets of field names that, taken together, are indexed.

		verbose_name = "pizza"
		# If this isn't given, Django will use a munged version of the class name: CamelCase becomes camel case.
		verbose_name_plural = "stories"
		# If this isn't given, Django will use verbose_name + "s".

Database is created in other apps, or unmaged tables

StackOverflow.


from django.db import models
class Poll(models.Model):
	question = models.CharField(max_length=200)
	pub_date = models.DateTimeField('date published')
	class Meta:
		app_label = 'test'

# Loot at site-packages\django\db\models\base.py:
if getattr(meta, 'app_label', None) is None:
	# Figure out the app_label/appName by looking one level up.
	# For 'django.contrib.sites.models', this would be 'sites'.
	model_module = sys.modules[new_class.__module__]
	kwargs = {"app_label": model_module.__name__.split('.')[-2]}
else:
	kwargs = {}

Where there is "list index out of range" error from django/db/models/base.py, it may be caused by using a database not managed by current app. Add the "app_label" and set "managed" to False, see previous. NOTE: in Django 1.7: app_label is no longer required.

Model attributes

objects

The most important attribute of a model is the Manager. It's the interface through which database query operations are provided to Django models and is used to retrieve the instances from the database.

If no custom Manager is defined, the default name is objects.

Managers are only accessible via model classes, not the model instances.

Models across files

It's perfectly OK to relate a model to one from another app.


from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
    zip_code = models.ForeignKey(
        ZipCode,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )

Organizing models in a package

The manage.py startapp command creates an application structure that includes a models.py file. If you have many models, organizing them in separate files may be useful.

To do so, create a models package: Remove models.py and create a myapp/models/ directory with an __init__.py file and the files to store your models. You must import the models in the __init__.py file.

For example, if you had organic.py and synthetic.py in the models directory:


myapp/models/__init__.py

from .organic import Person
from .synthetic import Robot

Explicitly importing each model rather than using from .models import * has the advantages of not cluttering the namespace, making code more readable, and keeping code analysis tools useful.