Overview
Django 2.0, released on December 2, 2017, opens a new era for the framework by definitively dropping Python 2 support. Its most visible feature is the path() function which greatly simplifies URL routing by replacing regular expressions with type converters. This release also brings a mobile-friendly admin interface and Window expressions.
Key Features
path() simplifies URL routing
The path() function uses type converters (int, str, slug, uuid) instead of regular expressions. The old url() function remains available as re_path() for cases requiring regex.
from django.urls import path, re_path
from . import views
# Before (Django 1.x): regular expressions required
# url(r'^articles/(?P<year>[0-9]{4})/(?P<slug>[\w-]+)/$',
# views.article_detail),
# After (Django 2.0): readable type converters
urlpatterns = [
path('articles/', views.article_list, name='list'),
path('articles/<int:year>/', views.by_year, name='by_year'),
path('articles/<int:year>/<slug:slug>/', views.detail, name='detail'),
path('profile/<uuid:identifier>/', views.profile, name='profile'),
# re_path for complex cases
re_path(r'^archive/(?P<year>[0-9]{4})-(?P<month>[0-9]{2})/$',
views.monthly_archive),
]
Window expressions
Window expressions allow using SQL window functions (ROW_NUMBER, RANK, LAG, LEAD) directly in the Django ORM. They are especially useful for rankings, running totals, and comparisons between neighboring rows.
from django.db.models import F, Window
from django.db.models.functions import Rank, RowNumber, Lag
# Ranking salespersons by revenue
salespersons = Salesperson.objects.annotate(
ranking=Window(
expression=Rank(),
order_by=F('revenue').desc(),
)
)
for sp in salespersons:
print(f"#{sp.ranking} {sp.name}: {sp.revenue} EUR")
# Comparison with previous value (monthly sales)
sales = MonthlySale.objects.annotate(
previous_sale=Window(
expression=Lag('amount'),
order_by=F('month').asc(),
)
)
