Skip to content

Instantly share code, notes, and snippets.

@sesh
Created January 19, 2018 20:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sesh/0bd3604533043a81c2c1d08513848347 to your computer and use it in GitHub Desktop.
Save sesh/0bd3604533043a81c2c1d08513848347 to your computer and use it in GitHub Desktop.
Django URLs 2.0 (MelbDjango Talk)

Django URLs 2.0


Django 2.0

  • Released December, 2017
  • Major features:
    • Only supports Python 3.4 and above
    • Mobile-friendly admin interface
    • Simplified URL routing syntax

The old way

from django.conf.urls import url

urlpatterns = [
  url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]
  • Required users to understand regular expressions
  • Passes URL parameters as strings to your views

The new way

from django.urls import path

urlpatterns = [
  path('articles/<int:year>/', views.year_archive)
]
  • Simpler for new users (no more regex!)
  • Handles coercion into the designated type
  • Can be extended with ... functions

And you can still regex

from django.urls import re_path

urlpatterns = [
  # support date paths: /date/2018-01-18
  re_path(r'^date/(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})$', views.day_archive)
]
  • You can use django.urls.re_path to add regex-based URLs
  • (you can also just keep using the old url function)

The built in converters

int: Matches zero or any positive integer. Returns an int.

Old:

url(r'^posts/(?P<pk>[0-9]+)/$', views.post)

New:

path('posts/<int:pk>/', views.post)

The built in converters

str: Matches any non-empty string, excluding the path separator, '/'

Old:

url(r'^define/(?P<word>[^/]+)/$', views.define)

New:

path('posts/<str:word>/', views.define)

or

path('posts/<word>/', views.define)

The built in converters

uuid: Matches a formatted UUID.

Old:

url(r'^(?P<pk>\b[0-9a-f]{8}\b(-\b[0-9a-f]{4}\b){3}-\b[0-9a-f]{12}\b)$', views.post)

New:

path('<uuid:pk>/', views.post)

The built in converters

slug: Matches slugs compatible with SlugField

Old:

url(r'^posts/(?P<post_slug>[-\w]+)/$', views.post)

New:

path('posts/<slug:post_slug>/', views.post)

The built in converters

path: Matches any non-empty string, including the path separator, '/'.

Old:

url(r'^url/(?P<url>.+)/$', views.url_info)

New:

path('url/<path:url>', views.url_info)

Adding your own converter

  • Register custom converters with django.urls.register_converter

    • The documentation suggests doing this in your urls.py
  • register_converter takes two arguments:

    • A Converter
    • The "type name" used in the URL

isodate converter

import datetime
from django.urls import register_converter

class IsoDateConverter:
    regex = '\d{4}-\d{2}-\d{2}'

    def to_python(self, value):
        return datetime.datetime.strptime(value, '%Y-%m-%d').date()

    def to_url(self, value):
        return str(value)


register_converter(IsoDateConverter, 'isodate')

Custom conversion functions

  • The result of to_python will be passed to your view
  • If an exception is raised, the next URL pattern will be used
  • Simple to test:
def test_isodate(self):
    response = self.client.get('/url/2018-01-18/').json()
    self.assertEqual('isodate', response['url_name'])

That's it!

  • Follow me on Twitter: @sesh
  • Talk will be on https://brntn.me
  • I work at Thoughtworks now (it's great)

Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment