Django ORM
What is Django ORM?
Django's Object-Relational Mapping (ORM) is a system that allows developers to interact with the database using Python code instead of writing SQL queries. The ORM automatically translates Python class definitions (models) into database tables and allows you to perform database operations such as creating, reading, updating, and deleting records using simple Python commands.
How do you create a new record using Django ORM?
To create a new record in Django ORM, you can either instantiate a model object and call the save() method or use the create() method to insert a new record directly into the database.
Example of creating a new record:
post = Post(title='New Post', content='Post content here')
post.save() # Saves the object to the database
Or using create():
Post.objects.create(title='New Post', content='Post content here')
How do you retrieve records using Django ORM?
To retrieve records in Django ORM, you can use methods like all(), get(), and filter() to query the database. These methods return either a queryset (a list-like object) or a single record.
Examples of retrieving records:
# Retrieve all records
posts = Post.objects.all()
# Retrieve a single record by its primary key (id)
post = Post.objects.get(id=1)
# Retrieve records that meet specific criteria
published_posts = Post.objects.filter(status='published')
How do you update records using Django ORM?
To update a record in Django ORM, you first retrieve the record, modify its fields, and then call the save() method to update the record in the database.
Example of updating a record:
post = Post.objects.get(id=1) # Retrieve the post by ID
post.title = 'Updated Title' # Modify the field
post.save() # Save the changes to the database
How do you delete records using Django ORM?
To delete a record in Django ORM, you first retrieve the record and then call the delete() method on the object.
Example of deleting a record:
post = Post.objects.get(id=1) # Retrieve the post by ID
post.delete() # Delete the record from the database
What is a queryset in Django ORM?
A queryset in Django ORM is a list-like collection of database records. It represents the results of a query and allows you to filter, order, and chain operations on the data. Querysets are lazy, meaning that they do not hit the database until they are evaluated (e.g., when iterating over them or converting them to a list).
Example of a queryset:
posts = Post.objects.filter(status='published') # A queryset of published posts
How do you filter records using Django ORM?
To filter records in Django ORM, you use the filter() method, which allows you to specify conditions that must be met for the records to be returned. You can chain multiple filters to refine the query further.
Example of filtering records:
published_posts = Post.objects.filter(status='published')
recent_posts = Post.objects.filter(published_at__year=2024)
In this example, the first query returns all posts with a status of "published", and the second query returns posts published in the year 2024.
How do you retrieve a single record using Django ORM?
You can retrieve a single record using the get() method. The get() method returns exactly one object that matches the given criteria. If no record is found, or if multiple records match, it raises an exception.
Example of retrieving a single record:
post = Post.objects.get(id=1) # Retrieve a post with the primary key of 1
Note that get() will raise a DoesNotExist exception if no record matches, or a MultipleObjectsReturned exception if more than one record matches.
How do you order records using Django ORM?
To order records in Django ORM, you use the order_by() method, which allows you to specify the field or fields by which the results should be ordered. You can also reverse the order by adding a minus sign before the field name.
Example of ordering records:
posts = Post.objects.all().order_by('published_at') # Ascending order by published_at
posts_desc = Post.objects.all().order_by('-published_at') # Descending order by published_at
How do you limit the number of results in a Django ORM query?
You can limit the number of results returned by a query using Python's array slicing syntax on a queryset.
Example of limiting results:
# Get the first 5 posts
posts = Post.objects.all()[:5]
# Get posts 5 through 10
posts = Post.objects.all()[5:10]
In this example, the slicing syntax limits the number of posts returned by the query.
How do you perform joins using Django ORM?
In Django ORM, joins are automatically performed when you use relationships like ForeignKey, OneToOneField, or ManyToManyField. You can also use select_related() for one-to-one and foreign key relationships and prefetch_related() for many-to-many relationships to optimize database queries.
Example of using select_related():
posts = Post.objects.select_related('author').all()
In this example, Django fetches both posts and their related authors in a single query, reducing the number of database hits.
How do you use select_related and prefetch_related in Django ORM?
select_related and prefetch_related are used to optimize database queries involving relationships:
select_related: Performs a SQL join and retrieves related objects in the same query. It is used forForeignKeyandOneToOneFieldrelationships.prefetch_related: Performs separate queries for related objects and joins them in Python. It is used forManyToManyFieldand reverse foreign key relationships.
Examples:
# Using select_related for a ForeignKey relationship
posts = Post.objects.select_related('author').all()
# Using prefetch_related for a ManyToMany relationship
posts = Post.objects.prefetch_related('tags').all()
How do you aggregate data using Django ORM?
To aggregate data in Django ORM, you can use the aggregate() method along with aggregation functions such as Count, Sum, Avg, Min, and Max. Aggregation allows you to perform calculations on the data directly within the database query.
Example of aggregating data:
from django.db.models import Count, Avg
# Count the number of posts
post_count = Post.objects.aggregate(Count('id'))
# Calculate the average number of views
avg_views = Post.objects.aggregate(Avg('views'))
In this example, Count is used to count the number of posts, and Avg is used to calculate the average number of views.
How do you annotate data using Django ORM?
Annotation in Django ORM allows you to add calculated fields to the queryset using the annotate() method. These calculated fields can be based on aggregation functions and are added to each object in the queryset.
Example of annotating data:
from django.db.models import Count
# Annotate the number of comments on each post
posts = Post.objects.annotate(num_comments=Count('comments'))
In this example, each post in the queryset is annotated with the number of comments it has, and this value is stored in the num_comments field.
How do you handle transactions in Django ORM?
Django provides transaction management through the transaction module. You can use atomic() to wrap a block of code in a transaction, ensuring that all database operations are completed successfully or none at all (rollback).
Example of using transactions:
from django.db import transaction
with transaction.atomic():
post = Post.objects.create(title='New Post', content='Content here')
Comment.objects.create(post=post, text='Great post!')
In this example, both the creation of the post and the comment occur within a single transaction. If an error occurs, the entire transaction is rolled back.
How do you perform raw SQL queries in Django?
In addition to using the ORM, Django allows you to execute raw SQL queries using the raw() method or the connection object for custom queries that are not easily expressed using the ORM.
Example of using raw():
posts = Post.objects.raw('SELECT * FROM myapp_post WHERE status = %s', ['published'])
In this example, a raw SQL query is executed to retrieve all posts with a status of "published".
What are managers in Django ORM?
Managers in Django are the interfaces through which you interact with the database. Every model in Django has at least one manager (by default, objects), which allows you to query the database. You can also create custom managers to add extra functionality or custom queries to your models.
Example of a custom manager:
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='published')
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
status = models.CharField(max_length=10)
objects = models.Manager() # Default manager
published = PublishedManager() # Custom manager
In this example, PublishedManager returns only posts with a status of "published". You can use it as Post.published.all().