How Django Models Work — A Beginner’s Guide
Everything You Need to Know About Django Models
One of the most important parts of Django is its object-relational mapper (ORM), which allows you to define models that map to database tables.
In this comprehensive guide, we’ll cover everything you need to know about Django models, including:
- What are models and why are they useful?
- How to define models
- Model fields and field options
- Relationships between models
- Querying models
- Model forms
- Model validation
- Model methods
- Model managers
- Model metadata
- Migrations
What are Django Models and Why Are They Useful?
Django models are Python classes that represent tables in your database. They allow you to query and interact with your data without having to write raw SQL queries.
Here are some of the key benefits of using Django models:
- Abstraction of your database: Django models provide a simple, Pythonic way to interact with your databases without needing to worry about the underlying database engine. The ORM handles translating your Python code to the appropriate SQL queries.
- Data validation: Models make it easy to enforce data validation and integrity at the application level rather than relying solely on the database level.
- Built-in admin interface: Django comes with a highly customizable admin interface built on top of your models. This allows easy CRUD (create, retrieve, update, delete) operations on your data.
- Version control and migrations: Django migrations allow you to use version control on your models and database schema. As you change your models, Django can automatically generate and run the necessary migrations to update your database.
Overall, Django models make your code cleaner, easier to maintain, and more Pythonic. Defining models for your data is one of the most useful things you can do in a Django project.
How to Define Django Models
Defining models in Django is easy. Models are regular Python classes that subclass django.db.models.Model. Each model maps to a single database table.
Here’s a simple example of a Django model:
from Django.db import models
class Article(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey('Author', on_delete=models.CASCADE)
text = models.TextField()
def __str__(self):
return self. title
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __str__(self):
return self. nameTo create the database tables for your models, run python manage.py migrate. This will create Article and Author tables in your database that match the model definitions.
Some key things to note:
- Each model subclasses
django.db.models.Model - Each field is defined as a class attribute using a Field class like
CharFieldorTextField authorfield uses aForeignKeyto define a many-to-one relationship with theAuthormodel- The
__str__methods define a human-readable representation of the model
This covers the basics of model definition. Next, we’ll go over the various field types and options.
Django Model Fields
The model fields define the types of data that can be stored in each column of the database table. Django has numerous built-in field types for common data types like text, numbers, dates, and relationships between models.
Some commonly used Django model field types include:
CharField- Limited-length textTextField- Unlimited textIntegerField- Integer numberDateField- DateEmailField- Email addressForeignKey- Relationship to another model
For example:
from Django.db import models
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
n_comments = models.IntegerField()
content = models.TextField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)Each field type has options like max_length and on_delete that control their behavior. The Django model field reference lists all available field types and options.
Some key things to keep in mind:
- Be thoughtful about max lengths for
CharFieldandTextField. This helps limit the size of your database. - Use
null=True, blank=Trueto allow empty values for a field. - Use
choicesto limit values to a predefined set of options. - Set
defaultvalues for fields like status flags. - Use
unique=Trueto prevent duplicate values.
Next, we’ll talk about relationships between models.
Django Model Relationships
Relating models to each other allows you to define foreign keys, one-to-one, one-to-many, and many-to-many relationships.
The main types of model relationships are:
- ForeignKey — One-to-many relationship. Example: A blog post has one author but an author can have multiple posts. Defines a
author_idfield on the post. - OneToOneField — One-to-one relationship. Example: A user profile has one user and each user has one profile. Defines a
user_idfield on the profile model. - ManyToManyField — Many-to-many relationship. Example: A pizza has many toppings and each topping can be on multiple pizzas. Defines an intermediary join table.
For example:
class Author(models.Model):
name = models.CharField(max_length=50)
class Article(models.Model):
headline = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
class Topping(models.Model):
name = models.CharField(max_length=50)
class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)The author’s foreign key creates a one-to-many relationship between Author and Article. The many-to-many field creates an intermediary Pizza_toppings join table.
Some things to note:
- ForeignKey is defined on the “many” side of the relationship.
- on_delete controls what happens when a related object is deleted.
- Related objects can be accessed via
.authorand.article_set. - ManyToManyField requires a join table, and no on_delete.
Querying Django Models
Once you’ve defined your models, Django makes it easy to query and retrieve your data. You can query models using the powerful Django ORM.
Some examples:
# Get all articles
articles = Article.objects.all()
# Filter by headline
post = Article.objects.get(headline='Hello World')
# Filter by foreign key
posts = Article.objects.filter(author=some_author)
# Order articles by pub date
articles = Article.objects.order_by('-pub_date')
# Get related objects
author = post.author
posts = author.article_set.all()You can chain filters, orders, and other operations to build complex queries.
Some key query methods include:
all()- Retrieve all objectsget()- Retrieve a single objectfilter()- Filter objects based on criteriaexclude()- Filter out objectsorder_by()- Order objects by fieldcount()- Return number of objectsexists()- Check if objects existselect_related()- Eager load related objects
The Django ORM handles translating the Python code into efficient SQL queries. This prevents you from having to write raw SQL in most cases.
Django Model Forms
Django includes helpful tools for generating forms from models. This includes model-based Form classes that understand your models and handle validation for you.
For example:
from Django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['headline', 'content', 'author']This creates a ModelForm with the specified fields from the Article model. Django will handle generating the form HTML and validating data based on the model definition.
Some key things ModelForms provide:
- Automatic generation of fields based on the model
- Data validation based on model field types and constraints
- Conversion of data to appropriate Python types
- HTML rendering with Bootstrap styles by default
- Built-in CSRF protection
Model forms make it easy to reuse your models for creating and editing data through forms, like in the Django admin.
Django Model Validation
Django models provide numerous ways to validate your data and keep it clean and consistent.
Some built-in model validation features include:
- Field constraints like
max_lengthandunique - Field options like
blank,null,choices,default - Validator functions to check values meet custom criteria
- Model clean() method to validate fields together
- Permissions to control who can create, view, change, and delete
For example:
from django.core.validators import MinLengthValidator
class Article(models.Model):
headline = models.CharField(max_length=200, unique=True)
content = models.TextField(validators=[MinLengthValidator(10)])
def clean(self):
# Validate headline and content together
class Meta:
permissions = [('edit_post', 'Can edit post')]This enforces max length, uniqueness, min length, and custom permissions.
Other tips for model validation:
- Reuse Django’s built-in validators like
MaxLengthValidator - Raise
ValidationErrorin clean methods or validators - Use model-level
permissionsfor CRUD security - Leverage
FormSetandModelFormvalidation
Proper validation helps prevent bugs and bad data in your application.
Django Model Methods
In addition to built-in model functionality, you can define custom methods on your models. These instance methods allow you to encapsulate model logic and can be called like instance.method().
Some examples of custom model methods:
class Article(models.Model):
...
def excerpt(self, length=100):
return self.content[:length]
def time_since_published(self):
return datetime.now() - self.pub_date
def approved_comments(self):
return self.comment_set.filter(approved=True)These custom methods allow encapsulating logic like:
- Formatting or aggregating fields
- Computed properties based on models
- Retrieving and filtering related objects
- Common operations around the model
Some tips for model methods:
- Use descriptive method names like
.time_since_published() - Keep methods lightweight. Avoid complex logic.
- Document methods with docstrings
- Name clashing methods like
.approved_comments()instead of just.comments()
Methods help make your models more useful and your code more readable.
Django Model Managers
Managers are classes that handle model database queries. Django automatically creates an objects manager for every model.
You can define custom managers with extra methods for querying your data.
For example:
class ArticleManager(models.Manager):
def latest(self):
return self.order_by('-pub_date')[:5]
class Article(models.Model):
...
objects = ArticleManager()Now you can query Article.objects.latest() to get the latest articles.
Some common uses for custom managers:
- Custom queries like the latest, most popular, related objects
- Query scopes that filter or annotate objects, like
published() - Multiple managers for different queries, like
articles.drafts.all()
Tips for managers:
- Make manager names clear like
PublishedArticleManager - Put reusable queries into managers instead of models
- Annotate and prefetch related objects to avoid extra queries
- Use
_querysetmethods to modify query sets
Managers help encapsulate query logic and performance optimization.
Django Model Metadata
Django stores helpful metadata on models that allow introspecting model properties and relationships.
Some key attributes of models include:
Model.objects- default model managerModel._meta- metadata attributeModel._meta.fields- list of fieldsModel._meta.db_table- database table nameField.attname- database column name
You can access these directly or through the Django API:
# Direct
article._meta.get_field('headline').max_length
# Django API
from django.db import models
models.Field.get_attname(Article._meta.get_field('headline'))This metadata can be useful for things like:
- Inspecting models for schema introspection
- Looping through fields dynamically
- Building SQL queries programmatically
- Serialization and deserialization -Dynamic and generic model operations
Some key points:
_metaprovides a rich model API. Explore it!- Cache
_metalookups instead of repetitive access - Avoid modifying
_metaproperties directly
Model metadata enables the dynamic use of Django models.
Django Migrations
Migrations provide a way to incrementally update your database schema while keeping a history of changes. Migrations solve the problem of schema and data changing over time in production.
Key features of migrations:
- Migrations are generated from model changes
- Rollback to previous migrations is supported
- Database schema and data are updated transactionally
- Migrations can alter data to match new schema
- Each migration has an ID allowing dependency tracking
To use migrations:
- Install the Django migrations app
- Run
makemigrationswhen models change - Review auto-generated migration for errors
- Run
migrateto apply migrations to the database
Whenever you change your models:
- Generate migration with
makemigrations - Review migration code for problems
- Add any required data migrations
- Migrate the database to apply changes
Some best practices:
- Commit migrations under version control
- Deploy migrations along with app code changes
- Try migration on a copy of production data first
- Limit migration size and complexity
Migrations allow evolving production database schema over time.
Recap
That covers the key things you need to know about Django models! Here’s a quick recap:
- Models represent database tables and provide validation and querying capabilities.
- Fields map to table columns and define validation rules and constraints.
- Relationships like ForeignKey express database relationships and links between models.
- The ORM allows querying and retrieving model data without raw SQL.
- ModelForms create forms and handle validation based on models.
- Custom methods add helper functions and computed values to models.
- Managers encapsulate custom model querying capabilities.
- Model metadata enables introspection and dynamic use.
- Migrations incrementally update the database schema over time.
Django’s model layer is one of its most powerful features. Mastering models will take your Django skills to the next level.
I hope this guide provides a comprehensive overview of how to leverage models to build robust and maintainable Django web applications!



