In this article, we will create a model, set up the database, and implement immigration.
Doing so allows us to create our database instead of relying on dummy data!
A model is a database layout containing the essential fields and behaviors of the data you’re storing.
Each model is represented by a class that subclasses django.db.models.Model
.
Each model has class variables and a database field.
CharField is a character field. It requires CharField.max_length
.
TextField is a large text field.
DateTimeField presents the date and time.
DateTimeField(auto_now=True)
will automatically set the day to current datetime every time the object is saved. It’s good if we set for the last_modified_date
DateField(auto_now_add=True)
will automatically set the day to the current datetime when the object is first created. You can’t update the date posted.from django.utils import timezone
and add models.DateTimeField(default=timezone.now)
.EmailField checks that the value is a valid email address using EmailValidator. The max length is 254.
ForeignKey shows relationships. It requires two arguments: the class to which the model is related and the on_delete option.
For example: author = models.ForeignKey(User, on_delete=models.CASCADE)
will delete Post if User is delete.
Learning resources: You can check all Django Model Fields.
python manage.py makemigrations
to create migrations for those changespython manage.py migrate
to apply those changes to the database.Example For example, we need Users(authors) and Posts for the blog app.
Because Django already has a built-in authentication system with a User model (admin page), so we just need to create a Post model.
Django already created a model.py file in the blog app, so we can open blog/models.py and edit:
from django.db import models
from django.utils import timezone # Import timezone for DateTimeField
from django.contrib.auth.models import User # Import User model
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE) # If a user created the post is deleted, posts are deleted as well.ß
# __str__() method returns how the Post is printed
def __str__(self):
return self.title
After making changes to the Django database, we need to run makemigrations
to create new migrations based on the detected modifications to your models.
$ python manage.py makemigrations
Migrations for 'blog':
blog/migrations/0001_initial.py
- Create model Post
Here, we have 0001_initial.py in the migration directory in our blog app.
Note: Check SQL code
We can check the exact SQL code that will be generated with the code python manage.py sqlmigrate APP_NAME MIGRATION_NUMBER
.
python manage.py sqlmigrate blog 0001
We’ll see this
BEGIN;
--
-- Create model Post
--
CREATE TABLE "blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(100) NOT NULL, "content" text NOT NULL, "date" datetime NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");
COMMIT;
Run migrate
command to create those model tables in our database:
$ python manage.py migrate
Migrations are very useful because they let us change models over time even after it is created and has data in the database.
The migrate command takes all the migrations that haven’t been applied.
Once you’ve created your data models, Django automatically provides a database-abstraction API that lets you create, retrieve, update and delete objects.
$ python manage.py shell
>>> from blog.models import Post
>>> from django.contrib.auth.models import User
>>> User.objects.all()
>>> User.objects.all().first()
filter()
method. In this code, we add the first()
method to take the first result, and store the value in the user
variable.>>> user = User.objects.filter(username='filter-value').first()
We can check:
user.id
user.email
>>> Post.objects.all()
<QuerySet [>]>
Because we haven’t created any posts, it shows an empty list.
>>> post_1 = Post(title='Blog 1', content='First post content', author=user)
>>> post_1.save()
Querry our Post again, we’ll see:
>>> Post.objects.all()
<QuerySet [<Post: Blog 1>]>
We can create a second post with step 7 and 8.
>>> post = Post.objects.first()
>>> post.content
'First post content'
>>> post.date
datetime.datetime(2020, 8, 10, 15, 29, 4, 220800, tzinfo=<UTC>)
>>> post.title
'Blog 1'
>>> user.post_set.all()
<QuerySet [<Post: Blog 1>, <Post: Blog 2>]>
post_set
:>>> user.post_set.create(title='Blog 3', content='Third post content')
<Post: Blog 3>
We don’t need to run .save()
in this case because it’s automatically saved.
If we run our Post.objects.all()
again, we’ll see:
<QuerySet [<Post: Blog 1>, <Post: Blog 2>, <Post: Blog 3>]>
After adding the database using the Python shell, we can add posts to our blog app.
from .models import Post
. context = {
'posts': Post.objects.all() # Get the posts from the Post Database
}
So here is our final code:
from django.shortcuts import render
from .models import Post
def index(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/index.html', context)
def about(request):
return render(request, 'blog/about.html', {'title': 'About'})