Database and Models
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!
Models
What is a model?
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.
Model field
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 thelast_modified_dateDateField(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.- To change the date, we can import
from django.utils import timezoneand addmodels.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 .
3-step guide to making model changes:
- Change your models in models.py
- Run
python manage.py makemigrationsto create migrations for those changes - Run
python manage.py migrateto 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.
Step 1: Change the models (in models.py)
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
Step 2: create migrations for those changes
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;
Step 3: Apply those changes to the database
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.
Interact with API
Once you’ve created your data models, Django automatically provides a database-abstraction API that lets you create, retrieve, update and delete objects.
- To invoke the Python shell, use this command:
$ python manage.py shell
- To import the Post model and User model.
>>> from blog.models import Post
>>> from django.contrib.auth.models import User
- To check all the Users
>>> User.objects.all()
- To check the first User
>>> User.objects.all().first()
- We can filter the result by using
filter()method. In this code, we add thefirst()method to take the first result, and store the value in theuservariable.
>>> user = User.objects.filter(username='filter-value').first()
We can check:
- user id:
user.id - user email:
user.email
- To check if we have any Post
>>> Post.objects.all()
<QuerySet [>]>
Because we haven’t created any posts, it shows an empty list.
- To add post
>>> post_1 = Post(title='Blog 1', content='First post content', author=user)
- To save post:
>>> 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.
- To access the fields of first post.
>>> 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'
- To check all the posts created by the user:
>>> user.post_set.all()
<QuerySet [<Post: Blog 1>, <Post: Blog 2>]>
- To create a post directly using
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>]>
Apply Database to blog app
After adding the database using the Python shell, we can add posts to our blog app.
- Open our blog/views.py
- Import our Post model:
from .models import Post. - Update the context part:
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'})