Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Configuring URL Routing in Django

Tech 2

URL Configuration

URL routing in Django maps URL patterns to view functions. This mapping is defined in a URL configuration file.

# Basic format
from django.conf.urls import url

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^author/', views.author),
]

Key points:

  • Once a route matches, subsequent patterns are not evaluated.
  • For a URL like "127.0.0.1:8000/author", Django first tries to match without a trailing slash, then with one.
  • Exact matching uses "^" and "$", e.g., "^author/$".
  • A homepage route can be added with url(r"^$", views.home).
  • A catch-all route uses url(r"", views.error).

Named and Unnamed Group Matching

Unnamed Groups

# urls.py
url(r'^author/([0-9]{4})/$', views.author),

# views.py
def author(request, year_value):
    pass
# The value from parentheses is passed as a positional argument to year_value.

Named Groups

# urls.py
url(r'^author/(?P<year>\d+)/$', views.author),

# views.py
def author(request, year):
    pass
# The value is passed as a keyword argument named year.

Important: Named and unnamed groups cannot be mixed in the same pattern. Both support multiple parameters.

URL Matching Behavior

URL matching does not consider request methods or query parameters. For example, "127.0.0.1:8080/login/?name=sun&pwd=123" only matches "login/".

Parameter Types

Parameters captured from groups are always strings. For instance, accessing "127.0.0.1:8080/book/2016" yields year='2016' as a string.

Default Values in Views

# urls.py
from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py
def page(request, num="1"):
    pass
# Accessing 127.0.0.1:8080/blog/ gives num='1'.
# Accessing 127.0.0.1:8080/blog/4/ gives num='4'.

Passing Extra Arguments to Views

# urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.archive, {'extra_param': 'value'}),
]

# views.py
def archive(request, year, extra_param):
    pass
# Accessing 127.0.0.1:8080/blog/2014 executes archive(request, year='2014', extra_param="value").

URL Reverse Resolution

Assigning names to URLs allows reverse lookup, enabling dynamic URL generation without hardcoding paths.

Basic Reverse Resolution

# urls.py
url(r"^testadd213123/$", views.testadd, name="testadd")

# Backend reverse
from django.shortcuts import reverse
result = reverse("testadd")  # Returns "/testadd213123/"

# Frontend reverse in templates
<a href="{% url 'testadd' %}">Add</a>
# Renders as <a href="/testadd213123/">Add</a>

Reverse with Unnamed Groups

# urls.py
url(r"^testadd213123/(\d+)$", views.testadd, name="testadd")

# Backend reverse
def testadd(request, identifier):
    result = reverse("testadd", args=(identifier,))

# Frontend reverse
<a href="{% url 'testadd' 123 %}">Add</a>
# Renders as <a href="/testadd213123/123/">Add</a>

Reverse with Named Groups

# urls.py
url(r"^testadd213123/(?P<year>\d+)$", views.testadd, name="testadd")

# Backend reverse methods
def testadd(request, year):
    result1 = reverse("testadd", args=(year,))
    result2 = reverse("testadd", kwargs={"year": year})

# Frontend reverse
<a href="{% url 'testadd' year %}">Add</a>
# Renders as <a href="/testadd213123/2012/">Add</a>

URL Dispatching

Central routing can delegate to app-specific URL configurations for better organization.

# Main urls.py
from django.conf.urls import include

urlpatterns = [
    url(r'^app01/', include("app01.urls")),
    url(r'^app02/', include("app02.urls")),
]

# app01/urls.py
from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/', views.index, name="index")
]

# app02/urls.py
from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^index/', views.index, name="index")
]

To avoid conflicts in reverse resolution when apps have identical URL names:

  • Use namespaces:
    url(r'^app01/', include("app01.urls", namespace='app01')),
    url(r'^app02/', include("app02.urls", namespace='app02'))
    # Reverse with reverse('app01:index')
    
  • Use distinct names:
    # In app01/urls.py: name="app01_index"
    # In app02/urls.py: name="app02_index"
    

Pseudo-Static URLs

Adding ".html" suffixes to URLs can make them appear static, potentially improving SEO by mimicking static file paths while still being processed dynamically.

Python Virtual Environments

Virtual environments isolate project dependencies, ensuring each project uses its specific interpreter and modules. This improves efficiency and prevents conflicts.

Django 1.x vs 2.x Differences

Key Chenges

  • In Django 1.x, url is used; in 2.x, re_path serves a similar role for regex patterns.
  • Django 2.x introduces path for simpler, non-regex URL matching.
  • Parameters in Django 1.x are always strings; Django 2.x can convert types.
  • Foreign key creation in Django 2.x requires on_delete=models.CASCADE.

Django 2.x Path Converters

from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('index/', views.index, name="index"),
    re_path(r"^edit/(\d+)/$", views.edit),
]

Built-in converters in path:

  • str: Matches any non-empty string except "/".
  • int: Matches zero or positive integers.
  • slug: Matches ASCII letters, numbers, hyphens, and underscores.
  • uuid: Matches formatted UUIDs.
  • path: Matches any non-empty string, including "/".

Example:

from django.urls import path
from app01 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),
]

Custom Conevrters

class FourDigitYearConverter:
    regex = '[0-9]{4}'
    def to_python(self, value):
        return int(value)
    def to_url(self, value):
        return '%04d' % value

# Register and use
from django.urls import register_converter, path
from app01 import views

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

# views.py
def year_archive(request, year):
    pass  # year is an integer
Tags: Django

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.