Table of Contents
Django Models and ORM (Object-Relational Mapping) system. Based on the official Django documentation, this content is organized in a logical sequence, starting from basics and progressing to advanced topics. It includes explanations, code examples, and best practices to help you understand and implement Django’s ORM effectively.
Django’s ORM is a powerful abstraction layer that allows you to interact with your database using Python code instead of raw SQL. It maps Python classes (models) to database tables, objects to rows, and attributes to columns. This enables you to create, retrieve, update, and delete (CRUD) database records without writing SQL queries in most cases.
Key benefits:
- Database-agnostic: Works with PostgreSQL, MySQL, SQLite, Oracle, and more.
- Security: Automatically escapes inputs to prevent SQL injection.
- Productivity: Handles complex queries, relationships, and migrations.
To use the ORM, define models in your app’s models.py file, then use the objects manager to query the database.
Example setup in settings.py:
python
INSTALLED_APPS = [
# ...
'myapp',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase',
}
}
Defining Models
Models are Python classes that subclass django.db.models.Model. Each model represents a database table, and its attributes define the fields (columns).
Basic structure:
python
from django.db import models
class MyModel(models.Model):
# Fields go here
pass
When you define a model, Django automatically adds an id primary key field unless specified otherwise. After defining models, run python manage.py makemigrations and python manage.py migrate to create the table in the database.
Model Fields
Fields define the data types and constraints for your model’s attributes. Django provides a wide range of built-in field types.
Common field types:
- CharField: For short strings. Options: max_length (required).
- Example: name = models.CharField(max_length=100)
- TextField: For long text.
- Example: description = models.TextField()
- IntegerField: For integers.
- Example: age = models.IntegerField()
- BooleanField: For true/false values.
- Example: is_active = models.BooleanField(default=True)
- DateTimeField: For dates and times. Options: auto_now_add (sets on creation), auto_now (sets on save).
- Example: created_at = models.DateTimeField(auto_now_add=True)
- ForeignKey: For many-to-one relationships (see Relationships section).
- FileField / ImageField: For file uploads. Requires additional setup for storage.
Field options (applicable to most fields):
- null=True: Allow NULL in database.
- blank=True: Allow empty values in forms.
- default=value: Set a default value.
- unique=True: Enforce uniqueness.
- choices=[(‘val1’, ‘Label1’), …]: Restrict to specific choices.
Full reference includes over 20 field types, such as EmailField, URLField, DecimalField, etc..
Example model:
python
class Book(models.Model):
title = models.CharField(max_length=200)
publication_date = models.DateField()
in_stock = models.BooleanField(default=True)
Relationships
Django supports three main relationship types: many-to-one, many-to-many, and one-to-one.
- Many-to-One (ForeignKey): Links one model to another. Use on_delete to specify behavior when the referenced object is deleted (e.g., models.CASCADE).
- Example: python
class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE)
- Example: python
- Many-to-Many (ManyToManyField): For associations between multiple instances. Can use a through model for additional data.
- Example: python
class Genre(models.Model): name = models.CharField(max_length=50) class Book(models.Model): genres = models.ManyToManyField(Genre)
- Example: python
- One-to-One (OneToOneField): For unique relationships, like extending a model.
- Example: python
class Profile(models.Model): user = models.OneToOneField('auth.User', on_delete=models.CASCADE) bio = models.TextField()
- Example: python
Access related objects using lowercase model name (e.g., book.author) or _set for reverse (e.g., author.book_set.all()) .
Meta Options
The inner Meta class in a model allows customization of model behavior.
Common options:
- ordering = [‘field’]: Default ordering for querysets.
- verbose_name = ‘My Model’: Human-readable name.
- db_table = ‘custom_table’: Custom database table name.
- unique_together = [[‘field1’, ‘field2’]]: Multi-field uniqueness.
- indexes = [models.Index(fields=[‘field1’])]: Add database indexes.
- abstract = True: Make the model abstract (for inheritance without a table).
Example:
python
class Book(models.Model):
# fields...
class Meta:
ordering = ['title']
verbose_name_plural = 'Books'
Model Methods
Models can have custom methods for business logic.
- str(): Returns a string representation (used in admin and shells).
- Example: def __str__(self): return self.title
- save(): Override to add logic before/after saving.
- Custom methods: E.g., def is_overdue(self): return self.due_date < date.today()
Making Queries
Use the model’s manager (default: objects) to perform CRUD operations.
- Create: obj = MyModel(field=’value’); obj.save() or MyModel.objects.create(field=’value’)
- Retrieve: MyModel.objects.get(id=1) (single object) or MyModel.objects.filter(field=’value’) (queryset)
- Update: obj.field = ‘new’; obj.save() or MyModel.objects.filter(…).update(field=’new’)
- Delete: obj.delete() or MyModel.objects.filter(…).delete()
Complex lookups use double underscores (e.g., filter(author__name=’Doe’) for related fields).
QuerySet API
QuerySets are lazy collections of objects. Chain methods for complex queries.
Key methods:
- **filter(kwargs): Returns matching objects.
- **exclude(kwargs): Returns non-matching.
- order_by(*fields): Sorts results.
- values(*fields): Returns dictionaries.
- distinct(): Removes duplicates.
- **annotate(expressions): Adds computed fields (e.g., annotate(total=Sum(‘field’))).
- **aggregate(expressions): Computes aggregates (e.g., aggregate(Count(‘id’))).
- select_related(*fields): Joins related models to avoid N+1 queries.
- prefetch_related(*lookups): Prefetches many-to-many/one relations.
Example:
python
from django.db.models import Q, Count
books = Book.objects.filter(Q(title__icontains='django') | Q(author__name='Doe')).order_by('-publication_date').annotate(num_genres=Count('genres'))
QuerySets are evaluated only when iterated, sliced, or forced (e.g., list(qs)).
Managers
Managers provide the interface for querying. Customize by subclassing models.Manager.
Example custom manager:
python
class ActiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_active=True)
class MyModel(models.Model):
objects = models.Manager() # Default
active_objects = ActiveManager() # Custom
Use: MyModel.active_objects.all().
Migrations
Migrations handle schema changes.
- makemigrations: Detects model changes and creates migration files.
- migrate: Applies migrations to the DB.
- sqlmigrate <name>: Shows SQL for a migration.
- Data migrations: Use RunPython operations in migration files for custom data ops.
Example data migration:
python
def forwards(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
MyModel.objects.create(name='Default')
class Migration(migrations.Migration):
operations = [migrations.RunPython(forwards)]
Squash migrations to consolidate history.
Optimization Techniques
Optimize database access to improve performance.
- Use select_related and prefetch_related to reduce queries.
- Avoid unnecessary fields with only(*fields) or defer(*fields).
- Batch updates/deletes with bulk_update/bulk_create.
- Index fields used in filters/order_by.
- Use database-specific features via raw SQL if needed.
- Profile with django-debug-toolbar or connection.queries.
Monitor slow queries and cache where appropriate.
Conclusion
This covers the core of Django Models and ORM. Practice by building a simple app, like a blog or library system. For deeper dives, refer to the official docs or tutorials like those on MDN if you have specific questions or need examples for a project.
FAQs
What is Django’s ORM?
The Django ORM (Object-Relational Mapping) is a system that allows you to interact with your database using Python code instead of raw SQL. It maps Python classes (models) to database tables, enabling CRUD operations (Create, Retrieve, Update, Delete) in a database-agnostic way.
How do I define a model in Django?
A model is a Python class that subclasses django.db.models.Model
. Define fields as class attributes to represent database columns. Example:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
publication_date = models.DateField()
What are the most common field types in Django models?
Common field types include:
CharField
: Short strings (requiresmax_length
).TextField
: Long text.IntegerField
: Integer values.BooleanField
: True/false values.DateTimeField
: Date and time.ForeignKey
: Many-to-one relationship.ManyToManyField
: Many-to-many relationship.
How do I create a database table from a model?
After defining a model, run:
python manage.py makemigrations
python manage.py migrate
This generates migration files and applies them to create/update the database schema.
What is the difference between null=True
and blank=True
?
null=True
: Allows NULL in the database.blank=True
: Allows empty values in forms (validation). For example:description = models.TextField(null=True, blank=True)
How do I handle relationships between models?
Django supports:
- ForeignKey: Many-to-one (e.g., a book has one author).
- ManyToManyField: Many-to-many (e.g., a book can have multiple genres).
- OneToOneField: One-to-one (e.g., a user has one profile).
Example:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
How do I query the database using the ORM?
Use the model’s objects
manager. Examples:
- Create:
Book.objects.create(title="Django Guide")
- Retrieve:
Book.objects.filter(title__contains="Django")
- Update:
Book.objects.filter(id=1).update(title="New Title")
- Delete:
Book.objects.filter(id=1).delete()
What are QuerySets, and why are they lazy?
QuerySets are collections of database queries that are only executed when needed (e.g., when iterated or sliced). This allows chaining methods like filter()
and order_by()
efficiently without hitting the database prematurely.
How can I optimize database queries?
- Use
select_related()
for ForeignKey joins. - Use
prefetch_related()
for ManyToMany/OneToOne relations. - Avoid fetching unnecessary fields with
only()
ordefer()
. - Add indexes in the model’s
Meta
class for frequently queried fields.
What are custom managers, and how do I use them?
Managers provide query interfaces for models. Create a custom manager for reusable querysets:
class ActiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_active=True)
class Book(models.Model):
is_active = models.BooleanField(default=True)
active_objects = ActiveManager()
Use: Book.active_objects.all()
.
How do I handle database migrations?
Run python manage.py makemigrations
to create migration files based on model changes, then python manage.py migrate
to apply them. Use sqlmigrate
to inspect SQL or RunPython
for data migrations.
What is the purpose of the Meta
class in a model?
The Meta
class customizes model behavior, such as:
ordering
: Default sort order (e.g.,ordering = ['title']
).db_table
: Custom table name.unique_together
: Multi-field uniqueness constraints.indexes
: Database indexes for performance.
Can I write raw SQL queries with Django ORM?
Yes, use MyModel.objects.raw('SELECT * FROM myapp_mymodel')
for custom SQL. Alternatively, use connection.cursor()
for low-level SQL execution.
How do I prevent N+1 query issues?
N+1 issues occur when related objects are queried individually. Use select_related()
for ForeignKey and prefetch_related()
for ManyToMany/OneToOne to fetch related data in a single query.