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-testMethod 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-longMethod 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-muenchenGenerating 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
- Generate slug once: Don't recalculate on every request
- Index in database: Add index to slug field
- Use caching: Cache frequently accessed slugs
- Set length limit: Don't exceed 60 characters
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.