CodeToLive

Django Models & Databases

Models in Django are Python classes that represent database tables. They define the structure of your data and provide an abstraction layer for database operations.

What are Django Models?

Django models:

  • Are Python classes that subclass django.db.models.Model
  • Each attribute represents a database field
  • Provide methods for querying the database
  • Handle data validation
  • Define relationships between data

Creating a Model

Define models in your app's models.py file:


from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    published_date = models.DateField()
    isbn = models.CharField(max_length=13)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=2)
    in_stock = models.BooleanField(default=True)
    
    def __str__(self):
        return self.title
                

Model Field Types

Django provides many field types:

  • AutoField - Integer field that auto-increments
  • BigAutoField - 64-bit integer that auto-increments
  • BooleanField - True/False field
  • CharField - String field for small strings
  • DateField - Date field
  • DateTimeField - Date and time field
  • DecimalField - Fixed-precision decimal number
  • EmailField - Email address field
  • FileField - File upload field
  • FloatField - Floating-point number
  • ImageField - Image upload field
  • IntegerField - Integer field
  • TextField - Large text field
  • URLField - URL field
  • UUIDField - Universally unique identifier

Field Options

Field types accept optional arguments:

  • null - If True, Django will store NULL in database (default: False)
  • blank - If True, field is allowed to be blank (default: False)
  • choices - Sequence of 2-tuples to use as choices
  • default - Default value for the field
  • help_text - Extra help text to be displayed with the form widget
  • primary_key - If True, this field is the primary key
  • unique - If True, field must be unique
  • verbose_name - Human-readable name

Model Methods

Add custom methods to your models:


class Book(models.Model):
    # ... fields ...
    
    def is_expensive(self):
        return self.price > 50
    
    def get_absolute_url(self):
        return reverse('book_detail', args=[str(self.id)])
                

Model Meta Options

Use Meta class to add metadata to your model:


class Book(models.Model):
    # ... fields ...
    
    class Meta:
        ordering = ['title']
        verbose_name = 'book'
        verbose_name_plural = 'books'
                

Model Relationships

Django supports three main types of relationships:

  • Many-to-one: ForeignKey
  • Many-to-many: ManyToManyField
  • One-to-one: OneToOneField

ForeignKey Example


class Author(models.Model):
    name = models.CharField(max_length=100)
    
class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
                

ManyToManyField Example


class Category(models.Model):
    name = models.CharField(max_length=100)
    
class Book(models.Model):
    title = models.CharField(max_length=100)
    categories = models.ManyToManyField(Category)
                

OneToOneField Example


class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)
    
class Restaurant(models.Model):
    place = models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True
    )
    serves_hot_dogs = models.BooleanField(default=False)
                

on_delete Options

When using relationships, specify what happens when referenced object is deleted:

  • CASCADE - Delete objects that had a foreign key pointing to it
  • PROTECT - Prevent deletion of referenced object
  • SET_NULL - Set foreign key to NULL
  • SET_DEFAULT - Set foreign key to default value
  • SET() - Set foreign key to value passed to SET()
  • DO_NOTHING - Take no action (database may raise error)

Migrations

Migrations are Django's way of propagating changes to your models into your database schema:


# Create migrations for your changes
python manage.py makemigrations

# Apply migrations to database
python manage.py migrate
                

Querying the Database

Django provides a powerful ORM for querying the database:

Creating Objects


# Create and save immediately
book = Book(title="Django for Beginners", author="William S. Vincent")
book.save()

# Create and save in one step
book = Book.objects.create(title="Django for Professionals", author="William S. Vincent")
                

Retrieving Objects


# Get all books
all_books = Book.objects.all()

# Get a single book by id
book = Book.objects.get(id=1)

# Filter books
expensive_books = Book.objects.filter(price__gt=50)
django_books = Book.objects.filter(title__contains="Django")
recent_books = Book.objects.filter(published_date__year=2023)
                

Updating Objects


# Update a single object
book = Book.objects.get(id=1)
book.price = 29.99
book.save()

# Update multiple objects
Book.objects.filter(published_date__year=2020).update(price=19.99)
                

Deleting Objects


# Delete a single object
book = Book.objects.get(id=1)
book.delete()

# Delete multiple objects
Book.objects.filter(published_date__year=2010).delete()
                

QuerySet Methods

Common QuerySet methods:

  • all() - Returns all objects
  • filter() - Returns objects matching given parameters
  • exclude() - Returns objects not matching given parameters
  • get() - Returns single object matching parameters
  • create() - Creates and saves a new object
  • count() - Returns count of objects
  • order_by() - Orders the results
  • values() - Returns dictionaries instead of model instances
  • values_list() - Returns tuples instead of model instances

Field Lookups

Field lookups specify how to match fields:

  • exact - Exact match (default lookup)
  • iexact - Case-insensitive exact match
  • contains - Case-sensitive containment test
  • icontains - Case-insensitive containment test
  • in - In a given list
  • gt - Greater than
  • gte - Greater than or equal to
  • lt - Less than
  • lte - Less than or equal to
  • startswith - Case-sensitive starts-with
  • istartswith - Case-insensitive starts-with
  • endswith - Case-sensitive ends-with
  • iendswith - Case-insensitive ends-with
  • range - Range test (inclusive)

Aggregation

Django supports database aggregation:


from django.db.models import Avg, Max, Min, Sum, Count

# Average price of all books
Book.objects.all().aggregate(Avg('price'))

# Max price of books in stock
Book.objects.filter(in_stock=True).aggregate(Max('price'))

# Count books by author
Book.objects.values('author').annotate(count=Count('id'))
                

Model Inheritance

Django supports three styles of model inheritance:

  • Abstract base classes: Parent model holds common info but isn't a database table
  • Multi-table inheritance: Each model has its own database table
  • Proxy models: Change Python behavior without changing database structure

Abstract Base Class Example


class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        abstract = True
        
class Book(BaseModel):
    title = models.CharField(max_length=100)
    # ...
                

Registering Models with Admin

To make models editable in the admin interface:


from django.contrib import admin
from .models import Book

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'price')
    list_filter = ('author', 'in_stock')
    search_fields = ('title', 'author')
                

Database Configuration

Django supports multiple databases. Configure in settings.py:


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}
                

Supported Databases

Django officially supports:

  • PostgreSQL
  • MySQL
  • SQLite
  • Oracle

Model Best Practices

  • Use descriptive field names
  • Add __str__ methods to all models
  • Use related_name for reverse relationships
  • Consider abstract base classes for common fields
  • Use verbose_name for better admin display
  • Add indexes for frequently queried fields
  • Use select_related and prefetch_related for performance
Next: Views & URL Routing