Using Django's New path() Converters

python backend django

Django 2.0’s new path() function is one of the most visible changes in the release. Gone are the days of cryptic regex patterns—path converters make URL routing readable and maintainable.

The Old Way vs The New Way

Before (Django 1.x):

from django.conf.urls import url

urlpatterns = [
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.archive),
    url(r'^user/(?P<username>[\w.@+-]+)/$', views.profile),
]

After (Django 2.0):

from django.urls import path

urlpatterns = [
    path('articles/<int:year>/<int:month>/', views.archive),
    path('user/<str:username>/', views.profile),
]

The new syntax is self-documenting. You can read the URL pattern and immediately understand what it expects.

Built-in Path Converters

Django ships with five converters:

str (default)

Matches any non-empty string, excluding /.

path('category/<str:name>/', views.category)
# Matches: /category/electronics/
# Doesn't match: /category/home/garden/

int

Matches zero or any positive integer.

path('article/<int:id>/', views.article)
# Matches: /article/42/
# View receives: id=42 (as Python int)

slug

Matches ASCII letters, numbers, hyphens, and underscores.

path('post/<slug:slug>/', views.post)
# Matches: /post/my-first-post/
# Matches: /post/hello_world_123/

uuid

Matches formatted UUID strings.

path('document/<uuid:doc_id>/', views.document)
# Matches: /document/075194d3-6885-417e-a8a8-6c931e272f00/
# View receives: doc_id as Python UUID object

path

Matches any non-empty string, including /.

path('files/<path:filepath>/', views.serve_file)
# Matches: /files/documents/reports/2018/q1.pdf
# View receives: filepath="documents/reports/2018/q1.pdf"

Custom Path Converters

When built-in converters aren’t enough, create your own:

# converters.py
class YearConverter:
    regex = '[0-9]{4}'
    
    def to_python(self, value):
        return int(value)
    
    def to_url(self, value):
        return str(value)

class FourLetterCodeConverter:
    regex = '[A-Z]{4}'
    
    def to_python(self, value):
        return value
    
    def to_url(self, value):
        return value

Register and use them:

# urls.py
from django.urls import path, register_converter
from . import converters, views

register_converter(converters.YearConverter, 'yyyy')
register_converter(converters.FourLetterCodeConverter, 'code')

urlpatterns = [
    path('archive/<yyyy:year>/', views.year_archive),
    path('airport/<code:iata>/', views.airport_detail),
]

When to Use re_path()

For complex patterns that converters can’t handle, re_path() still supports full regex:

from django.urls import re_path

urlpatterns = [
    # Match dates in multiple formats
    re_path(
        r'^events/(?P<date>\d{4}-\d{2}-\d{2}|\d{2}/\d{2}/\d{4})/$',
        views.event_by_date
    ),
    
    # Optional trailing component
    re_path(
        r'^api/v(?P<version>[0-9]+)/(?P<endpoint>.*)$',
        views.api_dispatch
    ),
]

Use re_path() sparingly. If you find yourself reaching for it often, consider whether your URL design could be simplified.

Migration Tips

When migrating from Django 1.x:

  1. Start with simple patterns: Convert straightforward URLs first
  2. Test thoroughly: URL routing bugs are subtle
  3. Use reverse(): Ensure URL reversing still works
  4. Keep re_path() as fallback: Don’t force complex patterns into path()
# Migration script approach
from django.urls import path, re_path

urlpatterns = [
    # Easy conversions
    path('home/', views.home),
    path('about/', views.about),
    path('article/<int:id>/', views.article),
    
    # Keep complex patterns as re_path for now
    re_path(r'^legacy/(?P<path>.*)$', views.legacy_redirect),
]

Best Practices

  1. Prefer path() over re_path(): Unless you need regex features
  2. Use semantic converters: <int:article_id> not <int:id>
  3. Create custom converters: For domain-specific patterns
  4. Document complex URLs: Comments help future maintainers

Final Thoughts

Path converters make Django URLs more Pythonic. They’re easier to read, harder to get wrong, and encourage cleaner URL design.

Take the time to migrate your URL configs. Your future self will thank you.


Clean URLs reflect clean architecture.

All posts