Skip to content

Fields and Relationships

A field in Django represents a column in a database table. Fields are the only mandatory part of a model and each field is defined as a class attribute on a model. It is important to avoid field names that conflict with the Model API, such as clean, save, or delete.

python
class Book(models.Model):
    title = models.CharField(max_length=200)
    published_date = models.DateField()

Here title and published_date are fields.

Field Types

Each field in your model should be an instance of the appropriate Field class. Django uses these field class types to determine the database column type, the default HTML widget for forms, and minimal validation requirements.

Numeric Fields

These fields store numbers, including integers, decimals, and floating-point values.

Field TypeDescription
AutoFieldAn IntegerField that automatically increments. Used for auto-created primary keys.
BigAutoFieldA 64-bit integer, similar to AutoField, but guarantees a larger range (1 to 9 quintillion).
SmallAutoFieldLike AutoField, but limits values to a smaller range (1 to 32,767).
IntegerFieldA standard integer. Safe for values from -2,147,483,648 to 2,147,483,647.
BigIntegerFieldA 64-bit integer guaranteed to fit much larger numbers than IntegerField.
SmallIntegerFieldLike IntegerField, but for smaller values (usually -32,768 to 32,767).
PositiveIntegerFieldLike IntegerField, but must be positive or zero.
PositiveBigIntegerFieldLike BigIntegerField, but must be positive or zero.
PositiveSmallIntegerFieldLike SmallIntegerField, but must be positive or zero.
DecimalFieldA fixed-precision decimal number. Requires max_digits and decimal_places.
FloatFieldA floating-point number represented in Python by a float instance.

String & Text Fields

These fields handle text data, ranging from short strings and identifiers to large blocks of text.

Field TypeDescription
CharFieldA string field for small- to large-sized strings. Requires max_length.
TextFieldA large text field for unlimited text.
SlugFieldA short label containing only letters, numbers, underscores, and hyphens. Useful for creating readable, SEO-friendly URLs.
EmailFieldA CharField that validates that the value is a valid email address.
URLFieldA CharField that validates that the value is a valid URL.
UUIDFieldA field for universally unique identifiers. Uses Python's UUID class.
GenericIPAddressFieldAn IPv4 or IPv6 address in string format (Ex: 192.0.2.30).
FilePathFieldA CharField restricted to filenames in a specific directory.

Date & Time Fields

These fields store temporal data, such as calendar dates, specific times, or durations.

Field TypeDescription
DateFieldA date, represented in Python by a datetime.date instance.
TimeFieldA time, represented in Python by a datetime.time instance.
DateTimeFieldA specific date and time, represented by a datetime.datetime instance.
DurationFieldA period of time, modeled in Python by datetime.timedelta.

File & Binary Fields

These fields manage file uploads and raw binary data.

Field TypeDescription
FileFieldA file-upload field. Requires upload_to to specify the storage directory.
ImageFieldInherits from FileField but validates that the uploaded file is an image.
BinaryFieldStores raw binary data. Can be assigned bytes, bytearray, or memoryview.

FileField vs FieldFile

FileField is a model field used to define a file column in the database. It handles file uploads and stores the file path in the database.

python
document = models.FileField(upload_to="documents/")

FieldFile is the File object that you interact with when you access the field on a specific record (instance) of your model. It represents the actual file and provides methods and attributes to work with it.

python
instance.document.name
instance.document.url
instance.document.size
instance.document.open()

In short, FileField defines the field on the model class, while FieldFile is the file object accessed on a model instance.

Miscellaneous Fields

These fields cover specific data types like booleans, structured JSON, and composite keys.

Field TypeDescription
BooleanFieldA true/false field.
JSONFieldStores JSON-encoded data. Represented in Python as native dicts or lists.
GeneratedFieldA field that is always computed by the database based on other fields in the model. Requires an expression and an output_field.
CompositePrimaryKeyA virtual field for defining a composite primary key (a key made of multiple fields).

For detailed information on all field types, refer to the official doc.

Field Options

Django fields support several optional arguments to customize their behavior. The most commonly used options are:

OptionDescription
nullIf True, Django will store empty values as NULL in the database. Default is False. (Note: Avoid using this on string-based fields like CharField unless unique=True is also set).
blankIf True, the field is allowed to be blank during form validation. Default is False. This is different from null (which is database-related); blank is validation-related.
choicesA sequence (list or tuple) of 2-tuples to use as choices for this field. If provided, the default form widget becomes a select box instead of a text field.
defaultThe default value for the field. This can be a value or a callable object. If it is a callable, it will be called every time a new object is created.
primary_keyIf True, this field is the primary key for the model.
uniqueIf True, this field must be unique throughout the table. Enforced at the database level and by model validation.
verbose_nameA human-readable name for the field. If not given, Django will automatically create one using the field's attribute name (converting underscores to spaces).
help_textExtra "help" text to be displayed with the form widget. Useful for documentation.
editableIf False, the field will not be displayed in the admin or any form and is skipped during model validation. Default is True.
db_indexIf True, a database index will be created for this field.
validatorsA list of validator functions (callables) to run for this field.

For a complete list of all available field options, refer to the official doc.

Relationship Options

There are also specific options available for relationship fields (ForeignKey, ManyToManyField, OneToOneField).

OptionApplicable ToDescription
on_deleteForeignKey, OneToOneFieldRequired. Defines what happens when the related object is deleted (e.g. CASCADE, PROTECT, SET_NULL (requires null=True)).
related_nameAll relationshipsName used to access related objects as an attribute on the related model (e.g. author.books.all()). Defaults to [model_name]_set.
related_query_nameAll relationshipsName used for reverse lookups in queryset filters (e.g. Tag.objects.filter(article__title="News")). Defaults to [related_name] or [model_name].
symmetricalManyToManyFieldUsed only with self. If True (default), the relationship is mutual; if False, it is one-way.
throughManyToManyFieldSpecifies a custom intermediate model for the relationship.
limit_choices_toAll relationshipsLimits selectable related objects using a filter (dict or Q).
to_fieldForeignKeySpecifies which field on the related model is referenced (defaults to the primary key).

Relationships

Django offers robust support for the three most common types of database relationships.

Many-to-One

You define a many-to-one relationship using ForeignKey. This field requires a positional argument specifying the model class to which it relates. For example, if a Car model has a Manufacturer, you would add a ForeignKey to the Manufacturer model inside the Car model.

Many-to-Many

You define a many-to-many relationship using ManyToManyField. This also requires the related model class as a positional argument. It does not matter which model contains the field, but it should only appear in one of them.

Standard Use

For simple links where no extra data is needed (Ex: a Person is a member of multiple Groups), Django automatically manages the hidden table connecting the two models.

Extra Data (The through Argument)

If you need to store data about the relationship itself, such as the date a person joined a group or the reason for an invite, you must use an intermediate model. You specify this model using the through argument.

python
from django.db import models

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

class Group(models.Model):
    name = models.CharField(max_length=128)
    # The 'through' argument points to the intermediate model
    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)

    # Extra fields stored on the relationship
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

If you need to associate extra data with the relationship, such as the date a person joined a group, you can specify an intermediate model using the through argument. This intermediate model can hold foreign keys to the related models and any additional fields you need.

One-to-One

You define a one-to-one relationship using OneToOneField. This is useful when an object effectively extends another. For instance, a Restaurant model might have a one-to-one relationship with a Place model. This field works similarly to ForeignKey but ensures that the link is unique.

Lazy Relationships

When defining relationships, you might encounter a situation where the model you want to link to has not been defined yet. This often happens if the related model is defined lower in the same file or if you have a circular dependency between two apps.

To solve this, Django allows you to refer to a model by its name as a string rather than the class object itself.

There are three types of lazy references:

  • Recursive: Used when a model has a relationship to itself, like an "Employee" having a "Manager" who is also an Employee.
  • Relative: Used when the related model is in the same models.py file (or app context).
  • Absolute: Used when the related model is in a different app. This is the most specific and robust format.

Recursive Relationship (Self)

If an object needs to relate to another object of the same class, use self:

python
class Employee(models.Model):
    name = models.CharField(max_length=100)
    # 'self' refers to the Employee class itself
    manager = models.ForeignKey('self', on_delete=models.SET_NULL, null=True)

Order of Definition (Same App)

Python reads code top-to-bottom. If you define Parent before Child, Python raises a NameError because Child does not exist yet. Using 'Child' as a string tells Django to look for it later.

python
class Parent(models.Model):
    name = models.CharField(max_length=50)
    # Using 'Child' as a string avoids a NameError
    favorite_child = models.ForeignKey('Child', on_delete=models.SET_NULL) 

class Child(models.Model):
    name = models.CharField(max_length=50)

This also applies to circular dependencies within the same file, where one model must be defined later. Lazy relationships resolve this ordering issue.

Circular Imports (Different Apps)

This happens when two different apps depend on each other (Ex: User needs Product and Product needs User). Standard imports create an infinite loop that crashes the application. Using a string path avoids the import entirely.

python
# In products/models.py
class Product(models.Model):
    # Syntax: 'app_label.ModelName'
    # No need to import User at the top of the file!
    created_by = models.ForeignKey('users.User', on_delete=models.CASCADE)

When you define a relationship (like a ForeignKey), Django automatically creates a "Reverse Relation" on the related model. This “related manager” is used in a one-to-many or many-to-many related context. This allows you to access data from the other side of the relationship.

By default, Django creates an attribute on the related model using the lowercased model name followed by _set.

If a Book model has a ForeignKey to Author:

  • Forward: book.author gives you the Author object.
  • Reverse: author.book_set gives you a "Manager" to access all books by that author.

Field Attributes

Field attributes are API properties available on a field instance. They are primarily used for introspection, allowing you to inspect the properties of a model field programmatically, rather than for defining the field itself.

AttributeDescription
auto_createdTrue if the field was automatically created by Django (like the default id primary key), rather than explicitly defined in your model.
concreteTrue if the field maps to a physical column in the database table. Returns False for fields like many-to-many or reverse relationships, which do not have their own column on the model's table.
hiddenTrue if the field is used internally by Django and should not be displayed in forms (Ex: the content_type field in a generic relationship).
is_relationTrue if the field establishes a relationship with another model (Ex: ForeignKey, ManyToManyField, OneToOneField).
modelReturns the model class where this field is defined.
related_modelReturns the model class that this field links to. For example, in ForeignKey(Author, ...), this returns the Author class.
many_to_manyTrue if the field represents a many-to-many relationship.
many_to_oneTrue if the field represents a many-to-one relationship (Ex: a standard ForeignKey).
one_to_manyTrue if the field represents a one-to-many relationship (Ex: the reverse side of a ForeignKey).
one_to_oneTrue if the field represents a one-to-one relationship (OneToOneField).