Creating Slugs in Django

Django slugs are a way to create SEO-friendly URLs for your web application. Instead of having URLs with unreadable ID numbers like /blog/post/12345/, you can create human-readable URLs like /blog/my-first-post/ using slugs. Slug make your content more discoverable and your URLs more readable. In this post, I’ll walk through how to add slugs to your Django models and views.

First, What is a Slug?

A slug is a short label that contains only letters, numbers, underscores, or hyphens. Slug are generally used in URLs to identify and describe a resource. For example, in a URL like https://website.com/blog/how-to-install-django/, “how-to-install-django” is the slug.

Slugs are beneficial because they can:

  • Make URLs more readable and meaningful for users
  • Be more recognizable than IDs for search the engines and users
  • Be changed without breaking external links to content

Adding Slugs to Django Models

To add a slug field in Django, you need to import and use the SlugField model field type. Here is an example Article model with a slug:

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

class Article(models.Model):
  title = models.CharField(max_length=255)
  content = models.TextField()
  slug = models.SlugField(max_length=255, unique=True)

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

The slugify() function will generate a URL-safe slug from a given string, normally the title. This ensures our slugs are created automatically from the model title.

The slug is set as unique so there will never be duplicate slug for different articles. You can also add other slug constraints like db_index=True if needed.

Generating Slugs in Views

Another approach is to generate the slug in the view rather than the model. Here is an example:

from django.utils.text import slugify

def create_article(request):

  # Generate slug from title 
  slug = slugify(request.POST['title'])

  new_article = Article(
    title = request.POST['title'], 
    content = request.POST['content'],
    slug = slug
  )

  new_article.save()

  return HttpResponseRedirect('/articles/' + slug)

This allows more flexibility in how the slug is created, like excluding certain characters or manually setting it. The downside is you need to handle slug generation in the view.

Using Slugs in URLs

Once you have slug on your model, you need to update your URLs to use them. Replace IDs with slugs:

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

urlpatterns = [
  path('articles/<slug:slug>/', article_detail, name='article-detail'),
]

Then in views, you can query the Article model using the slug parameter instead of the ID:

def article_detail(request, slug):
  article = Article.objects.get(slug=slug)
  context = {'article': article}
  return render(request, 'article_detail.html', context)

This allows looking up the article by readable slug instead of a numeric ID.

Conclusion

Adding slugs is a quick way to improve the readability, consistency, and SEO of your Django URLs. By following conventions and keeping slug short and descriptive, you can make your URLs easy for users to read, type, and share. Slugs do require some extra work to ensure the uniqueness and handle slug changes, but overall provide a major improvement over numeric IDs in URLs.