Designing the blog data schema - Django Blog #2

Hello Internet Programmer, today we Designing the blog data schema means we create a model for blogs to store blog posts. So let’s start. Before that, activate your virtual environment in your project path.

Creating blog Model

You will start designing your blog data schema by defining the data models for your blog.

A model is a Python class that subclasses django.db.models.Model in which each attribute represents a database field. Django will create a table for each model defined in the models.py file.

When you create a model, Django will provide you with a practical API to query objects in the database easily.

First, you need to define a Post model. Add the following lines to the models.py file of the blog application

# models
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

# post model
class Post(models.Model):
    STATUS_CHOICES = (
    ('draft', 'Draft'),
    ('published', 'Published'),
    )

    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique_for_date='publish')
    author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='blog_posts')
    body = models.TextField()

    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    
    status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')

    class Meta:
        ordering = ('-publish',)
    
    def __str__(self):
        return self.title

This is your data model for blog posts. Let’s take a look at the fields you just defined
for this model,

  • title: This field for the blog post title. This field is CharField, which translate into VARCHAR column in the SQL database.
  • slug: This is a field intended to be used in URLs. A slug is a short label that contains only letters, numbers, underscores, or hyphens. You will use the slug field to build beautiful, SEO-friendly URLs for your blog posts. You have added the unique_for_date parameter to this field so that you can build URLs for posts using their publish date and slug. Django will prevent multiple posts from having the same slug for a given date.
  • author: This field defines a many-to-one relationship, meaning that each post is written by a user, and a user can write any number of posts. For this field, Django will create a foreign key in the database using the primary key of the related model. In this case, you are relying on the User model of the Django authentication system. The on_delete parameter specifies the behavior to adopt when the referenced object is deleted. This is not specific to Django; it is an SQL standard. Using CASCADE, you specify that when the referenced user is deleted, the database will also delete all related blog posts. You specify the name of the reverse relationship, from User to Post, with the related_name attribute. This will allow you to access related objects easily.
  • body: This is the body of the post. This field is a TextField that translates into a TEXT column in the SQL database.
  • publish: This datetime indicates when the post was published. You use Django’s timezone now method as the default value. This returns the current datetime in a timezone-aware format. You can think of it as a timezone-aware version of the standard Python datetime.now method.
  • created: This datetime indicates when the post was created. Since you are using auto_now_add here, the date will be saved automatically when creating an object.
  • updated: This datetime indicates the last time the post was updated. Since you are using auto_now here, the date will be updated automatically when saving an object.
  • status: This field shows the status of a post. You use a choices parameter, so the value of this field can only be set to one of the given choices.

The Meta class inside the model contains metadata. You tell Django to sort results by the publish field in descending order by default when you query the database. You specify the descending order using the negative prefix. By doing this, posts published recently will appear first.

The __str__() method is the default human-readable representation of the object. Django will use it in many places, such as the administration site.

Creating and applying migrations

Now the model is ready for your blog app to store posts. You will need a database table for it. Django comes with a migration system that tracks the changes made to the model and enables them to propagate into the database.

The migrate command applies migrations for all applications listed in INSTALLED_APP in settings.py. It synchronizes the database with the current models and existing migrations.

First, you will need to create an initial migration for your Post model. In the root directory of your project, run the following command,

python3 manage.py makemigrations

Let’s sync your database with the new model. Run the following command to apply existing migrations,

python3 manage.py migrate

You just applied migrations for the applications listed in INSTALLED_APPS, including your blog application. After applying the migrations, the database reflects the current status of your models.

If you edit the models.py file in order to add, remove, or change the fields of existing models, or if you add new models, you will have to create a new migration using the makemigrations command.

The migration will allow Django to keep track of model changes. Then, you will have to apply it with the migrate command to keep the database in sync with your models.

Creating a superuser

Now that you have defined the Post model, you will create a simple administration site to manage your blog app.

Django comes with a built-in administration interface that is very useful for editing content. The Django site is built dynamically by reading your model metadata and providing a production-ready interface for editing content.

You can use it out of the box, configuring how you want your models to be displayed in it.

The django.contrib.admin application is already included in the INSTALLED_APPS setting, so you don’t need to add it.

First, you will need to create a user to manage the administration site. Run the following command:

python3 manage.py createsuperuser

After this, you will see the following output. Enter your desire username, email, and password as follows,

The Django administration site

We created a superuser. Now, start the development server using python3 manage.py runserver command and open http://127.0.0.1:8000/admin/ in your favorite browser.

You should see the administration login page, as shown in the following screenshot,

django admin, designing post model

Login using the credentials of the user you created in the preceding step. You will see the administration site index page, as shown in the following screenshot,

django admin, Designing the blog data schema

The Group and User models are part of the Django authentication framework located in django.contrib.auth. If you click on Users, you will see the user you created previously.

Adding models to the administration site

Now we are adding our Post model to the administration site. For that open admin.py file of the blog app and add this,

from django.contrib import admin
from .models import Post

admin.site.register(Post)

Now open or reload the administration site in your browser. You should see your Post model on the site, as follows,

django admin, post model, making post model for blog django blog tutorial

Now click on Posts, you can see like this.

post model, add post

Now click on ADD POST button, and add the first post.

adding post from django admin, post model

Fill in the form and click on the SAVE button. You should be redirected to the post
list page with a success message and the post you just created, as shown in the
following screenshot

post display as object, django models

Customizing the way that models are displayed

You can see in the above screenshot post data displayed as Post object (1) right. That’s not a better way to display right. So let’s modify it.

Now, we will take a look at how to customize the administration site. Edit the admin.py file of your blog application and change it, as follows,

from django.contrib import admin
from .models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'author', 'publish', 'status')

You are telling the Django administration site that your model is registered in the site using a custom class that inherits from ModelAdmin.

The list_display attribute allows you to set the fields of your model that you want to display on the administration object list page.

The @admin.register() decorator performs the same function as the admin.site.register() function that you replaced, registering the ModelAdmin class that it decorates.

Let’s customize the admin model with some more options, using the following code, Just make code look like the following code in admin.py,

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'author', 'publish', 'status')
    list_filter = ('status', 'created', 'publish', 'author')
    search_fields = ('title', 'body')
    prepopulated_fields = {'slug': ('title',)}
    raw_id_fields = ('author',)
    date_hierarchy = 'publish'
    ordering = ('status', 'publish')

Return to your browser and reload the post list page. Now, it will look like this,

customizing django admin, django models

You can see that the fields displayed on the post list page are the ones you specified in the list_display attribute. The list page now includes a right sidebar that allows you to filter the results by the fields included in the list_filter attribute.

A search bar has appeared on the page. This is because you have defined a list of searchable fields using the search_fields attribute. Just below the search bar, there are navigation links to navigate through a date hierarchy; this has been defined by the date_hierarchy attribute.

You can also see that the posts are ordered by STATUS and PUBLISH columns by default. You have specified the default sorting criteria using the ordering attribute.

Another change in Post form page. Click on ADD POST and you will see some changes here.

As you type the title of a new post, the slug field is filled in automatically. You have told Django to prepopulate the slug field with the input of the title field using the prepopulated_fields attribute.

Also, the author field is now displayed with a lookup widget that can scale much better than a drop-down select input when you have thousands of users. This is achieved with the raw_id_fields attribute and it looks like this,

author

With a few lines of code, you have customized the way your model is displayed on the administration site. There are plenty of ways to customize and extend the Django administration site.

So that’s it for this tutorial. Share this tutorial with your friends.

GitHub Link: https://github.com/SoniArpit/awwblog

Previous: Create a Blog in Django – Installation and Setup – Django Blog #1

Next: Displaying List of Posts and Single Post on a Web page and Pagination – Django Blog #3