Object-Relational Mapping (ORM) in Django

Loading

Django’s Object-Relational Mapping (ORM) provides a way to interact with databases using Python objects instead of raw SQL queries. ORM abstracts the database layer, making it easier to create, read, update, and delete records.


1. Setting Up Django ORM

Django ORM requires a database connection, defined in settings.py:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql', # Database backend
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}

Supported databases:

  • PostgreSQL (django.db.backends.postgresql)
  • MySQL (django.db.backends.mysql)
  • SQLite (django.db.backends.sqlite3)
  • Oracle (django.db.backends.oracle)

Run:

python manage.py migrate  # Apply existing migrations

2. Creating Models (Tables)

In models.py:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)

class Book(models.Model):
title = models.CharField(max_length=200)
published_date = models.DateField()
author = models.ForeignKey(Author, on_delete=models.CASCADE) # One-to-Many
price = models.DecimalField(max_digits=10, decimal_places=2)
  • CharField → Stores text (max length required)
  • EmailField → Stores email addresses
  • DateField → Stores dates
  • DecimalField → Stores decimal numbers
  • ForeignKey → Defines a relationship between tables

Apply changes:

python manage.py makemigrations
python manage.py migrate

3. Creating, Reading, Updating, and Deleting (CRUD)

3.1 Creating Records

from myapp.models import Author, Book

author = Author.objects.create(name="J.K. Rowling", email="jk@example.com")
book = Book.objects.create(title="Harry Potter", published_date="1997-06-26", author=author, price=29.99)

3.2 Reading Records

all_books = Book.objects.all()  # Fetch all books
book = Book.objects.get(id=1) # Get a specific book
books_by_author = Book.objects.filter(author__name="J.K. Rowling") # Filter books by author

3.3 Updating Records

book = Book.objects.get(id=1)
book.price = 24.99
book.save() # Save changes

3.4 Deleting Records

book = Book.objects.get(id=1)
book.delete()

4. ORM Queries

4.1 Filtering Data

Book.objects.filter(price__gte=20)  # Books with price >= 20
Book.objects.exclude(price__lt=20) # Books with price < 20 are excluded
Book.objects.filter(title__icontains="Harry") # Case-insensitive search

4.2 Ordering Data

Book.objects.order_by("published_date")  # Ascending order
Book.objects.order_by("-published_date") # Descending order

4.3 Selecting Specific Fields

Book.objects.values("title", "price")  # Returns a dictionary
Book.objects.only("title", "price") # Fetches only these fields

4.4 Aggregations

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

Book.objects.aggregate(Avg("price")) # Average price of all books
Book.objects.aggregate(Max("price")) # Maximum price of all books

5. Relationships in Django ORM

5.1 One-to-One Relationship

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()

5.2 One-to-Many Relationship

class Post(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE) # One Author can have many Posts

5.3 Many-to-Many Relationship

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

class Post(models.Model):
tags = models.ManyToManyField(Tag) # A post can have multiple tags

6. Query Optimization

6.1 Using select_related (For ForeignKeys)

books = Book.objects.select_related("author").all()  # Reduces queries

6.2 Using prefetch_related (For ManyToMany)

posts = Post.objects.prefetch_related("tags").all()

6.3 Using only and defer

Book.objects.only("title", "price")  # Fetch only needed fields
Book.objects.defer("published_date") # Exclude unnecessary fields

7. Raw SQL Queries

If needed, raw SQL can be executed:

from django.db import connection

with connection.cursor() as cursor:
cursor.execute("SELECT * FROM myapp_book WHERE price > %s", [20])
results = cursor.fetchall()

ORM also supports:

Book.objects.raw("SELECT * FROM myapp_book WHERE price > 20")

8. Transactions

To ensure data integrity:

from django.db import transaction

with transaction.atomic():
author = Author.objects.create(name="George Orwell", email="orwell@example.com")
Book.objects.create(title="1984", published_date="1949-06-08", author=author, price=19.99)

9. Model Inheritance

9.1 Abstract Base Class

class CommonInfo(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
abstract = True # No table created for this model

class BlogPost(CommonInfo):
title = models.CharField(max_length=100)

9.2 Multi-Table Inheritance

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

class Dog(Animal):
breed = models.CharField(max_length=50) # Creates separate Dog table with Animal relation

10. Signals (Triggers)

Django signals allow running code when a model event occurs.

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Author)
def notify_admin(sender, instance, created, **kwargs):
if created:
print(f"New author added: {instance.name}")

Leave a Reply

Your email address will not be published. Required fields are marked *