Add Slug Field

Create SEO-friendly URLs in Django

🔗 What is a Slug Field?

A slug is a URL-friendly version of text, containing only letters, numbers, hyphens, and underscores. Slugs make URLs readable and SEO-friendly, like "my-first-post" instead of "123".


from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
                                    

Slug Benefits

🔍

SEO Friendly

Better search engine rankings

Readable URLs Keywords
👤

User Friendly

Easy to read and remember

Clean URLs Shareable
🔒

Unique IDs

Identify resources uniquely

No Duplicates Permanent

Performance

Indexed database lookups

Fast Queries Efficient

🔹 Add Slug to Model

Add a SlugField to your Django model to store URL-friendly versions of titles. The unique=True parameter ensures no two objects have the same slug.

# models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

URL Example:

Before: /post/123/

After: /post/my-awesome-article/

🔹 Auto-Generate Slug

Automatically create slugs from titles using Django's slugify function. Override the save method to generate slugs when creating new objects without manual input.

# models.py
from django.db import models
from django.utils.text import slugify

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True, blank=True)
    content = models.TextField()
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)
    
    def __str__(self):
        return self.title

Example:

Title: "My First Blog Post!"

Slug: "my-first-blog-post"

🔹 Handle Duplicate Slugs

Prevent duplicate slug errors by adding numbers to make each slug unique. This ensures that posts with similar titles get different slugs automatically.

# models.py
from django.db import models
from django.utils.text import slugify

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True, blank=True)
    content = models.TextField()
    
    def save(self, *args, **kwargs):
        if not self.slug:
            base_slug = slugify(self.title)
            slug = base_slug
            counter = 1
            
            while Post.objects.filter(slug=slug).exists():
                slug = f"{base_slug}-{counter}"
                counter += 1
            
            self.slug = slug
        super().save(*args, **kwargs)

Example:

Post 1: "hello-world"

Post 2: "hello-world-1"

Post 3: "hello-world-2"

🔹 Use Slug in URLs

Configure your URL patterns to use slugs instead of numeric IDs. This creates clean, readable URLs that are better for SEO and user experience.

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('post/<slug:slug>/', views.post_detail, name='post_detail'),
]
# views.py
from django.shortcuts import render, get_object_or_404
from .models import Post

def post_detail(request, slug):
    post = get_object_or_404(Post, slug=slug)
    return render(request, 'post_detail.html', {'post': post})

🔹 Display Slug in Admin

Configure Django admin to automatically populate the slug field based on the title. The prepopulated_fields option creates the slug as you type the title.

# admin.py
from django.contrib import admin
from .models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'slug', 'created_at']
    prepopulated_fields = {'slug': ('title',)}
    search_fields = ['title', 'content']

Admin Features:

  • Auto-fill slug as you type title
  • Edit slug manually if needed
  • See slug in list view
  • Search by slug

🔹 Run Migrations

After adding the slug field to your model, create and apply migrations to update your database schema with the new field.

# Create migration
python manage.py makemigrations

# Apply migration
python manage.py migrate

Output:

✓ Migrations for 'blog':

0002_post_slug.py

✓ Running migrations: OK

🧠 Test Your Knowledge

What does slugify("Hello World!") return?