Understanding Django Models: A Beginner’s Guide
This beginner-friendly article introduces Django models and explains how they define the structure and behavior of application data. It covers model classes, fields, field options, primary keys, relationships, methods, metadata, migrations, ORM operations, and Django admin registration. By the end, developers new to Django will understand how models connect Python code to database tables and form the foundation of a Django application.
Understanding Django Models: A Beginner’s Guide
Django models define the structure of an application’s data. They provide a Python-based interface for creating database tables, storing records, defining relationships, and retrieving information.
Instead of writing SQL for every database operation, developers work with Python classes and objects. Django’s object-relational mapper, commonly called the ORM, translates those operations into database queries.
What Is a Django Model?
A Django model is a Python class that represents a type of data in an application. In most cases:
- A model class corresponds to a database table.
- A model field corresponds to a table column.
- A model instance corresponds to a row in that table.
Every standard Django model inherits from django.db.models.Model.
For example, a book-tracking application might need to store books:
⧉
1 2 3 4 5 6 7 8 | |
The Book class describes the structure of the data. Django can use it to create a database table containing columns for the title, author, publication date, and page count.
The Basic Structure of a Model
A model definition usually contains four types of elements:
- Fields
- Field options
- Metadata
- Methods
A more complete model might look like this:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
The fields define what data is stored. The inner Meta class configures model-level behavior. The str() method controls the readable text used to represent each object.
Model Fields
Fields are the main building blocks of a model. Each field is an instance of a Django field class, such as CharField, IntegerField, or DateField.
Fields can then be declared using expressions such as models.CharField() and models.DateField()
The most commonly used fields include:
CharField
Stores short or moderately sized text:
⧉
1 | |
A CharField requires a max_length value. Django uses this value for database definitions and validation.
TextField
Stores longer text without a small fixed length:
⧉
1 | |
This is useful for articles, notes, product descriptions, and other long-form content.
IntegerField
Stores whole numbers:
⧉
1 | |
For values that should not be negative, PositiveIntegerField may communicate the intention more clearly:
⧉
1 | |
DecimalField
Stores fixed-precision decimal values:
⧉
1 | |
This example allows up to eight digits in total, with two digits after the decimal point. It is generally more suitable than floating-point storage for monetary values.
BooleanField
Stores True or False:
⧉
1 | |
DateField and DateTimeField
Store dates and timestamps:
⧉
1 2 3 | |
auto_now_add=True sets a value when an object is first created. auto_now=True updates the value whenever the object is saved.
EmailField
Stores and validates an email address:
⧉
1 | |
URLField
Stores and validates a URL:
⧉
1 | |
Field Options
Field options change how fields are stored, validated, and presented.
default
Provides a value when none is supplied:
⧉
1 | |
Defaults can also be callable:
⧉
1 2 3 | |
The function itself is passed as the default. It is not called in the field declaration.
null
Controls whether the database may store SQL NULL:
⧉
1 | |
The default is False.
Django generally recommends avoiding null=True for string fields such as CharField and TextField, because doing so creates two possible representations of missing text: NULL and an empty string.
blank
Controls whether a value may be omitted during form and model validation:
⧉
1 | |
null and blank are related but different:
- null affects database storage.
- blank affects validation.
For an optional date field, both may be appropriate:
⧉
1 | |
For optional text, blank=True is commonly sufficient:
⧉
1 | |
unique
Requires every stored value to be distinct:
⧉
1 | |
The database will reject two books with the same ISBN.
choices
Restricts a field to a defined set of values:
⧉
1 2 3 4 5 6 7 8 9 10 11 | |
The database stores the compact value, such as "PB", while interfaces can display the human-readable label, such as "Paperback".
help_text
Adds explanatory text that can be displayed in forms and the Django administration interface:
⧉
1 2 3 4 | |
Primary Keys
Every database table needs a primary key that uniquely identifies each row.
When a model does not explicitly define one, Django automatically adds a primary-key field. Therefore, a basic model can be written without manually creating an id field.
Conceptually, Django adds something similar to:
⧉
1 | |
A model instance can access its primary key through either id or the more general pk attribute:
book.id book.pk
Using pk can make code more flexible because it works even when a model uses a custom primary key.
Relationships Between Models
Relational databases become especially useful when tables can refer to one another. Django provides three major relationship fields.
Many-to-One Relationships
A ForeignKey creates a many-to-one relationship.
Suppose each book belongs to one publisher, while a publisher can release many books:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Each Book points to one Publisher.
The on_delete argument tells Django what should happen when the referenced publisher is deleted. With models.CASCADE, deleting a publisher also deletes its associated books.
Other deletion behaviors include:
- models.PROTECT
- models.RESTRICT
- models.SET_NULL
- models.SET_DEFAULT
- models.DO_NOTHING
The correct option depends on the application’s data-integrity requirements.
One-to-One Relationships
A OneToOneField connects one record to exactly one other record:
⧉
1 2 3 4 5 6 7 8 9 10 | |
Many-to-Many Relationships
A ManyToManyField represents a relationship in which objects on both sides may be associated with multiple objects.
A book may have several categories, and each category may contain several books:
⧉
1 2 3 4 5 6 7 | |
Django creates an intermediate database table to store these associations.
The field can also be optional:
⧉
1 | |
This structure may be useful when optional or specialized information should be stored separately from the main model.
Model Methods
Models can contain methods that implement behavior related to their data.
The str() Method
The most common beginner-level method is str():
⧉
1 2 | |
Without it, Django may display an object using an unhelpful representation such as:
Book object (1)
With str(), the same object may appear as:
ByteStaq - Django ORM introduction
This improves readability in the Django admin, shell, forms, and debugging output.
Custom Methods
A model can also contain domain-specific methods:
⧉
1 2 3 4 5 6 | |
And use it just like any ordinary method:
⧉
1 | |
Methods should generally describe behavior that naturally belongs to the model.
The Meta Class
An optional inner class named Meta configures model-level behavior.
⧉
1 2 3 4 5 6 7 8 | |
Common Meta options include:
- ordering: Defines the default query ordering; can use a minus sign for descending order: ["-title"].
- verbose_name: Sets the singular human-readable name.
- verbose_name_plural: Sets the plural name.
- db_table: Overrides the generated database table name.
- indexes: Defines database indexes.
- constraints: Defines database-level rules.
Creating Database Tables with Migrations
Writing a model does not immediately modify the database. Django uses migrations to track and apply schema changes.
After creating or changing a model, run:
⧉
1 | |
This creates a migration file describing the changes.
Then run:
⧉
1 | |
This applies pending migrations to the configured database.
The typical workflow is therefore:
- Edit models.py.
- Run makemigrations.
- Review the generated migration.
- Run migrate.
Migration files should normally be committed to version control because they form part of the application’s database history.
We have a full article covering migrate and makemigrations: Understanding migrate and makemigrations
Creating and Retrieving Model Objects
After the database tables exist, model objects can be managed through Django’s ORM.
Create an object:
⧉
1 2 3 4 5 6 | |
Retrieve all books:
⧉
1 | |
Retrieve one book:
⧉
1 | |
Filter objects:
⧉
1 | |
Update an object:
⧉
1 2 | |
Delete an object:
⧉
1 | |
The objects attribute is the model’s default manager. It provides the main interface for constructing database queries.
Registering a Model in the Django Admin
A model can be made available in Django’s administration interface by registering it in the application’s admin.py file:
⧉
1 2 3 4 5 6 | |
After registration, authorized users can create, update, and delete book records through the admin interface.
Instead of using a simple registration with the admin console, admin configurations can be customized.
A customized admin configuration might look like this:
⧉
1 2 3 4 5 | |
Among other things, this let's the user specify hiw the model is displayed inside the admin panel.
A Complete Example
The following example combines several basic model concepts:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
This example defines:
- Basic text, date, number, and Boolean fields
- Required and optional values
- Unique constraints
- A many-to-one publisher relationship
- A many-to-many category relationship
- Reverse relationship names
- Default ordering
- Human-readable object representations
Beginner Mistakes
- One common mistake is changing a model without creating and applying migrations. Model code and database structure must remain synchronized.
- Another is confusing null=True with blank=True. Remember that null concerns database storage, while blank concerns validation.
- Developers should also avoid storing related information as plain text when it represents a real entity. For example, a Publisher model and ForeignKey are usually preferable to repeatedly storing publisher names in a CharField.
- Finally, model methods should contain data-related behavior rather than view or presentation logic. Models describe the application’s data and the rules surrounding that data.
Django models provide a structured way to describe application data using Python. A model class defines fields, validation rules, relationships, metadata, and data-related behavior. Django then uses that definition to generate database structures and provide a high-level query interface.
For developers new to Django, the most important concepts are:
- Models are Python classes that inherit from models.Model.
- Fields define the data stored for each object.
- Field options control validation and database behavior.
- Relationship fields connect different models.
- Migrations synchronize model definitions with the database.
- Model instances can be created, queried, updated, and deleted through the ORM.
Join the Newsletter
Practical insights on Django, backend systems, deployment, architecture, and real-world development — delivered without noise.
Get updates when new guides, learning paths, cheat sheets, and field notes are published.
No spam. Unsubscribe anytime.
There is no third-party involved so don't worry - we won't share your details with anyone.