django2: routing path syntax

Keywords: Python Django Mobile Database

Catalog

September 23. Django The 2.0a1 version has been released, which is a feature free version. If nothing unexpected happens, the 2.0 official version will not add new features. According to past rules, the official version is expected to be released in December.

Note: Django 2.0 was officially released on December 2. ( link)

2.0 is undoubtedly a milestone version. It has removed the support for Python 2.7. It needs at least 3.4 or above. It is recommended to use 3.5 or above.

What's new in Django2.0 Three new features are listed in the document:

  • Simpler URL routing syntax
  • Optimization and improvement of admin application for mobile devices (mobile friendly contrib. Admin)
  • Support SQL window expressions

The first feature is mainly used for dynamic route definition. In the implementation of Django 2.0 code, the main change is the addition of django.urls.path function, which allows a more concise and readable routing syntax. For example, the code of the previous version:

url(r'^articles/(?P[0-9]{4})/$', views.year_archive),

In the new version, it can also be written as:

path('articles//', views.year_archive),

The new syntax supports type conversion. In the above example, the year parameter received by the year archive function becomes an integer instead of a string.

If you have been exposed to the Flask framework, you will find that Variable-Rules Their grammatical forms and functions are similar.

1. Problem introduction

Here is a piece of code for Django1.X:

from django.conf.urls import url

def year_archive(request, year):
    year = int(year) # convert str to int
    # Get articles from database

def detail_view(request, article_id):
    pass

def edit_view(request, article_id):
    pass

def delete_view(request, article_id):
    pass

urlpatterns = [
    url('articles/(?P<year>[0-9]{4})/', year_archive),
    url('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),
    url('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),
    url('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),
]

Consider the following two questions:

The first problem is that the year parameter in the function year'archive is of string type, so it needs to be converted to the variable value of integer type first. Of course, year=int(year) will not have exceptions such as TypeError or ValueError. So is there a way to make this transformation step automatically completed by Django in url?

Second, in the three routes, the article UU ID represents the same field in the service, using the same regular expression, but you need to write it three times. After the article UU ID rule changes, you need to modify three codes at the same time. Is there a way to modify only one?

In Django 2.0, you can use path to solve the above two problems.

2. Use example

This is a simple example:

from django.urls import path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug>/', views.article_detail),
]

Basic rules:

  • Use angle brackets (< >) to capture values from the url.
  • The capture value can contain a converter type, such as' capture an integer variable '. If there is no converter, any strings will be matched, including the / 'character.
  • There is no need to add a leading slash.

Here is the basis 2.0 official documents The sample analysis table is as follows:

Request URL Match item View function call form
/articles/2005/03/ Third views.month_archive(request, year=2005, month=3)
/articles/2003/ First views.special_case_2003(request)
/articles/2003 nothing -
/articles/2003/03/building-a-django-site/ Fourth views.article_detail(request, year=2003, month=3, slug="building-a-django-site")

3.path converter

The original text of the document is Path converters, which will be translated into converters temporarily.

Django supports the following five converters by default:

  • str, matching non empty strings other than path separator (/), which is the default form
  • int, matches a positive integer, containing 0.
  • slug, which matches letters, numbers, and a string of horizontal bars and underscores.
  • uuid, match the formatted uuid, such as 075194d3-6885-417e-a8a8-6c931e272f00.
  • Path, matching any non empty string, containing the path separator

4. Custom converter

4.1 definition

For some complex or reuse needs, you can define your own converter. Converter is a class or interface, which requires three points:

  • regex class property, string type
  • to_python(self, value) method, value is the string matched by the class attribute regex, which returns the specific Python variable value for Django to pass to the corresponding view function.
  • to_url(self, value) method, contrary to to to_python, value is a specific Python variable value, which returns its string, usually used for URL reverse reference.

First, let's see how the default IntConverter and StringConverter are implemented:

class IntConverter:
    regex = '[0-9]+'

    def to_python(self, value):
        return int(value)

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


class StringConverter:
    regex = '[^/]+'

    def to_python(self, value):
        return value

    def to_url(self, value):
        return value

The second example is the 4-bit converter implemented by ourselves.

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

4.2 registration

Use register? Converter to register it to the URL configuration:

from django.urls import register_converter, path

from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<yyyy:year>/', views.year_archive),
    ...
]

5. Use regular expressions

If the above paths and converters still can not meet the requirements, regular expressions can also be used. In this case, django.urls.re_path function should be used.

In Python regular expressions, the naming grouping syntax is (? P pattern), where name is the name and pattern is the pattern to be matched.

The previous example code can also be written as:

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path('articles/(?P<year>[0-9]{4})/', views.year_archive),
    re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_archive),
    re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[^/]+)/', views.article_detail),
]

This code and the previous code realize basic functions, but there are some differences:

  • The code matching here is more strict. For example, year=10000 cannot be matched here.
  • The variables passed to the view function are all of string type, which is consistent with url.

Unnamed group

Generally speaking, it is not recommended to use this method, because it may introduce ambiguity or even error.

6.Import changes

django.urls.path can be regarded as an enhanced form of django.conf.urls.url.

For convenience, the reference path has also changed. Please note that the urls package path is no longer a sub package of conf. at present, like views and conf, it is considered as the core component of Django.

1.X 2.0 Remarks
- django.urls.path New, enhanced version of url
django.conf.urls.include django.urls.include Path change
django.conf.urls.url django.urls.re_path The same function with different names, the url will not be discarded immediately

7. Code rewriting

Using the new path function, the code in the "problem introduction" section can be rewritten as follows:

from django.urls import path, register_converter
from django.urls.converters import SlugConverter

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

register_converter(SlugConverter, 'article_id')
register_converter(FourDigitYearConverter, 'year')

def year_archive(request, year):
    print(type(year)) # <class 'int'>
    # Get articles from database

def detail_view(request, article_id):
    pass

def edit_view(request, article_id):
    pass

def delete_view(request, article_id):
    pass

urlpatterns = [
    path('articles/<year:year>/', year_archive),
    path('article/<article_id:article_id>/detail/', detail_view),
    path('articles/<article_id:article_id>/edit/', edit_view),
    path('articles/<article_id:article_id>/delete/', delete_view),
]

8. summary

First, the current process from url to View can be summarized into four steps:

  1. url matching
  2. Regular acquisition
  3. Variable type conversion
  4. View call

Django 2.0 has more variable type conversion steps than before.

Second, the new path syntax can solve the following scenarios:

  • Type auto conversion
  • Common regular expression

Posted by murali on Sun, 12 Jan 2020 01:50:56 -0800