My name is Brenton Cleeland and I'm a web developer in Melbourne, Australia. Currently working as a Consultant at ThoughtWorks.

Brenton Cleeland

Posts, Projects & Talks

A smattering of content I've created over the last few years.

Most of my other talks and intro slides from the first 3 years of MelbDjango are availble on my account. I have a whole bunch of open-source personal projects on GitHub.

I post updates down below
Which sometimes post to @sesh on Twitter

Slides from my presentation at MelbDjango in January 2018 on the changes to URLs in Django 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.





The built in converters

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


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


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


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

The built in converters

uuid: Matches a formatted UUID.





The built in converters

slug: Matches slugs compatible with SlugField





The built in converters

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


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


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
  • 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
  • I work at Thoughtworks now (it's great)