Database and Migrations¶
Django's
ORM
(Object-Relational Mapping) provides a powerful and flexible way to interact with databases.This tutorial will guide you through setting up models, creating and applying
migrations
, and managing your database schema. We'll use a blogging application withPost
,User
, andComment
models as examples.
Setting Up Your Models¶
Let's start by defining our models in
blog/models.py
.Here is a table listing the
supported field types
inDjango's django.db.models
module along with examples for eachField Type Description Example CharField A string field, for small- to large-sized strings. name = models.CharField(max_length=100) TextField A large text field. Use this for large amounts of text. description = models.TextField() IntegerField An integer field. age = models.IntegerField() FloatField A floating-point number field. price = models.FloatField() BooleanField A boolean field. is_active = models.BooleanField(default=True) DateField A date field. birth_date = models.DateField() DateTimeField A date and time field. created_at = models.DateTimeField(auto_now_add=True) TimeField A time field. start_time = models.TimeField() EmailField An Email field. email = models.EmailField() URLField A URL field. website = models.URLField() SlugField A slug field. slug = models.SlugField() FileField A file upload field. file = models.FileField(upload_to='uploads/') ImageField An image upload field. image = models.ImageField(upload_to='images/') ForeignKey A many-to-one relationship. author = models.ForeignKey(Author, on_delete=models.CASCADE) OneToOneField A one-to-one relationship. profile = models.OneToOneField(Profile, on_delete=models.CASCADE) ManyToManyField A many-to-many relationship. categories = models.ManyToManyField(Category) DecimalField A fixed-precision decimal number field. price = models.DecimalField(max_digits=10, decimal_places=2) PositiveIntegerField An integer field for positive values only. quantity = models.PositiveIntegerField() PositiveSmallIntegerField A small integer field for positive values only. rank = models.PositiveSmallIntegerField() SmallIntegerField A small integer field. votes = models.SmallIntegerField() DurationField A field for storing periods of time. duration = models.DurationField() UUIDField A field for storing universally unique identifiers. uuid = models.UUIDField(default=uuid.uuid4, editable=False) BinaryField A field for storing binary data. data = models.BinaryField() JSONField A field for storing JSON data. metadata = models.JSONField()
Post Model¶
CharField: Represents a short-to-mid-sized string.
ForeignKey: Creates a
many-to-one
relationship to theUser
model.TextField: Represents large text fields.
DateTimeField: Represents a
date
andtime
field, with default set to the current time.from django.db import models from django.utils import timezone from django.contrib.auth.models import User class Post(models.Model): title = models.CharField(max_length=80) author = models.ForeignKey(User, on_delete=models.CASCADE) content = models.TextField() date_posted = models.DateTimeField(default=timezone.now) def __str__(self): return self.title
Comment Model¶
ForeignKey to Post and User: Each comment is associated with a specific post and user.
class Comment(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE) author = models.ForeignKey(User, on_delete=models.CASCADE) content = models.TextField() date_posted = models.DateTimeField(default=timezone.now) def __str__(self): return f'Comment by {self.author} on {self.post}'
Creating and Applying Migrations¶
- After defining your models, you need to create and apply
migrations
to update the database schema.
Creating Migrations¶
Run the following command to create
migrations
based on the changes in your modelsThis command generates a migration file in the
blog/migrations
directory.python manage.py makemigrations
Applying Migrations¶
- To apply the migrations and update the database schema, run:
- This command applies the
migrations
to your database, creating the necessarytables
andfields
.python manage.py migrate
Creating Demo Data¶
First, ensure you have access to Django's
shell
to execute Python code within the context of your Django project. Run the following command:python manage.py shell
Within the shell, you can create instances of your models.
from django.contrib.auth.models import User from blog.models import Post, Comment from django.utils import timezone # Create a user user = User.objects.create_user(username='john_doe', email='john@example.com', password='password123') # Create some posts post1 = Post.objects.create(title='First Post', author=user, content='This is the content of the first post', date_posted=timezone.now()) post2 = Post.objects.create(title='Second Post', author=user, content='This is the content of the second post', date_posted=timezone.now()) # Create comments for post1 comment1 = Comment.objects.create(post=post1, author=user, content='This is the first comment on the first post', date_posted=timezone.now()) comment2 = Comment.objects.create(post=post1, author=user, content='This is the second comment on the first post', date_posted=timezone.now()) # Create a comment for post2 comment3 = Comment.objects.create(post=post2, author=user, content='This is the first comment on the second post', date_posted=timezone.now())
- If you facing any problem, you can re-create database, but your all data will be gone (including super-user)
In default, Django use
db.sqlite3
to store all datarm db.sqlite3
Related Object Queries¶
Get all comments for a specific post
Access related objects using reverse relationships
# Get all comments for a specific post post_comments = Comment.objects.filter(post=post1) # Access related objects using reverse relationships post_comments = post1.comment_set.all()
Advanced Queries [field lookups]¶
Django's
ORM
usesfield lookups
, which are used to create complex queries.Here's a table of common
field lookups
with their purpose and examples:Function Purpose Example exact Exact match Post.objects.filter(title__exact='First Post') iexact Case-insensitive exact match Post.objects.filter(title__iexact='first post') contains Contains substring Post.objects.filter(content__contains='Django') icontains Case-insensitive contains Post.objects.filter(content__icontains='django') in Value is in a given list Post.objects.filter(id__in=[1, 2, 3]) gt Greater than Post.objects.filter(date_posted__gt=timezone.now() - timedelta(days=7)) gte Greater than or equal to Post.objects.filter(date_posted__gte=timezone.now() - timedelta(days=7)) lt Less than Post.objects.filter(date_posted__lt=timezone.now()) lte Less than or equal to Post.objects.filter(date_posted__lte=timezone.now()) startswith Starts with substring Post.objects.filter(title__startswith='Fir') istartswith Case-insensitive starts with substring Post.objects.filter(title__istartswith='fir') endswith Ends with substring Post.objects.filter(title__endswith='Post') iendswith Case-insensitive ends with substring Post.objects.filter(title__iendswith='post') range Value is within a range Post.objects.filter(date_posted__range=[start_date, end_date]) date Match a specific date Post.objects.filter(date_posted__date=datetime.date(2023, 6, 17)) year Match a specific year Post.objects.filter(date_posted__year=2023) month Match a specific month Post.objects.filter(date_posted__month=6) day Match a specific day Post.objects.filter(date_posted__day=17) week_day Match a specific day of the week Post.objects.filter(date_posted__week_day=2) isnull Check for NULL (or not NULL) Post.objects.filter(author__isnull=True)
Retrieve posts containing a keyword
Retrieve posts published in the last 7 days
Order posts by date posted (newest first)
# Retrieve posts containing a keyword keyword_posts = Post.objects.filter(content__icontains='content') # Retrieve posts published in the last 7 days recent_posts = Post.objects.filter(date_posted__gte=timezone.now() - timezone.timedelta(days=7)) # Order posts by date posted (newest first) ordered_posts = Post.objects.all().order_by('-date_posted')
Working with the Admin Interface¶
- Register your models with the
admin
interface to manage them through Django's admin panel.
Registering Models¶
In
blog/admin.py
, register your models:This will make the
Post
andComment
models accessible in theadmin
interface.from django.contrib import admin from .models import Post, Comment admin.site.register(Post) admin.site.register(Comment)