Django Http Requests

Django shortcut functions

Django Generic views

http://docs.djangoproject.com/en/dev/topics/http/

Introduction

The contents of the page are produced by a view function, and the URL is specified in a URLconf. A view is just a Python function that takes an HttpRequest as its first parameter and returns an instance of HttpResponse.

view.py example:

from django.http import HttpResponse #1
 
def hello(request): #2
    return HttpResponse("Hello world") #3
  1. First, we import the class HttpResponse, which lives in the django.http module. We need to import this class because it’s used later in our code.
  2. Next, we define a function called hello — the view function. Each view function takes at least one parameter, called request by convention. This is an object that contains information about the current Web request that has triggered this view, and it’s an instance of the class django.http.HttpRequest.
  3. The function is a simple one-liner: it merely returns an HttpResponse object that has been instantiated with the text "Hello world".

URLconf

  • A URLconf is like a table of contents for your Django-powered Web site. Basically, it’s a mapping between URLs and the view functions that should be called for those URLs.
from django.conf.urls.defaults import * #1
from mysite.views import hello #2
 
urlpatterns = patterns('', #3
    ('^hello/$', hello),
)
  1. The first line imports all objects from the django.conf.urls.defaults module, which is Django’s URLconf infrastructure. This includes a function called patterns.
  2. We import the hello view from its module — mysite/views.py, which translates into mysite.views in Python import syntax.
  3. The second line calls the function patterns and saves the result into a variable called urlpatterns.

**urlpatterns ** is a sequence of tuples in the following format:

(regular expression, Python callback function [, optional dictionary])

Simplifying the URLconfs

Instead of writing this

urlpatterns = patterns('',
    (r'^polls/$', 'mysite.polls.views.index'),
    (r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'),
    (r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'),
    (r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
)

the URLconf framework provides a shortcut for common prefixes. You can factor out the common prefixes and add them as the first argument to patterns(), like so:

urlpatterns = patterns('mysite.polls.views',
    (r'^polls/$', 'index'),
    (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
    (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
    (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
)

Streamlining Function Imports

Example 1: Each entry in the URLconf includes its associated view function, passed directly as a function object. This means it’s necessary to import the view functions at the top of the module. But as a Django application grows in complexity, its URLconf grows, too, and keeping those imports can be tedious to manage.

from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^hello/$', views.hello),
    (r'^time/$', views.current_datetime),
    (r'^time/plus/(d{1,2})/$', views.hours_ahead),
)

Example 2: It’s possible to avoid that tedium by importing the views module itself.

from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^hello/$', views.hello),
    (r'^time/$', views.current_datetime),
    (r'^time/plus/(d{1,2})/$', views.hours_ahead),
)

Example 3: Django offers another way of specifying the view function for a particular pattern in the URLconf: you can pass a string containing the module name and function name rather than the function object itself.

from django.conf.urls.defaults import *
 
urlpatterns = patterns('',
    (r'^hello/$', 'mysite.views.hello'),
    (r'^time/$', 'mysite.views.current_datetime'),
    (r'^time/plus/(d{1,2})/$', 'mysite.views.hours_ahead'),
)

Example 4: A further shortcut you can take when using the string technique is to factor out a common “view prefix.” . We can factor out that common prefix and pass it as the first argument to patterns().

from django.conf.urls.defaults import *
 
urlpatterns = patterns('mysite.views',
    (r'^hello/$', 'hello'),
    (r'^time/$', 'current_datetime'),
    (r'^time/plus/(d{1,2})/$', 'hours_ahead'),
)

Using Multiple View Prefixes

  • If you use the string technique, you’ll probably end up mixing views to the point where the views in your URLconf won’t have a common prefix.
  • To avoid this you can add multiple patterns() objects together.

Example: Old

from django.conf.urls.defaults import *
 
urlpatterns = patterns('',
    (r'^hello/$', 'mysite.views.hello'),
    (r'^time/$', 'mysite.views.current_datetime'),
    (r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'),
    (r'^tag/(\w+)/$', 'weblog.views.tag'),
)
from django.conf.urls.defaults import *
 
urlpatterns = patterns('mysite.views',
    (r'^hello/$', 'hello'),
    (r'^time/$', 'current_datetime'),
    (r'^time/plus/(\d{1,2})/$', 'hours_ahead'),
)
 
urlpatterns += patterns('weblog.views',
    (r'^tag/(\w+)/$', 'tag'),
)

Special-Casing URLs in Debug Mode

Example: To alter your URLconf’s behavior while in Django’s debug mode you can do the following. In this example, the URL /debuginfo/ will only be available if your DEBUG setting is set to True.

from django.conf import settings
from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^$', views.homepage),
    (r'^(\d{4})/([a-z]{3})/$', views.archive_month),
)
 
if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^debuginfo/$', views.debug),
    )

Using Named Groups

  • It’s possible to use named regular expression groups to capture URL bits and pass them as keyword arguments to a view.
  • In Python regular expressions, the syntax for named regular expression groups is ?P<name>pattern, where name is the name of the group and pattern is some pattern to match.

So instead of writing

from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^articles/(\d{4})/$', views.year_archive),
    (r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
)

you can write

from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^articles/(?P<year>\d{4})/$', views.year_archive),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)

Understanding the Matching/Grouping Algorithm

  • If there are any named arguments, it will use those, ignoring non-named arguments.
  • Otherwise, it will pass all non-named arguments as positional arguments.
  • In both cases, it will pass any extra options as keyword arguments.

Passing Extra Options to View Functions

Example: You have two views whose contents are identical except for the template they use.

# urls.py
 
from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^foo/$', views.foo_view),
    (r'^bar/$', views.bar_view),
)
 
# views.py
 
from django.shortcuts import render_to_response
from mysite.models import MyModel
 
def foo_view(request):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response('template1.html', {'m_list': m_list})
 
def bar_view(request):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response('template2.html', {'m_list': m_list})

to remove the redundancy we could use the same view for both URLs, putting parentheses around the URL to capture it, and checking the URL within the view to determine the template.

# urls.py
 
from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^(foo)/$', views.foobar_view),
    (r'^(bar)/$', views.foobar_view),
)
 
# views.py
 
from django.shortcuts import render_to_response
from mysite.models import MyModel
 
def foobar_view(request, url):
    m_list = MyModel.objects.filter(is_new=True)
    if url == 'foo':
        template_name = 'template1.html'
    elif url == 'bar':
        template_name = 'template2.html'
    return render_to_response(template_name, {'m_list': m_list})

The problem with that solution, though, is that it couples your URLs to your code.

Better solution: Each pattern in a URLconf may include a third item: a dictionary of keyword arguments to pass to the view function.

# urls.py
 
from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
    (r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
)
 
# views.py
 
from django.shortcuts import render_to_response
from mysite.models import MyModel
 
def foobar_view(request, template_name):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response(template_name, {'m_list': m_list})
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.