Chapter 15: Django Update Model

Grab your second cup of chai because we’re now diving deep into updating models in Django — not just updating data (records), but actually changing the structure of your models themselves (adding fields, changing types, renaming columns, adding relationships, etc.).

This is a very different topic from the previous “update data” lesson.

Today we are talking about:

How to safely evolve your database schema when your app requirements change (adding a new field, making a field nullable, changing max_length, adding indexes, splitting models, etc.)

This process is called migrations — and it’s one of the most powerful (and sometimes most frustrating) features of Django.

We will go very slowly, step by step, like I’m sitting next to you in Gachibowli looking at your screen, explaining every decision, every warning message, and every common panic moment beginners face.

Current Situation (Your Starting Point)

You already have these models in polls/models.py:

Python

And you have already run makemigrations and migrate at least once → you have migration file 0001_initial.py.

Now the business requirements change (very realistic scenario):

  1. We want to add a category field to Question (e.g. “fun”, “politics”, “sports”)
  2. We want question_text to allow longer questions (change max_length from 200 → 500)
  3. We want to add an is_active boolean field (default True)
  4. We want to add a slug field for SEO-friendly URLs (unique per question)
  5. Later we might rename votes to vote_count

Let’s do all of this safely.

Step 1: Never Edit the Database Manually – Always Use Migrations

Rule #1 in Django (especially in production):

Do NOT touch db.sqlite3 or run SQL directly → Always change models.py → create migration → apply migration

Step 2: Make the Model Changes (Edit polls/models.py)

Add / modify fields:

Python

Important notes about changes we made:

  • max_length=500 → non-destructive (safe)
  • New category with choices= → very nice for admin dropdown
  • slug with unique=True → needs careful migration
  • Overrode .save() → auto-generate slug (common pattern)

Step 3: Create the Migration File

Bash

You will probably see something like this:

text

Open the generated file (polls/migrations/0002_….py)

It will look roughly like this:

Python

Very common question: “Why is slug blank=True even though unique=True?”

→ Because existing rows don’t have slug yet → we must allow NULL/blank during migration, then populate them.

Step 4: Data Migration – Populate Slug for Existing Rows

We need to fill slug for old questions before making it non-nullable / enforcing uniqueness fully.

Create an empty data migration:

Bash

Open the new file (e.g. 0003_populate_slugs.py) and edit it:

Python

Now run:

Bash

→ Django:

  1. Adds new fields (nullable/blank)
  2. Runs your Python code to fill slugs
  3. Applies other changes

Step 5: Make Slug Non-Blank & Enforce Uniqueness Fully (Optional Next Step)

Later you can:

Python

Then:

Bash

But first you must ensure no duplicates — otherwise migration will fail.

Step 6: Rename Field Example (votes → vote_count)

Change in model:

Python

Run:

Bash

Django detects rename → asks you:

text

Type y → it creates RenameField operation (preserves data!)

Common Panic Situations & Fixes (Real Stories)

  1. “You cannot add a non-nullable field without default”

    → Add default=… or make field null=True, blank=True first

  2. “UNIQUE constraint failed” on slug

    → Duplicate slugs → run data migration to make unique (append -2, -3 etc.)

  3. “Cannot ALTER TABLE because it has pending trigger” (PostgreSQL)

    → Rare – usually means conflicting migrations → fake migration or squash

  4. “Table already exists” after reset

    → Deleted db.sqlite3 but not migrations folder → delete migrations/000* + db.sqlite3 → start fresh

Quick Checklist Before Every Migrate

  • Read the migration file (showmigrations + open it)
  • Run python manage.py makemigrations –dry-run –verbosity 3 (preview)
  • Always backup db in production
  • Test on copy of production data if possible

Your Homework

  1. Add the fields I showed (category, is_active, slug)
  2. Create & run the data migration for slugs
  3. Visit admin → see new fields
  4. Try renaming votes to vote_count
  5. Update your detail template to show {{ question.category }} and {{ question.slug }}

Tell me:

  • “It worked — show me how to add ManyToManyField next”
  • “Migration failed with XXX error — here is the message”
  • “How to squash migrations (clean up old files)?”
  • “Explain makemigrations –merge”
  • Or next big topic: “Django Forms & ModelForm”

You’re now officially dangerous with migrations — that’s when real Django development begins! 💪🚀

Keep going — you’re doing awesome! 🇮🇳

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *