Python Slug Generation: Django, Flask and Vanilla Python Guide

Learn all methods of URL slug generation in Python. Create SEO-friendly URLs with Django slugify, python-slugify library, and custom functions.

What is a Slug in Python and Why Does It Matter?

A slug is the readable and SEO-friendly part of a URL. Creating slugs in Python is critical for search engine optimization of your web applications.

Method 1: Vanilla Python Slug Generation

Basic slug function without any libraries:

import re
import unicodedata

def slugify(text):
    # Convert Unicode characters to ASCII
    text = unicodedata.normalize('NFKD', text)
    text = text.encode('ascii', 'ignore').decode('ascii')
    
    # Convert to lowercase
    text = text.lower()
    
    # Replace non-alphanumeric characters with hyphens
    text = re.sub(r'[^a-z0-9]+', '-', text)
    
    # Remove leading and trailing hyphens
    text = text.strip('-')
    
    # Reduce multiple hyphens to single
    text = re.sub(r'-+', '-', text)
    
    return text

# Usage
print(slugify("Hello World! This is a test."))
# Output: hello-world-this-is-a-test

Method 2: python-slugify Library

Using python-slugify, the most popular slug library:

# Installation
pip install python-slugify

# Usage
from slugify import slugify

# Basic usage
slug = slugify("Hello World!")
print(slug)  # hello-world

# With special characters
slug = slugify("Café & Restaurant")
print(slug)  # cafe-restaurant

# Set maximum length
slug = slugify("This might be a very long title", max_length=20)
print(slug)  # this-might-be-a-very

# Word boundary truncation
slug = slugify("This is a long title", max_length=15, word_boundary=True)
print(slug)  # this-is-a-long

Method 3: Django's Built-in slugify

Using Django's built-in slugify function:

from django.utils.text import slugify

# Basic usage
slug = slugify("Hello World")
print(slug)  # hello-world

# With Unicode support
slug = slugify("Привет мир", allow_unicode=True)
print(slug)  # привет-мир

# Auto-slug in Model
from django.db import models
from django.utils.text import slugify

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

Method 4: Slugs in Flask Applications

Creating slugs in Flask projects:

from flask import Flask
from slugify import slugify
from werkzeug.utils import secure_filename

app = Flask(__name__)

def generate_slug(title):
    return slugify(title, max_length=60)

# Using in URL route
@app.route('/blog/')
def blog_post(slug):
    post = Post.query.filter_by(slug=slug).first_or_404()
    return render_template('post.html', post=post)

# SQLAlchemy model
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200))
    slug = db.Column(db.String(200), unique=True)
    
    def __init__(self, title):
        self.title = title
        self.slug = generate_slug(title)

Custom Solution for International Characters

Function for correctly converting international characters:

def international_slugify(text, char_map=None):
    # Default character mapping
    default_map = {
        'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss',
        'à': 'a', 'â': 'a', 'é': 'e', 'è': 'e', 'ê': 'e',
        'ñ': 'n', 'ç': 'c'
    }
    
    if char_map:
        default_map.update(char_map)
    
    # Convert special characters
    for special, replacement in default_map.items():
        text = text.replace(special, replacement)
    
    # Standard slugify process
    text = text.lower()
    text = re.sub(r'[^a-z0-9]+', '-', text)
    text = text.strip('-')
    text = re.sub(r'-+', '-', text)
    
    return text

# Test
print(international_slugify("Café München"))
# Output: cafe-muenchen

Generating Unique Slugs

Unique slug to prevent database collisions:

def generate_unique_slug(model_class, title, slug_field='slug'):
    base_slug = slugify(title, max_length=50)
    slug = base_slug
    counter = 1
    
    while model_class.objects.filter(**{slug_field: slug}).exists():
        slug = f"{base_slug}-{counter}"
        counter += 1
    
    return slug

# Usage
class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = generate_unique_slug(Article, self.title)
        super().save(*args, **kwargs)

Performance Tips

Conclusion

There are many methods to create slugs in Python. Depending on your project needs, you can use vanilla Python, python-slugify, or your framework's built-in functions. Remember to add special conversion functions for international characters.