← Back to all tutorials
Django TutorialEpisode 32

Slugifying the Title

Auto-generate URL slugs from article titles — use Django slugify to create clean, URL-friendly strings when articles are saved.

Slugifying the Title

Typing a slug manually for every article is tedious. Let us auto-generate the slug from the title when the article is saved.

Using Django slugify

from django.utils.text import slugify

slugify('My First Blog Post')
# Returns: 'my-first-blog-post'

slugify('Hello World! #2')
# Returns: 'hello-world-2'

Auto-Slugify on Save

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

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(blank=True)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    thumb = models.ImageField(default='default.png', blank=True)
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE, default=None)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def __str__(self):
        return self.title

    def snippet(self):
        return self.body[:50] + '...'

How It Works

article = Article(title='My Second Post', body='Content...')
article.save()

print(article.slug)  # 'my-second-post'

Removing Slug from the Form

# articles/forms.py
class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'body', 'thumb']  # No slug field needed!

Since the slug is auto-generated, you can remove it from the form. Users only need to enter the title.

Handling Duplicates

def save(self, *args, **kwargs):
    self.slug = slugify(self.title)
    # Ensure uniqueness
    original_slug = self.slug
    counter = 1
    while Article.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
        self.slug = f'{original_slug}-{counter}'
        counter += 1
    super().save(*args, **kwargs)

If two articles have the same title, the duplicate gets a number appended: my-post, my-post-1, my-post-2.

Series Complete

Congratulations! You have built a complete Django blog with:

FeatureImplementation
Project structureDjango project with articles and accounts apps
DatabaseModels, migrations, ORM queries
TemplatesTemplate tags, inheritance, static files
AuthenticationSignup, login, logout, login_required
CRUDCreate and read articles with ModelForm
MediaImage uploads with ImageField
URLsNamed URLs, URL parameters, slugs
StylingProfessional CSS with responsive design

Key Takeaways

  • slugify() converts any string to a URL-friendly slug
  • Override save() on the model to auto-generate slugs
  • Handle duplicate slugs by appending a counter
  • Remove the slug field from forms since it is auto-generated