Session Overview

  • Post Model
  • Foreign Key Relationship
  • Image Upload
  • CKEditor Integration
  • Blog Post CRUD

Create Post Model

The Post Model stores all Blog Articles published on the website.

Each Post belongs to one Category and contains the Title, Summary, Image, Description and Publishing Information.

Step 1 - Import RichTextField
from ckeditor.fields import RichTextField
Step 2 - Create Post Model
class Post(models.Model):

    Id = models.AutoField(primary_key=True)

    Category = models.ForeignKey(
        Category,
        on_delete=models.CASCADE
    )

    Title = models.CharField(max_length=200)

    Slug = models.SlugField(unique=True)

    Summary = models.CharField(max_length=300)

    Image = models.ImageField(upload_to='uploads/')

    Description = RichTextField()

    PublishDate = models.DateField()

    IsPublished = models.BooleanField(default=True)

    def __str__(self):

        return self.Title

    class Meta:

        db_table = "BlogPosts"
Explanation
Field Purpose
Category Links the Post to a Category.
Title Stores the Blog Title.
Slug Creates SEO-friendly URLs.
Summary Short description displayed on the Home Page.
Image Stores the Featured Image.
Description Stores the complete Blog Content.
PublishDate Date on which the article is published.
IsPublished Controls whether the Blog is visible on the website.
Why are we using RichTextField?

The RichTextField provided by CKEditor allows users to write formatted content instead of plain text.

It supports features such as:

  • Bold and Italic Text
  • Headings
  • Lists
  • Hyperlinks
  • Text Formatting

Understanding the Post Model

The Post Model combines multiple Django Field Types to represent a complete Blog Article.

Relationship Between Tables
BlogCategories

Id      Name

1       Technology

2       Sports

3       Travel


        │

        │ Foreign Key

        ▼


BlogPosts

Title : Django ORM

Category : Technology

Image : django.jpg

Summary : Learn Django ORM

Description : Rich Text Content

Publish Date : 01/07/2026

Published : Yes
Understanding on_delete=models.CASCADE
Category = models.ForeignKey(

    Category,

    on_delete=models.CASCADE

)
Meaning If a Category is deleted, Django automatically deletes all Blog Posts belonging to that Category.
Why do we use these additional fields?
Field Usage
Slug Creates user-friendly URLs such as /post/django-orm.
Summary Displayed on the Blog Listing page before opening the full article.
IsPublished Allows administrators to hide or publish Blog Posts without deleting them.

Create Migration

After creating the Post Model, we must update the database by generating and applying migrations.

Step 1 - Generate Migration
python manage.py makemigrations

Django creates a new migration file inside the migrations folder.

Step 2 - Apply Migration
python manage.py migrate

Django creates the BlogPosts table in the MySQL database.

Verify Database

Refresh your MySQL database and verify that the BlogPosts table has been created successfully.

Migration Flow
Create Model

      ↓

makemigrations

      ↓

Migration File

      ↓

migrate

      ↓

BlogPosts Table

Register Post Model in Admin

Register the Post Model to manage Blog Posts through the Django Admin Panel.

Open admin.py
blog/admin.py
Register Post Model
from django.contrib import admin

from .models import Category, Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):

    list_display = [

        'Id',

        'Title',

        'Category',

        'PublishDate',

        'IsPublished'

    ]

    search_fields = [

        'Title',

        'Summary'

    ]

    list_filter = [

        'Category',

        'IsPublished',

        'PublishDate'

    ]

    ordering = [

        '-PublishDate'

    ]
Result: The Posts module is now available in the Django Admin Panel with search, filtering and sorting features.

CKEditor Integration

CKEditor is a Rich Text Editor that allows users to create formatted Blog content without writing HTML code.

It provides features such as headings, bold text, lists, tables and hyperlinks.

Step 1 - Install CKEditor
pip install django-ckeditor
Note: This package was already installed during the Blog Project Setup.
Step 2 - Register CKEditor Application

Open blogproject/settings.py and add 'ckeditor' inside the INSTALLED_APPS list.

INSTALLED_APPS = [

    ...

    'ckeditor',

]
Step 3 - Import RichTextField
from ckeditor.fields import RichTextField
Step 4 - Update Description Field
Description = RichTextField()
Result: The Description field now displays the CKEditor Rich Text Editor in the Django Admin Panel, allowing users to create professionally formatted Blog content.

Image Upload

Every Blog Post contains a Featured Image displayed on the Home Page and Blog Details page.

Django stores uploaded images inside the media folder.

Step 1 - Install Pillow
pip install pillow
Note: Pillow was installed during the Blog Project Setup.
Step 2 - Create Image Field
Image = models.ImageField(

    upload_to='uploads/'

)
Step 3 - Verify Media Configuration
MEDIA_URL = '/media/'

MEDIA_ROOT = BASE_DIR / 'media'
Step 4 - Verify urls.py
if settings.DEBUG:

    urlpatterns += static(

        settings.MEDIA_URL,

        document_root=settings.MEDIA_ROOT

    )
Result: Uploaded Blog Images will be stored inside:
media/uploads

Quick Revision

Post Model
  • Title
  • Slug
  • Summary
Relationships
  • ForeignKey
  • Category
  • CASCADE
Database
  • Meta Class
  • db_table
  • Migrations
Image Upload
  • ImageField
  • Pillow
  • Media Folder
CKEditor
  • RichTextField
  • Formatted Content
  • ckeditor App
Admin Panel
  • list_display
  • list_filter
  • search_fields
Commands Practiced Today
python manage.py makemigrations

python manage.py migrate

python manage.py runserver

Assignment

Continue Developing the News Portal

Implement the same functionality covered in today's Blog Project using your News Portal.

  1. Create a NewsPost model with the following fields:
    • Id
    • NewsCategory (Foreign Key)
    • Title
    • Slug
    • Summary
    • Image
    • Description (RichTextField)
    • PublishDate
    • IsPublished
  2. Rename the database table to NewsPosts using the Meta class.
  3. Generate and apply migrations.
  4. Register the NewsPost model in the Django Admin Panel.
  5. Configure the Admin Panel with:
    • list_display
    • search_fields
    • list_filter
    • ordering
  6. Integrate CKEditor and use RichTextField for the Description field.
  7. Add at least five News Posts using the Django Admin Panel with images and formatted descriptions.
  8. Verify that uploaded images are stored inside the media/uploads folder and all records are successfully saved in the NewsPosts table.