SlideShare a Scribd company logo
The 
Django 
Book 
Chapter 
8: 
Advanced 
Views 
and 
URLconfs 
Speaker: 
Vincent 
Chien
advantage of this in several ways, as described in the sections that follow. 
from django.conf.urls.defaults import * 
from mysite.views import hello, current_datetime, hours_ahead 
Streamlining 
Function 
Imports 
9.1.1 Streamlining Function Imports 
Consider this URLconf, which builds on the example in Chapter 3: 
from django.conf.urls.defaults import * 
from mysite.views import hello, current_datetime, hours_ahead 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^hello/$โ€™, hello), 
(rโ€™^time/$โ€™, current_datetime), 
(rโ€™^time/plus/(d{1,2})/$โ€™, hours_ahead), 
) 
As urlpatterns explained in = Chapter patterns(โ€™โ€™, 
3, each entry in the URLconf includes its associated view function, function (rโ€™^object. hello/$โ€™, This means hello), 
itโ€™s necessary to import the view functions at the top of the module. 
But as (a rโ€™^Django time/$โ€™, application current_datetime), 
(rโ€™^time/plus/(d{grows 1,2})/$โ€™, in complexity, hours_its ahead), 
URLconf grows, too, and keeping those imports manage. (For each new view function, you have to remember to import it, and the import statement long if you use this approach.) Itโ€™s possible to avoid that tedium by importing the views module URLconf is equivalent to the previous one: 
from django.conf.urls.defaults import * 
from mysite import views 
) 
As explained in Chapter 3, each entry in the URLconf includes its associated view function, 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 manage. (For each new view function, you have to remember to import it, and the import statement long if you use this approach.) Itโ€™s possible to avoid that tedium by importing the views module URLconf is equivalent to the previous one: 
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), 
) 
urlpatterns = patterns(โ€˜โ€™,
string containing the module name and function name rather than the function object itself. Continuing example: 
from django.conf.urls.defaults import * 
DSjantgro Beooak Dmocumlienntatiionn, Rgel 
eaFseu0.1nction 
Imports 
urlpatterns = patterns(โ€˜โ€™, 
(rโ€™^hello/$โ€™, โ€˜mysite.views.helloโ€™), 
(rโ€™^time/$โ€™, โ€˜mysite.views.current_datetimeโ€™), 
(rโ€™^time/plus/(d{1,2})/$โ€™, โ€˜mysite.views.hours_aheadโ€™), 
Django 
offers 
another 
way 
of 
specifying 
the 
view 
funcAon 
for 
a 
parAcular 
) 
Note that you donโ€™t put a trailing dot (".") in the prefix, nor do you put a leading dot in the view strings. Django paCern 
offers in 
the 
another URLconf: 
way of you 
specifying can 
pass 
the a 
view string 
function containing 
for a particular the 
module 
pattern name 
in the URLconf: you can string and 
funccontaining Aon 
name 
the module rather 
name than 
and the 
function funcAon 
name object 
rather itself. 
than the function object itself. Continuing the ongoing 
example: 
from django.conf.urls.defaults import * 
) 
(Note the quotes around the view names. Weโ€™re using โ€™mysite.views.current_datetimeโ€™ instead of mysite.views.current_datetime.) 
Using urlpatterns this technique, = patterns(โ€˜โ€™, 
itโ€™s no longer necessary to import the view functions; Django automatically (rโ€™^hello/$โ€™, โ€˜mysite.views.helloโ€™), 
(rโ€™^view time/$โ€™, function โ€˜the mysite.first time views.itโ€™s needed, current_according datetimeโ€™), 
to the string describing the name and path function. 
(rโ€™^time/plus/(d{1,2})/$โ€™, โ€˜mysite.views.hours_aheadโ€™), 
A further shortcut you can take when using the string technique is to factor out a common โ€œview URLconf example, each of the view strings starts with โ€™mysite.viewsโ€™, which is redundant to factor out that common prefix and pass it as the first argument to patterns(), like this: 
from django.conf.urls.defaults import * 
) 
(Note the quotes around the view names. Weโ€™re using โ€™mysite.views.current_datetimeโ€™ โ€“ with quotes instead factor 
of out 
mysite.a 
common 
views.โ€œview 
current_prefix.โ€ 
datetime.) 
Using this technique, itโ€™s no longer necessary to import the view functions; Django automatically imports view function the first time itโ€™s needed, according to the string describing the name and path of the function. 
A further shortcut you can take when using the string technique is to factor out a common โ€œview prefix.โ€ URLconf example, each of the view strings starts with โ€™mysite.viewsโ€™, which is redundant to type. We factor out that common prefix and pass it as the first argument to patterns(), like this: 
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 
Pre>iDxjanegosB 
ook Documentation, from django.conf.urls.defaults import * 
= 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โ€™), 
OLD 
) 
New: 
NEW 
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โ€™), 
) 
Django Book Documentation, Release 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โ€™), 
) 
New: 
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โ€™), 
)
9.1.3 Special-Casing URLs in Debug Mode 
Special-ยญโ€Casing 
URLs 
in 
Debug 
Speaking of constructing urlpatterns dynamically, you might want to take advantage your runtime, Mode 
URLconfโ€™s behavior while in Djangoโ€™s debug mode. To do this, just check the like so: 
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), 
) 
In this example, the URL /debuginfo/ will only be available if your DEBUG setting 9.1.4 Using Named Groups
Keyword Arguments vs. Positional Arguments 
A Python function can be called using keyword arguments or positional arguments โ€“ and, in some cases, both at same time. In a keyword argument call, you specify the names of the arguments along with the values youโ€™re passing. 
In a positional argument call, you simply pass the arguments without explicitly specifying which argument matches 
which value; the association is implicit in the argumentsโ€™ order. 
For example, consider this simple function: 
def sell(item, price, quantity): 
A Python function can be called using keyword arguments or positional arguments โ€“ and, in some cases, same time. In a keyword argument call, you specify the names of the arguments along with the values In a positional argument call, you simply pass the arguments without explicitly specifying which argument which value; the association is implicit in the argumentsโ€™ order. 
For example, consider this simple function: 
def sell(item, price, quantity): 
same In a positional time. In a argument keyword argument call, you simply call, you pass specify the arguments the names without of the arguments explicitly specifying along with which the values argument In which a positional value; the argument association call, is you implicit simply in the pass argumentsโ€™ the arguments order. 
without explicitly specifying which argument which For example, value; the consider association this simple is implicit function: 
in the argumentsโ€™ order. 
For example, consider this simple function: 
def sell(item, price, quantity): 
def sell(item, price, quantity): 
Using 
Named 
Groups 
print "Selling %s unit(s) of %s at %s" % (quantity, item, price) 
print "Selling %s unit(s) of %s at %s" % (quantity, item, price) 
To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) 
To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: 
sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) 
sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) 
sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) 
sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) 
Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
print print "Selling "Selling %s %unit(s unit(s) of s) %s of at %s %s" at % %(s" quantity, % (quantity, item, price) 
item, price) 
call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) 
To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: 
To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) 
To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: 
sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) 
sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) 
sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) 
sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) 
Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed in the function 
definition: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) 
To call it with keyword arguments, you specify the names of the arguments along with the values. The following 
PosiAonal 
Arguments 
Keyword 
Arguements 
are equivalent: 
sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(item=โ€™item=โ€™Socksโ€™, Socksโ€™, quantity=price=โ€™$6, 2.50โ€™, price=โ€™$quantity=2.50โ€™) 
6) 
sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) 
sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) 
sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) 
sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) 
Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed before keyword 
arguments. The following statements are equivalent to the previous examples: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) 
sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) 
sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) 
sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) 
Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: 
sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
Mix 
In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern), where 
In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern),
sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) 
Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) 
sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) 
Using 
Named 
Groups 
In Python regular expressions, the syntax for named regular expression groups is (?P<name>name is the name of the group and pattern is some pattern to match. 
In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern), name is the name of the group and pattern is some pattern to match. 
Hereโ€™s an example URLconf that uses non-named groups: 
from django.conf.urls.defaults import * 
from mysite import views 
Hereโ€™s an example URLconf that uses non-named groups: 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^articles/(d{4})/$โ€™, views.year_archive), 
(rโ€™^articles/(d{4})/(d{2})/$โ€™, views.month_archive), 
(rโ€™^articles/(d{4})/$โ€™, views.year_archive), 
(rโ€™^articles/(d{4})/(d{2})/$โ€™, views.month_archive), 
) 
Hereโ€™s the same URLconf, rewritten to use named groups: 
from django.conf.urls.defaults import * 
from mysite import views 
) 
Hereโ€™s the same URLconf, rewritten to use named groups: 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^articles/(?P<year>d{4})/$โ€™, views.year_archive), 
(rโ€™^articles/(?P<year>d{4})/(?P<month>d{2})/$โ€™, views.month_archive), 
(rโ€™^articles/(?P<year>d{4})/$โ€™, views.year_archive), 
(rโ€™^articles/(?P<year>d{4})/(?P<month>d{2})/$โ€™, views.month_archive), 
) 
This accomplishes exactly the same thing as the previous example, with one subtle difference: the captured passed to view functions as keyword arguments rather than positional arguments. 
) 
This accomplishes exactly the same thing as the previous example, with one subtle difference: passed to view functions as keyword arguments rather than positional arguments.
Using 
Named 
Groups 
โ€ข For 
example, 
with 
non-ยญโ€named 
groups, 
a 
request 
to 
/arAcles/ 
2006/03/ 
would 
result 
in 
a 
funcAon 
call 
equivalent 
to 
this: 
month_archive(request, 
'2006', 
'03') 
โ€ข With 
named 
groups, 
though, 
the 
same 
request 
would 
result 
in 
this 
funcAon 
call: 
month_archive(request, 
year='2006', 
month='03')
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 
posiAonal 
arguments. 
โ€ข In 
both 
cases, 
it 
will 
pass 
any 
extra 
opAons 
as 
keyword 
arguments. 
See 
the 
next 
secAon 
for 
more 
informaAon.
โ€ข Otherwise, it will pass all non-named arguments as positional arguments. 
โ€ข In both cases, it will pass any extra options as keyword arguments. See the next section for more information. 
Passing 
Extra 
Options 
to 
View 
Functions 
9.1.6 Passing Extra Options to View Functions 
Sometimes youโ€™ll find yourself writing view functions that are quite similar, with only a few small differences. example, say 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 
from mysite.models import MyModel 
9.1. URLconf Tricks Django Book Documentation, Release 0.1 
def foo_view(request): 
m_list = MyModel.objects.filter(is_new=True) 
return render(request, โ€™template1.htmlโ€™, {โ€™m_listโ€™: m_list}) 
def bar_view(request): 
m_list = MyModel.objects.filter(is_new=True) 
return render(request, โ€™template2.htmlโ€™, {โ€™m_listโ€™: m_list}) 
Weโ€™re repeating ourselves in this code, and thatโ€™s inelegant. At first, you may think to remove the redundancy by the same view for both URLs, putting parentheses around the URL to capture it, and checking the URL within
def bar_view(request): 
m_list = MyModel.objects.filter(is_new=True) 
return render(request, โ€™template2.htmlโ€™, {โ€™m_listโ€™: m_list}) 
Passing 
Extra 
Options 
to 
View 
Functions 
Weโ€™re repeating ourselves in this code, and thatโ€™s inelegant. At first, you may think to remove the redundancy by using 
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, like so: 
# 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 
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(request, template_name, {โ€™m_listโ€™: m_list}) 
The problem with that solution, though, is that it couples your URLs to your code. If you decide to rename /foo/ to 
/fooey/, youโ€™ll have to remember to change the view code. 
The elegant solution involves an optional URLconf parameter. Each pattern in a URLconf may include a third item: a 
dictionary of keyword arguments to pass to the view function. 
With this in mind, we can rewrite our ongoing example like this: 
The 
problem 
with 
that 
soluAon, 
though, 
is 
that 
it 
couples 
your 
URLs 
to 
your 
code. 
If 
you 
decide 
to 
rename 
/foo/ 
to 
/fooey/, 
youโ€™ll 
have 
to 
remember 
to 
change 
the 
view 
code.
The /Passing 
problem with that solution, though, is that it couples your URLs to your code. If you decide to rename /fooey/, youโ€™ll have to Extra 
remember to change Options 
the view code. 
to 
View 
The elegant solution involves an optional URLconf parameter. Each pattern in a URLconf may include a third dictionary Functions 
of keyword arguments to pass to the view function. 
With this in mind, we can rewrite our ongoing example like this: 
# 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 
from mysite.models import MyModel 
def foobar_view(request, template_name): 
m_list = MyModel.objects.filter(is_new=True) 
return render(request, template_name, {โ€™m_listโ€™: m_list}) 
As you can see, the URLconf in this example specifies template_name in the URLconf. The view function 128 Chapter 9. Chapter 8: Advanced Views and URLconfs
) 
And the view function signature would look like this: 
def my_view(request, month, day): 
Faking 
Captured 
URLconf 
Values 
# .... 
This approach is straightforward โ€“ itโ€™s nothing you havenโ€™t seen before. The trick comes in when you want another URL that uses my_view but whose URL doesnโ€™t include a month and/or day. 
For example, you might want to add another URL, /mydata/birthday/, which would be equivalent /mydata/jan/06/. You can take advantage of extra URLconf options like so: 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^mydata/birthday/$โ€™, views.my_view, {โ€™monthโ€™: โ€™janโ€™, โ€™dayโ€™: โ€™06โ€™}), 
(rโ€™^mydata/(?P<month>w{3})/(?P<day>dd)/$โ€™, views.my_view), 
) 
The cool thing here is that you donโ€™t have to change your view function at all. The view function only cares that month and day parameters โ€“ it doesnโ€™t matter whether they come from the URL capturing itself or extra parameters. 
Making a View Generic 
Itโ€™s good programming practice to โ€œfactor outโ€ commonalities in code. For example, with these two Python functions: 
def say_hello(person_name): 
print โ€™Hello, %sโ€™ % person_name 
def say_goodbye(person_name): 
print โ€™Goodbye, %sโ€™ % person_name
def greet(person_name, greeting): 
print โ€™%s, %sโ€™ % (greeting, person_name) 
Making 
a 
View 
Generic 
You can apply this same philosophy to your Django views by using extra URLconf parameters. 
With this in mind, you can start making higher-level abstractions of your views. Instead of thinking to yourself, โ€œThis 
view displays a list of Event objects,โ€ and โ€œThat view displays a list of BlogEntry objects,โ€ realize theyโ€™re both 
specific cases of โ€œA view that displays a list of objects, where the type of object is variable.โ€ 
Take Original 
this code, for example: 
# urls.py 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^events/$โ€™, views.event_list), 
(rโ€™^blog/entries/$โ€™, views.entry_list), 
) 
# views.py 
from django.shortcuts import render 
from mysite.models import Event, BlogEntry 
def event_list(request): 
obj_list = Event.objects.all() 
return render(request, โ€™mysite/event_list.htmlโ€™, {โ€™event_listโ€™: obj_list}) 
def entry_list(request): 
obj_list = BlogEntry.objects.all() 
return render(request, โ€™mysite/blogentry_list.htmlโ€™, {โ€™entry_listโ€™: obj_list}) 
The two views do essentially the same thing: they display a list of objects. So letโ€™s factor out the type of object theyโ€™re 
displaying:
obj_list = Event.objects.all() 
return render(request, โ€™mysite/event_list.htmlโ€™, {โ€™event_listโ€™: obj_list}) 
def entry_list(request): 
Making 
a 
View 
Generic 
obj_list = BlogEntry.objects.all() 
return render(request, โ€™mysite/blogentry_list.htmlโ€™, {โ€™entry_listโ€™: obj_list}) 
The two views do essentially the same thing: they display a list of objects. So letโ€™s factor out the type of object displaying: 
# urls.py 
BeCer 
from django.conf.urls.defaults import * 
from mysite import models, views 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^events/$โ€™, views.object_list, {โ€™modelโ€™: models.Event}), 
(rโ€™^blog/entries/$โ€™, views.object_list, {โ€™modelโ€™: models.BlogEntry}), 
) 
# views.py 
from django.shortcuts import render 
def object_list(request, model): 
obj_list = model.objects.all() 
template_name = โ€™mysite/%s_list.htmlโ€™ % model.__name__.lower() 
return render(request, template_name, {โ€™object_listโ€™: obj_list}) 
With those small changes, we suddenly have a reusable, model-agnostic view! From now on, anytime we need that Every 
lists Python 
a set of class 
objects, has 
we a 
can __name__ 
simply reuse aCribute 
this object_that 
returns 
list the 
view class 
rather name. 
than writing view code. Here
var = do_something() 
return render(request, template_name, {โ€™varโ€™: var}) 
Understanding 
Precedence 
of 
Captured 
Values 
vs. 
Extra 
Options 
Understanding Precedence of Captured Values vs. Extra Options 
When thereโ€™s a conflict, extra URLconf parameters get precedence over captured parameters. URLconf if 
your 
URLconf 
captures captures 
a named-a 
named-ยญโ€group group 
variable variable 
and an and 
extra an 
extra 
URLconf URLconf 
parameter includes a variable the parameter 
extra URLconf includes 
parameter a 
variable 
value with 
the 
will same 
be used. 
name, 
the 
extra 
URLconf 
parameter 
value 
will 
be 
used. 
For example, consider this URLconf: 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^mydata/(?P<id>d+)/$โ€™, views.my_view, {โ€™idโ€™: 3}), 
) 
Here, both the regular expression and the extra dictionary include an id. The hard-coded means any request (e.g., /mydata/2/ or /mydata/432432/) will be treated as if id value id 
captured will 
be 
3. 
in the URL. 
Astute readers will note that in this case, itโ€™s a waste of time and typing to capture the id because its value will always be overridden by the dictionaryโ€™s value. Thatโ€™s correct; we bring avoid making the mistake.
9.1.7 Using Default View Arguments 
Another convenient trick is to specify default parameters use Using 
for a parameter Default 
by default if none is View 
specified. 
Arguments 
for a viewโ€™s arguments. This tells the view An example: 
# urls.py 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^blog/$โ€™, views.page), 
(rโ€™^blog/page(?P<num>d+)/$โ€™, views.page), 
) 
# views.py 
def page(request, num=โ€™1โ€™): 
# Output the appropriate page of blog entries, according to num. 
# ... 
Here, both URL patterns point to the same view โ€“ views.page โ€“ but the first pattern doesnโ€™t capture the URL. If the first pattern matches, the page() function will use its default argument for num, โ€™1โ€™. pattern matches, page() will use whatever num value was captured by the regular expression. 
(Note that weโ€™ve been careful to set the default argumentโ€™s value to the string โ€™1โ€™, not the integer consistency, because any captured value for num will always be a string.) 
Itโ€™s common to use this technique in conjunction with configuration options, as explained earlier. This example
Special-ยญโ€Casing 
Views 
Django Book else: 
SomeAmes 
youโ€™ll 
have 
a 
paCern 
in 
your 
URLconf 
that 
handles 
a 
large 
set 
of 
URLs, 
but 
youโ€™ll 
need 
to 
special-ยญโ€case 
one 
of 
them. 
In 
this 
case, 
take 
advantage 
of 
the 
linear 
way 
a 
# URLconf 
do normal is 
processed 
code 
and 
put 
the 
special 
case 
first. 
but thatโ€™s inelegant for a reason weโ€™ve touched on multiple times in this chapter: it more elegant solution, we can take advantage of the fact that URLconfs are processed urlpatterns = patterns(โ€™โ€™, 
# ... 
(โ€™^auth/user/add/$โ€™, views.user_add_stage), 
(โ€™^([^/]+)/([^/]+)/add/$โ€™, views.add_stage), 
# ... 
) 
With this in place, a request to /auth/user/add/ will be handled by the user_add_URL matches the second pattern, it matches the top one first. (This is short-circuit logic.) 
9.1.9 Capturing Text in URLs
so) about accepting only objects of a certain type. A common error is to attempt to create a datetime.date 
object with string values instead of integer values: 
>>> import datetime 
>>> datetime.date(โ€™1993โ€™, โ€™7โ€™, โ€™9โ€™) 
Traceback (most recent call last): 
Capturing 
Text 
in 
URLs 
... 
Each 
captured 
argument 
is 
sent 
to 
the 
view 
as 
a 
plain 
Python 
Unicode 
string, 
regardless 
of 
what 
sort 
of 
match 
the 
regular 
expression 
makes. 
TypeError: an integer is required 
>>> datetime.date(1993, 7, 9) 
datetime.date(1993, 7, 9) 
Translated Wrong 
to a URLconf and view, the error looks like this: 
# urls.py 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^articles/(d{4})/(d{2})/(d{2})/$โ€™, views.day_archive), 
) 
# views.py 
import datetime 
def day_archive(request, year, month, day): 
# The following statement raises a TypeError! 
date = datetime.date(year, month, day) 
Django Book Documentation, Release 0.1 
Instead, Correct 
day_archive() can be written correctly like this: 
def day_archive(request, year, month, day): 
date = datetime.date(int(year), int(month), int(day)) 
9.1. URLconf Tricks 133 
Note that int() itself raises a ValueError when you pass it a string that is not composed solely of digits, but
9.1.11 Higher-Level Abstractions of View Functions 
And speaking of branching based on request method, letโ€™s take a look at how we might build a nice way of doing Consider this URLconf/view layout: 
# urls.py 
Higher-ยญโ€level 
Abstractions 
of 
View 
Functions(Original) 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
# ... 
(rโ€™^somepage/$โ€™, views.some_page), 
# ... 
) 
# views.py 
from django.http import Http404, HttpResponseRedirect 
from django.shortcuts import render 
def some_page(request): 
if request.method == โ€™POSTโ€™: 
do_something_for_post() 
return HttpResponseRedirect(โ€™/someurl/โ€™) 
elif request.method == โ€™GETโ€™: 
do_something_for_get() 
return render(request, โ€™page.htmlโ€™) 
else: 
raise Http404() 
In this example, the some_page() viewโ€™s handling of POST vs. GET requests is quite different. The only thing
Higher-ยญโ€level 
Abstractions 
of 
View 
Functions(no 
args 
and 
kwargs) 
Django Book Documentation, Release 0.1 
We can do that by writing a view function that delegates to other views, either before or after executing some custom 
logic. Hereโ€™s an example of how this technique could help simplify our some_page() view: 
# views.py 
from django.http import Http404, HttpResponseRedirect 
from django.shortcuts import render 
def method_splitter(request, GET=None, POST=None): 
if request.method == โ€™GETโ€™ and GET is not None: 
return GET(request) 
elif request.method == โ€™POSTโ€™ and POST is not None: 
return POST(request) 
raise Http404 
def some_page_get(request): 
assert request.method == โ€™GETโ€™ 
do_something_for_get() 
return render(request, โ€™page.htmlโ€™) 
def some_page_post(request): 
assert request.method == โ€™POSTโ€™ 
do_something_for_post() 
return HttpResponseRedirect(โ€™/someurl/โ€™) 
# urls.py 
from django.conf.urls.defaults import * 
from mysite import views 
urlpatterns = patterns(โ€™โ€™, 
# ... 
(rโ€™^somepage/$โ€™, views.method_splitter, {โ€™GETโ€™: views.some_page_get, โ€™POSTโ€™: views.some_page_post}), 
# ...
Django Book Documentation, Release 0.1 
Higher-ยญโ€level 
Abstractions 
of 
View 
Functions(args 
and 
kwargs) 
GET and POST views take no arguments other than request. What if we wanted to use method_with views that, for example, capture text from URLs, or take optional keyword arguments themselves? 
To do that, we can use a nice Python feature: variable arguments with asterisks. Weโ€™ll show the example explain it: 
def method_splitter(request, *args, **kwargs): 
get_view = kwargs.pop(โ€™GETโ€™, None) 
post_view = kwargs.pop(โ€™POSTโ€™, None) 
if request.method == โ€™GETโ€™ and get_view is not None: 
return get_view(request, *args, **kwargs) 
elif request.method == โ€™POSTโ€™ and post_view is not None: 
return post_view(request, *args, **kwargs) 
raise Http404 
Here, weโ€™ve refactored method_splitter() to remove the GET and POST keyword arguments, in and **kwargs (note the asterisks). This is a Python feature that allows a function to accept a dynamic, number of arguments whose names arenโ€™t known until runtime. If you put a single asterisk in front of a function definition, any positional arguments to that function will be rolled up into a single tuple. asterisks in front of a parameter in a function definition, any keyword arguments to that function will a single dictionary. 
For example, with this function: 
def foo(*args, **kwargs):
Wrapping 
View 
Functions 
(Original) 
Django Book Documentation, def my_view2(request): 
if not request.user.is_authenticated(): 
return HttpResponseRedirect(โ€™/accounts/login/โ€™) 
# ... 
return render(request, โ€™template2.htmlโ€™) 
def my_view3(request): 
if not request.user.is_authenticated(): 
return HttpResponseRedirect(โ€™/accounts/login/โ€™) 
# ... 
return render(request, โ€™template3.htmlโ€™) 
Here, each view starts by checking that request.user is authenticated โ€“ that is, the logged into the site โ€“ and redirects to /accounts/login/ if not. (Note that request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user either logged-in or anonymous.) 
It would be nice if we could remove that bit of repetitive code from each of these views and
request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user represents the current either logged-in or anonymous.) 
It would be nice if we could remove that bit of repetitive code from each of these views and just mark them as requiring 
authentication. We can do that by making a view wrapper. Take a moment to study this: 
def requires_login(view): 
logged into the site โ€“ and redirects to /accounts/login/ if not. (Note that we request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user represents either Wrapping 
logged-in or anonymous.) 
View 
Functions 
(elegant) 
It would be nice if we could remove that bit of repetitive code from each of these views and just authentication. def new_view(We request, can do that *args, by making **kwargs): 
a view wrapper. Take a moment to study this: 
if not request.user.is_authenticated(): 
def requires_login(view): 
return HttpResponseRedirect(โ€™/accounts/login/โ€™) 
def return new_view(view(request, request, *args, *args, **kwargs) 
**kwargs): 
return new_view 
if not request.user.is_authenticated(): 
return HttpResponseRedirect(โ€™/accounts/login/โ€™) 
This function, return requires_login, takes a view function (view) and returns a new view function (The new function, view(request, args, kwargs) 
new_new_view is defined *within requires_**login and handles the logic of checking 
request.return user.new_is_authenticated() view 
and delegating to the original view (view). 
Now, we can remove the if not request.user.is_authenticated() checks from our views and wrap them with requires_login in our URLconf: 
from django.conf.urls.defaults import * 
from mysite.views import requires_login, my_view1, my_view2, my_view3 
This function, requires_login, takes a view function (view) and returns a new view The new function, new_view is defined within requires_login and handles request.user.is_authenticated() and delegating to the original view (view). 
Now, we can remove the if not request.user.is_authenticated() checks from wrap them with requires_login in our URLconf: 
from django.conf.urls.defaults import * 
from mysite.views import requires_login, my_view1, my_view2, my_view3 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^view1/$โ€™, requires_login(my_view1)), 
(rโ€™^view2/$โ€™, requires_login(my_view2)), 
(rโ€™^view3/$โ€™, requires_login(my_view3)), 
) 
This urlpatterns has the same effect = patterns(โ€™โ€™, 
as before, but with less code redundancy. Now weโ€™ve created a nice, generic function requires_login() that we can wrap around any view in order to make it require login. 
(rโ€™^view1/$โ€™, requires_login(my_view1)), 
(rโ€™^view2/$โ€™, requires_login(my_view2)), 
(rโ€™^view3/$โ€™, requires_login(my_view3)),
If you intend your code to be used on multiple Django-based sites, you should consider arranging such At Including 
a way that allows for โ€œincluding.โ€ 
any point, your URLconf Other 
can โ€œincludeโ€ URLconfs 
other URLconf modules. This essentially โ€œrootsโ€ other ones. For example, this URLconf includes other URLconfs: 
from django.conf.urls.defaults import * 
9.2. Including Other URLconfs Django Book Documentation, Release 0.1 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^weblog/โ€™, include(โ€™mysite.blog.urlsโ€™)), 
(rโ€™^photos/โ€™, include(โ€™mysite.photos.urlsโ€™)), 
(rโ€™^about/$โ€™, โ€™mysite.views.aboutโ€™), 
) 
(We saw this before in Chapter 6, when we introduced the Django admin site. The admin site that you merely include() within yours.) 
Thereโ€™s an important gotcha here: the regular expressions in this example that point to an include() $ (end-of-string match character) but do include a trailing slash. Whenever Django encounters off whatever part of the URL matched up to that point and sends the remaining string to the further processing. 
Continuing this example, hereโ€™s the URLconf mysite.blog.urls: 
from django.conf.urls.defaults import * 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^(dddd)/$โ€™, โ€™mysite.blog.views.year_detailโ€™),
โ€ข /about/: This matches the view mysite.views.about in the first URLconf, demonstrating mix include() patterns with non-include() patterns. 
How 
Captured 
Parameters 
Work 
with 
include() 
9.2.1 How Captured Parameters Work with include() 
An included URLconf receives any captured parameters from parent URLconfs, for example: 
# root urls.py 
from django.conf.urls.defaults import * 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^(?P<username>w+)/blog/โ€™, include(โ€™foo.urls.blogโ€™)), 
) 
# foo/urls/blog.py 
from django.conf.urls.defaults import * 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^$โ€™, โ€™foo.views.blog_indexโ€™), 
(rโ€™^archive/$โ€™, โ€™foo.views.blog_archiveโ€™), 
) 
In this example, the captured username variable is passed to the included URLconf and, function within that URLconf.
9.2.2 How Extra URLconf Options Work with include() 
Similarly, you can pass extra URLconf options to include(), just as you can pass extra normal view โ€“ as a dictionary. When you do this, each line in the included URLconf will be For example, the following two URLconf sets are functionally identical. 
Set one: 
# urls.py 
How 
Extra 
URLconf 
Options 
Work 
with 
include() 
from django.conf.urls.defaults import * 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^blog/โ€™, include(โ€™innerโ€™), {โ€™blogidโ€™: 3}), 
) 
# inner.py 
from django.conf.urls.defaults import * 
urlpatterns = patterns(โ€™โ€™, 
(rโ€™^archive/$โ€™, โ€™mysite.views.archiveโ€™), 
(rโ€™^about/$โ€™, โ€™mysite.views.aboutโ€™), 
(rโ€™^rss/$โ€™, โ€™mysite.views.rssโ€™), 
) 
Set two:

More Related Content

What's hot (20)

PDF
Data Validation models
Marcin Czarnecki
ย 
PDF
Perl.Hacks.On.Vim
Lin Yo-An
ย 
PDF
PhpUnit - The most unknown Parts
Bastian Feder
ย 
PDF
Dutch php a short tale about state machine
ลukasz Chruล›ciel
ย 
PPTX
Php functions
JIGAR MAKHIJA
ย 
PPTX
Looping the Loop with SPL Iterators
Mark Baker
ย 
PPT
JavaScript Functions
Brian Moschel
ย 
PDF
DRYing to Monad in Java8
Dhaval Dalal
ย 
PDF
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Javier Eguiluz
ย 
PDF
WordCamp Portland 2018: PHP for WordPress
Alena Holligan
ย 
PPT
JSConf: All You Can Leet
johndaviddalton
ย 
PPTX
Php pattern matching
JIGAR MAKHIJA
ย 
PDF
Functional programming using underscorejs
ๅ‰ๆ ผ ้ซ˜
ย 
PDF
Good Evils In Perl
Kang-min Liu
ย 
PPTX
Whatโ€™s new in ECMAScript 6.0
Eyal Vardi
ย 
ODP
Very basic functional design patterns
Tomasz Kowal
ย 
PPTX
A Functional Guide to Cat Herding with PHP Generators
Mark Baker
ย 
KEY
CoffeeScript - A Rubyist's Love Affair
Mark
ย 
PDF
Swift์—์„œ ๊ผฌ๋ฆฌ์žฌ๊ท€ ์‚ฌ์šฉ๊ธฐ (Tail Recursion)
์ง„์„ฑ ์˜ค
ย 
Data Validation models
Marcin Czarnecki
ย 
Perl.Hacks.On.Vim
Lin Yo-An
ย 
PhpUnit - The most unknown Parts
Bastian Feder
ย 
Dutch php a short tale about state machine
ลukasz Chruล›ciel
ย 
Php functions
JIGAR MAKHIJA
ย 
Looping the Loop with SPL Iterators
Mark Baker
ย 
JavaScript Functions
Brian Moschel
ย 
DRYing to Monad in Java8
Dhaval Dalal
ย 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Javier Eguiluz
ย 
WordCamp Portland 2018: PHP for WordPress
Alena Holligan
ย 
JSConf: All You Can Leet
johndaviddalton
ย 
Php pattern matching
JIGAR MAKHIJA
ย 
Functional programming using underscorejs
ๅ‰ๆ ผ ้ซ˜
ย 
Good Evils In Perl
Kang-min Liu
ย 
Whatโ€™s new in ECMAScript 6.0
Eyal Vardi
ย 
Very basic functional design patterns
Tomasz Kowal
ย 
A Functional Guide to Cat Herding with PHP Generators
Mark Baker
ย 
CoffeeScript - A Rubyist's Love Affair
Mark
ย 
Swift์—์„œ ๊ผฌ๋ฆฌ์žฌ๊ท€ ์‚ฌ์šฉ๊ธฐ (Tail Recursion)
์ง„์„ฑ ์˜ค
ย 

Viewers also liked (13)

PDF
The Django Book - Chapter 7 forms
Vincent Chien
ย 
PDF
The Django Book chapter 5 Models
Vincent Chien
ย 
PPTX
Znaczenie zl w org
JustynaG1991
ย 
PDF
The Django Book / Chapter 3: Views and URLconfs
Vincent Chien
ย 
PDF
The Django Book chapter 4 templates (supplement)
Vincent Chien
ย 
PPTX
Satysfakcja z pracy
JustynaG1991
ย 
PPTX
Pomiar satysfakcji z pracy
JustynaG1991
ย 
PDF
The Django Book - Chapter 6 the django admin site
Vincent Chien
ย 
PPTX
ADV 208 Individual Project
smbrandt
ย 
PPTX
Chapter 51 2011 2012
mmarionkova
ย 
PPT
Chapter 33 2012 2013
mmarionkova
ย 
PPTX
Animal behavior 2012 2013
mmarionkova
ย 
PPT
Reality Of Reality Shows
yogi0908
ย 
The Django Book - Chapter 7 forms
Vincent Chien
ย 
The Django Book chapter 5 Models
Vincent Chien
ย 
Znaczenie zl w org
JustynaG1991
ย 
The Django Book / Chapter 3: Views and URLconfs
Vincent Chien
ย 
The Django Book chapter 4 templates (supplement)
Vincent Chien
ย 
Satysfakcja z pracy
JustynaG1991
ย 
Pomiar satysfakcji z pracy
JustynaG1991
ย 
The Django Book - Chapter 6 the django admin site
Vincent Chien
ย 
ADV 208 Individual Project
smbrandt
ย 
Chapter 51 2011 2012
mmarionkova
ย 
Chapter 33 2012 2013
mmarionkova
ย 
Animal behavior 2012 2013
mmarionkova
ย 
Reality Of Reality Shows
yogi0908
ย 
Ad

Similar to Chapter 8- Advanced Views and URLconfs (20)

PDF
Web Development with Python and Django
Michael Pirnat
ย 
PDF
Django design-patterns
Agiliq Info Solutions India Pvt Ltd
ย 
PDF
django_reference_sheet
webuploader
ย 
PPTX
Django - Python MVC Framework
Bala Kumar
ย 
PDF
Django - basics
University of Technology
ย 
KEY
Introduction to Django
James Casey
ย 
PDF
The Best (and Worst) of Django
Jacob Kaplan-Moss
ย 
PPTX
Django framework
TIB Academy
ย 
PDF
Django Introduction & Tutorial
ไน‹ๅฎ‡ ่ถ™
ย 
DOCX
Akash rajguru project report sem v
Akash Rajguru
ย 
PDF
Django
Nam Dang
ย 
PPTX
FSD MODULE 4 - Using Generic Views, Generic Views of Objects, Extending Gener...
PRADEEPNAYAK75
ย 
PDF
Intermediate python
NaphtaliOchonogor1
ย 
PPTX
Web development with django - Basics Presentation
Shrinath Shenoy
ย 
PDF
Django 1.10.3 Getting started
MoniaJ
ย 
PDF
Python Essentials For Dummies John C Shovic Alan Simpson
cundyfema
ย 
PDF
How to make the fastest Router in Python
kwatch
ย 
PDF
Django Overview
Brian Tol
ย 
PDF
Django tutorial
Ksd Che
ย 
Web Development with Python and Django
Michael Pirnat
ย 
Django design-patterns
Agiliq Info Solutions India Pvt Ltd
ย 
django_reference_sheet
webuploader
ย 
Django - Python MVC Framework
Bala Kumar
ย 
Django - basics
University of Technology
ย 
Introduction to Django
James Casey
ย 
The Best (and Worst) of Django
Jacob Kaplan-Moss
ย 
Django framework
TIB Academy
ย 
Django Introduction & Tutorial
ไน‹ๅฎ‡ ่ถ™
ย 
Akash rajguru project report sem v
Akash Rajguru
ย 
Django
Nam Dang
ย 
FSD MODULE 4 - Using Generic Views, Generic Views of Objects, Extending Gener...
PRADEEPNAYAK75
ย 
Intermediate python
NaphtaliOchonogor1
ย 
Web development with django - Basics Presentation
Shrinath Shenoy
ย 
Django 1.10.3 Getting started
MoniaJ
ย 
Python Essentials For Dummies John C Shovic Alan Simpson
cundyfema
ย 
How to make the fastest Router in Python
kwatch
ย 
Django Overview
Brian Tol
ย 
Django tutorial
Ksd Che
ย 
Ad

Recently uploaded (20)

PDF
AI Prompts Cheat Code prompt engineering
Avijit Kumar Roy
ย 
PPTX
Chess King 25.0.0.2500 With Crack Full Free Download
cracked shares
ย 
PDF
IDM Crack with Internet Download Manager 6.42 Build 31 2025?
utfefguu
ย 
PPTX
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
ย 
PDF
Notification System for Construction Logistics Application
Safe Software
ย 
PDF
Salesforce Experience Cloud Consultant.pdf
VALiNTRY360
ย 
PPTX
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
ย 
PDF
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
ย 
PDF
Odoo Customization Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
PDF
Instantiations Company Update (ESUG 2025)
ESUG
ย 
PPTX
UI5con_2025_Accessibility_Ever_Evolving_
gerganakremenska1
ย 
PDF
Everything you need to know about pricing & licensing Microsoft 365 Copilot f...
Q-Advise
ย 
PDF
intro_to_cpp_namespace_robotics_corner.pdf
MohamedSaied877003
ย 
PDF
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
ย 
PPTX
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
ย 
PDF
AI Software Engineering based on Multi-view Modeling and Engineering Patterns
Hironori Washizaki
ย 
PPTX
Odoo Migration Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
PDF
chapter 5.pdf cyber security and Internet of things
PalakSharma980227
ย 
PDF
How to get the licensing right for Microsoft Core Infrastructure Server Suite...
Q-Advise
ย 
PDF
custom development enhancement | Togglenow.pdf
aswinisuhu
ย 
AI Prompts Cheat Code prompt engineering
Avijit Kumar Roy
ย 
Chess King 25.0.0.2500 With Crack Full Free Download
cracked shares
ย 
IDM Crack with Internet Download Manager 6.42 Build 31 2025?
utfefguu
ย 
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
ย 
Notification System for Construction Logistics Application
Safe Software
ย 
Salesforce Experience Cloud Consultant.pdf
VALiNTRY360
ย 
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
ย 
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
ย 
Odoo Customization Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
Instantiations Company Update (ESUG 2025)
ESUG
ย 
UI5con_2025_Accessibility_Ever_Evolving_
gerganakremenska1
ย 
Everything you need to know about pricing & licensing Microsoft 365 Copilot f...
Q-Advise
ย 
intro_to_cpp_namespace_robotics_corner.pdf
MohamedSaied877003
ย 
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
ย 
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
ย 
AI Software Engineering based on Multi-view Modeling and Engineering Patterns
Hironori Washizaki
ย 
Odoo Migration Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
chapter 5.pdf cyber security and Internet of things
PalakSharma980227
ย 
How to get the licensing right for Microsoft Core Infrastructure Server Suite...
Q-Advise
ย 
custom development enhancement | Togglenow.pdf
aswinisuhu
ย 

Chapter 8- Advanced Views and URLconfs

  • 1. The Django Book Chapter 8: Advanced Views and URLconfs Speaker: Vincent Chien
  • 2. advantage of this in several ways, as described in the sections that follow. from django.conf.urls.defaults import * from mysite.views import hello, current_datetime, hours_ahead Streamlining Function Imports 9.1.1 Streamlining Function Imports Consider this URLconf, which builds on the example in Chapter 3: from django.conf.urls.defaults import * from mysite.views import hello, current_datetime, hours_ahead urlpatterns = patterns(โ€™โ€™, (rโ€™^hello/$โ€™, hello), (rโ€™^time/$โ€™, current_datetime), (rโ€™^time/plus/(d{1,2})/$โ€™, hours_ahead), ) As urlpatterns explained in = Chapter patterns(โ€™โ€™, 3, each entry in the URLconf includes its associated view function, function (rโ€™^object. hello/$โ€™, This means hello), itโ€™s necessary to import the view functions at the top of the module. But as (a rโ€™^Django time/$โ€™, application current_datetime), (rโ€™^time/plus/(d{grows 1,2})/$โ€™, in complexity, hours_its ahead), URLconf grows, too, and keeping those imports manage. (For each new view function, you have to remember to import it, and the import statement long if you use this approach.) Itโ€™s possible to avoid that tedium by importing the views module URLconf is equivalent to the previous one: from django.conf.urls.defaults import * from mysite import views ) As explained in Chapter 3, each entry in the URLconf includes its associated view function, 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 manage. (For each new view function, you have to remember to import it, and the import statement long if you use this approach.) Itโ€™s possible to avoid that tedium by importing the views module URLconf is equivalent to the previous one: 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), ) urlpatterns = patterns(โ€˜โ€™,
  • 3. string containing the module name and function name rather than the function object itself. Continuing example: from django.conf.urls.defaults import * DSjantgro Beooak Dmocumlienntatiionn, Rgel eaFseu0.1nction Imports urlpatterns = patterns(โ€˜โ€™, (rโ€™^hello/$โ€™, โ€˜mysite.views.helloโ€™), (rโ€™^time/$โ€™, โ€˜mysite.views.current_datetimeโ€™), (rโ€™^time/plus/(d{1,2})/$โ€™, โ€˜mysite.views.hours_aheadโ€™), Django offers another way of specifying the view funcAon for a parAcular ) Note that you donโ€™t put a trailing dot (".") in the prefix, nor do you put a leading dot in the view strings. Django paCern offers in the another URLconf: way of you specifying can pass the a view string function containing for a particular the module pattern name in the URLconf: you can string and funccontaining Aon name the module rather name than and the function funcAon name object rather itself. than the function object itself. Continuing the ongoing example: from django.conf.urls.defaults import * ) (Note the quotes around the view names. Weโ€™re using โ€™mysite.views.current_datetimeโ€™ instead of mysite.views.current_datetime.) Using urlpatterns this technique, = patterns(โ€˜โ€™, itโ€™s no longer necessary to import the view functions; Django automatically (rโ€™^hello/$โ€™, โ€˜mysite.views.helloโ€™), (rโ€™^view time/$โ€™, function โ€˜the mysite.first time views.itโ€™s needed, current_according datetimeโ€™), to the string describing the name and path function. (rโ€™^time/plus/(d{1,2})/$โ€™, โ€˜mysite.views.hours_aheadโ€™), A further shortcut you can take when using the string technique is to factor out a common โ€œview URLconf example, each of the view strings starts with โ€™mysite.viewsโ€™, which is redundant to factor out that common prefix and pass it as the first argument to patterns(), like this: from django.conf.urls.defaults import * ) (Note the quotes around the view names. Weโ€™re using โ€™mysite.views.current_datetimeโ€™ โ€“ with quotes instead factor of out mysite.a common views.โ€œview current_prefix.โ€ datetime.) Using this technique, itโ€™s no longer necessary to import the view functions; Django automatically imports view function the first time itโ€™s needed, according to the string describing the name and path of the function. A further shortcut you can take when using the string technique is to factor out a common โ€œview prefix.โ€ URLconf example, each of the view strings starts with โ€™mysite.viewsโ€™, which is redundant to type. We factor out that common prefix and pass it as the first argument to patterns(), like this: 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โ€™),
  • 4. Using Multiple View Pre>iDxjanegosB ook Documentation, from django.conf.urls.defaults import * = 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โ€™), OLD ) New: NEW 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โ€™), ) Django Book Documentation, Release 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โ€™), ) New: 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โ€™), )
  • 5. 9.1.3 Special-Casing URLs in Debug Mode Special-ยญโ€Casing URLs in Debug Speaking of constructing urlpatterns dynamically, you might want to take advantage your runtime, Mode URLconfโ€™s behavior while in Djangoโ€™s debug mode. To do this, just check the like so: 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), ) In this example, the URL /debuginfo/ will only be available if your DEBUG setting 9.1.4 Using Named Groups
  • 6. Keyword Arguments vs. Positional Arguments A Python function can be called using keyword arguments or positional arguments โ€“ and, in some cases, both at same time. In a keyword argument call, you specify the names of the arguments along with the values youโ€™re passing. In a positional argument call, you simply pass the arguments without explicitly specifying which argument matches which value; the association is implicit in the argumentsโ€™ order. For example, consider this simple function: def sell(item, price, quantity): A Python function can be called using keyword arguments or positional arguments โ€“ and, in some cases, same time. In a keyword argument call, you specify the names of the arguments along with the values In a positional argument call, you simply pass the arguments without explicitly specifying which argument which value; the association is implicit in the argumentsโ€™ order. For example, consider this simple function: def sell(item, price, quantity): same In a positional time. In a argument keyword argument call, you simply call, you pass specify the arguments the names without of the arguments explicitly specifying along with which the values argument In which a positional value; the argument association call, is you implicit simply in the pass argumentsโ€™ the arguments order. without explicitly specifying which argument which For example, value; the consider association this simple is implicit function: in the argumentsโ€™ order. For example, consider this simple function: def sell(item, price, quantity): def sell(item, price, quantity): Using Named Groups print "Selling %s unit(s) of %s at %s" % (quantity, item, price) print "Selling %s unit(s) of %s at %s" % (quantity, item, price) To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) print print "Selling "Selling %s %unit(s unit(s) of s) %s of at %s %s" at % %(s" quantity, % (quantity, item, price) item, price) call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed definition: sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) To call it with keyword arguments, you specify the names of the arguments along with the values. statements are equivalent: sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) To call it with positional arguments, you specify the arguments in the order in which theyโ€™re listed in the function definition: sell(โ€™Socksโ€™, โ€™$2.50โ€™, 6) To call it with keyword arguments, you specify the names of the arguments along with the values. The following PosiAonal Arguments Keyword Arguements are equivalent: sell(item=โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(item=โ€™item=โ€™Socksโ€™, Socksโ€™, quantity=price=โ€™$6, 2.50โ€™, price=โ€™$quantity=2.50โ€™) 6) sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed before keyword arguments. The following statements are equivalent to the previous examples: sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) sell(item=โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) sell(price=โ€™$2.50โ€™, item=โ€™Socksโ€™, quantity=6) sell(price=โ€™$2.50โ€™, quantity=6, item=โ€™Socksโ€™) sell(quantity=6, item=โ€™Socksโ€™, price=โ€™$2.50โ€™) sell(quantity=6, price=โ€™$2.50โ€™, item=โ€™Socksโ€™) Finally, you can mix keyword and positional arguments, as long as all positional arguments are listed arguments. The following statements are equivalent to the previous examples: sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) Mix In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern), where In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern),
  • 7. sell(โ€™Socksโ€™, โ€™$2.50โ€™, quantity=6) Socksโ€™, quantity=6, price=โ€™$2.50โ€™) sell(โ€™Socksโ€™, price=โ€™$2.50โ€™, quantity=6) sell(โ€™Socksโ€™, quantity=6, price=โ€™$2.50โ€™) Using Named Groups In Python regular expressions, the syntax for named regular expression groups is (?P<name>name is the name of the group and pattern is some pattern to match. In Python regular expressions, the syntax for named regular expression groups is (?P<name>pattern), name is the name of the group and pattern is some pattern to match. Hereโ€™s an example URLconf that uses non-named groups: from django.conf.urls.defaults import * from mysite import views Hereโ€™s an example URLconf that uses non-named groups: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, urlpatterns = patterns(โ€™โ€™, (rโ€™^articles/(d{4})/$โ€™, views.year_archive), (rโ€™^articles/(d{4})/(d{2})/$โ€™, views.month_archive), (rโ€™^articles/(d{4})/$โ€™, views.year_archive), (rโ€™^articles/(d{4})/(d{2})/$โ€™, views.month_archive), ) Hereโ€™s the same URLconf, rewritten to use named groups: from django.conf.urls.defaults import * from mysite import views ) Hereโ€™s the same URLconf, rewritten to use named groups: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, urlpatterns = patterns(โ€™โ€™, (rโ€™^articles/(?P<year>d{4})/$โ€™, views.year_archive), (rโ€™^articles/(?P<year>d{4})/(?P<month>d{2})/$โ€™, views.month_archive), (rโ€™^articles/(?P<year>d{4})/$โ€™, views.year_archive), (rโ€™^articles/(?P<year>d{4})/(?P<month>d{2})/$โ€™, views.month_archive), ) This accomplishes exactly the same thing as the previous example, with one subtle difference: the captured passed to view functions as keyword arguments rather than positional arguments. ) This accomplishes exactly the same thing as the previous example, with one subtle difference: passed to view functions as keyword arguments rather than positional arguments.
  • 8. Using Named Groups โ€ข For example, with non-ยญโ€named groups, a request to /arAcles/ 2006/03/ would result in a funcAon call equivalent to this: month_archive(request, '2006', '03') โ€ข With named groups, though, the same request would result in this funcAon call: month_archive(request, year='2006', month='03')
  • 9. 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 posiAonal arguments. โ€ข In both cases, it will pass any extra opAons as keyword arguments. See the next secAon for more informaAon.
  • 10. โ€ข Otherwise, it will pass all non-named arguments as positional arguments. โ€ข In both cases, it will pass any extra options as keyword arguments. See the next section for more information. Passing Extra Options to View Functions 9.1.6 Passing Extra Options to View Functions Sometimes youโ€™ll find yourself writing view functions that are quite similar, with only a few small differences. example, say 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 from mysite.models import MyModel 9.1. URLconf Tricks Django Book Documentation, Release 0.1 def foo_view(request): m_list = MyModel.objects.filter(is_new=True) return render(request, โ€™template1.htmlโ€™, {โ€™m_listโ€™: m_list}) def bar_view(request): m_list = MyModel.objects.filter(is_new=True) return render(request, โ€™template2.htmlโ€™, {โ€™m_listโ€™: m_list}) Weโ€™re repeating ourselves in this code, and thatโ€™s inelegant. At first, you may think to remove the redundancy by the same view for both URLs, putting parentheses around the URL to capture it, and checking the URL within
  • 11. def bar_view(request): m_list = MyModel.objects.filter(is_new=True) return render(request, โ€™template2.htmlโ€™, {โ€™m_listโ€™: m_list}) Passing Extra Options to View Functions Weโ€™re repeating ourselves in this code, and thatโ€™s inelegant. At first, you may think to remove the redundancy by using 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, like so: # 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 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(request, template_name, {โ€™m_listโ€™: m_list}) The problem with that solution, though, is that it couples your URLs to your code. If you decide to rename /foo/ to /fooey/, youโ€™ll have to remember to change the view code. The elegant solution involves an optional URLconf parameter. Each pattern in a URLconf may include a third item: a dictionary of keyword arguments to pass to the view function. With this in mind, we can rewrite our ongoing example like this: The problem with that soluAon, though, is that it couples your URLs to your code. If you decide to rename /foo/ to /fooey/, youโ€™ll have to remember to change the view code.
  • 12. The /Passing problem with that solution, though, is that it couples your URLs to your code. If you decide to rename /fooey/, youโ€™ll have to Extra remember to change Options the view code. to View The elegant solution involves an optional URLconf parameter. Each pattern in a URLconf may include a third dictionary Functions of keyword arguments to pass to the view function. With this in mind, we can rewrite our ongoing example like this: # 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 from mysite.models import MyModel def foobar_view(request, template_name): m_list = MyModel.objects.filter(is_new=True) return render(request, template_name, {โ€™m_listโ€™: m_list}) As you can see, the URLconf in this example specifies template_name in the URLconf. The view function 128 Chapter 9. Chapter 8: Advanced Views and URLconfs
  • 13. ) And the view function signature would look like this: def my_view(request, month, day): Faking Captured URLconf Values # .... This approach is straightforward โ€“ itโ€™s nothing you havenโ€™t seen before. The trick comes in when you want another URL that uses my_view but whose URL doesnโ€™t include a month and/or day. For example, you might want to add another URL, /mydata/birthday/, which would be equivalent /mydata/jan/06/. You can take advantage of extra URLconf options like so: urlpatterns = patterns(โ€™โ€™, (rโ€™^mydata/birthday/$โ€™, views.my_view, {โ€™monthโ€™: โ€™janโ€™, โ€™dayโ€™: โ€™06โ€™}), (rโ€™^mydata/(?P<month>w{3})/(?P<day>dd)/$โ€™, views.my_view), ) The cool thing here is that you donโ€™t have to change your view function at all. The view function only cares that month and day parameters โ€“ it doesnโ€™t matter whether they come from the URL capturing itself or extra parameters. Making a View Generic Itโ€™s good programming practice to โ€œfactor outโ€ commonalities in code. For example, with these two Python functions: def say_hello(person_name): print โ€™Hello, %sโ€™ % person_name def say_goodbye(person_name): print โ€™Goodbye, %sโ€™ % person_name
  • 14. def greet(person_name, greeting): print โ€™%s, %sโ€™ % (greeting, person_name) Making a View Generic You can apply this same philosophy to your Django views by using extra URLconf parameters. With this in mind, you can start making higher-level abstractions of your views. Instead of thinking to yourself, โ€œThis view displays a list of Event objects,โ€ and โ€œThat view displays a list of BlogEntry objects,โ€ realize theyโ€™re both specific cases of โ€œA view that displays a list of objects, where the type of object is variable.โ€ Take Original this code, for example: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, (rโ€™^events/$โ€™, views.event_list), (rโ€™^blog/entries/$โ€™, views.entry_list), ) # views.py from django.shortcuts import render from mysite.models import Event, BlogEntry def event_list(request): obj_list = Event.objects.all() return render(request, โ€™mysite/event_list.htmlโ€™, {โ€™event_listโ€™: obj_list}) def entry_list(request): obj_list = BlogEntry.objects.all() return render(request, โ€™mysite/blogentry_list.htmlโ€™, {โ€™entry_listโ€™: obj_list}) The two views do essentially the same thing: they display a list of objects. So letโ€™s factor out the type of object theyโ€™re displaying:
  • 15. obj_list = Event.objects.all() return render(request, โ€™mysite/event_list.htmlโ€™, {โ€™event_listโ€™: obj_list}) def entry_list(request): Making a View Generic obj_list = BlogEntry.objects.all() return render(request, โ€™mysite/blogentry_list.htmlโ€™, {โ€™entry_listโ€™: obj_list}) The two views do essentially the same thing: they display a list of objects. So letโ€™s factor out the type of object displaying: # urls.py BeCer from django.conf.urls.defaults import * from mysite import models, views urlpatterns = patterns(โ€™โ€™, (rโ€™^events/$โ€™, views.object_list, {โ€™modelโ€™: models.Event}), (rโ€™^blog/entries/$โ€™, views.object_list, {โ€™modelโ€™: models.BlogEntry}), ) # views.py from django.shortcuts import render def object_list(request, model): obj_list = model.objects.all() template_name = โ€™mysite/%s_list.htmlโ€™ % model.__name__.lower() return render(request, template_name, {โ€™object_listโ€™: obj_list}) With those small changes, we suddenly have a reusable, model-agnostic view! From now on, anytime we need that Every lists Python a set of class objects, has we a can __name__ simply reuse aCribute this object_that returns list the view class rather name. than writing view code. Here
  • 16. var = do_something() return render(request, template_name, {โ€™varโ€™: var}) Understanding Precedence of Captured Values vs. Extra Options Understanding Precedence of Captured Values vs. Extra Options When thereโ€™s a conflict, extra URLconf parameters get precedence over captured parameters. URLconf if your URLconf captures captures a named-a named-ยญโ€group group variable variable and an and extra an extra URLconf URLconf parameter includes a variable the parameter extra URLconf includes parameter a variable value with the will same be used. name, the extra URLconf parameter value will be used. For example, consider this URLconf: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, (rโ€™^mydata/(?P<id>d+)/$โ€™, views.my_view, {โ€™idโ€™: 3}), ) Here, both the regular expression and the extra dictionary include an id. The hard-coded means any request (e.g., /mydata/2/ or /mydata/432432/) will be treated as if id value id captured will be 3. in the URL. Astute readers will note that in this case, itโ€™s a waste of time and typing to capture the id because its value will always be overridden by the dictionaryโ€™s value. Thatโ€™s correct; we bring avoid making the mistake.
  • 17. 9.1.7 Using Default View Arguments Another convenient trick is to specify default parameters use Using for a parameter Default by default if none is View specified. Arguments for a viewโ€™s arguments. This tells the view An example: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, (rโ€™^blog/$โ€™, views.page), (rโ€™^blog/page(?P<num>d+)/$โ€™, views.page), ) # views.py def page(request, num=โ€™1โ€™): # Output the appropriate page of blog entries, according to num. # ... Here, both URL patterns point to the same view โ€“ views.page โ€“ but the first pattern doesnโ€™t capture the URL. If the first pattern matches, the page() function will use its default argument for num, โ€™1โ€™. pattern matches, page() will use whatever num value was captured by the regular expression. (Note that weโ€™ve been careful to set the default argumentโ€™s value to the string โ€™1โ€™, not the integer consistency, because any captured value for num will always be a string.) Itโ€™s common to use this technique in conjunction with configuration options, as explained earlier. This example
  • 18. Special-ยญโ€Casing Views Django Book else: SomeAmes youโ€™ll have a paCern in your URLconf that handles a large set of URLs, but youโ€™ll need to special-ยญโ€case one of them. In this case, take advantage of the linear way a # URLconf do normal is processed code and put the special case first. but thatโ€™s inelegant for a reason weโ€™ve touched on multiple times in this chapter: it more elegant solution, we can take advantage of the fact that URLconfs are processed urlpatterns = patterns(โ€™โ€™, # ... (โ€™^auth/user/add/$โ€™, views.user_add_stage), (โ€™^([^/]+)/([^/]+)/add/$โ€™, views.add_stage), # ... ) With this in place, a request to /auth/user/add/ will be handled by the user_add_URL matches the second pattern, it matches the top one first. (This is short-circuit logic.) 9.1.9 Capturing Text in URLs
  • 19. so) about accepting only objects of a certain type. A common error is to attempt to create a datetime.date object with string values instead of integer values: >>> import datetime >>> datetime.date(โ€™1993โ€™, โ€™7โ€™, โ€™9โ€™) Traceback (most recent call last): Capturing Text in URLs ... Each captured argument is sent to the view as a plain Python Unicode string, regardless of what sort of match the regular expression makes. TypeError: an integer is required >>> datetime.date(1993, 7, 9) datetime.date(1993, 7, 9) Translated Wrong to a URLconf and view, the error looks like this: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, (rโ€™^articles/(d{4})/(d{2})/(d{2})/$โ€™, views.day_archive), ) # views.py import datetime def day_archive(request, year, month, day): # The following statement raises a TypeError! date = datetime.date(year, month, day) Django Book Documentation, Release 0.1 Instead, Correct day_archive() can be written correctly like this: def day_archive(request, year, month, day): date = datetime.date(int(year), int(month), int(day)) 9.1. URLconf Tricks 133 Note that int() itself raises a ValueError when you pass it a string that is not composed solely of digits, but
  • 20. 9.1.11 Higher-Level Abstractions of View Functions And speaking of branching based on request method, letโ€™s take a look at how we might build a nice way of doing Consider this URLconf/view layout: # urls.py Higher-ยญโ€level Abstractions of View Functions(Original) from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, # ... (rโ€™^somepage/$โ€™, views.some_page), # ... ) # views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render def some_page(request): if request.method == โ€™POSTโ€™: do_something_for_post() return HttpResponseRedirect(โ€™/someurl/โ€™) elif request.method == โ€™GETโ€™: do_something_for_get() return render(request, โ€™page.htmlโ€™) else: raise Http404() In this example, the some_page() viewโ€™s handling of POST vs. GET requests is quite different. The only thing
  • 21. Higher-ยญโ€level Abstractions of View Functions(no args and kwargs) Django Book Documentation, Release 0.1 We can do that by writing a view function that delegates to other views, either before or after executing some custom logic. Hereโ€™s an example of how this technique could help simplify our some_page() view: # views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render def method_splitter(request, GET=None, POST=None): if request.method == โ€™GETโ€™ and GET is not None: return GET(request) elif request.method == โ€™POSTโ€™ and POST is not None: return POST(request) raise Http404 def some_page_get(request): assert request.method == โ€™GETโ€™ do_something_for_get() return render(request, โ€™page.htmlโ€™) def some_page_post(request): assert request.method == โ€™POSTโ€™ do_something_for_post() return HttpResponseRedirect(โ€™/someurl/โ€™) # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns(โ€™โ€™, # ... (rโ€™^somepage/$โ€™, views.method_splitter, {โ€™GETโ€™: views.some_page_get, โ€™POSTโ€™: views.some_page_post}), # ...
  • 22. Django Book Documentation, Release 0.1 Higher-ยญโ€level Abstractions of View Functions(args and kwargs) GET and POST views take no arguments other than request. What if we wanted to use method_with views that, for example, capture text from URLs, or take optional keyword arguments themselves? To do that, we can use a nice Python feature: variable arguments with asterisks. Weโ€™ll show the example explain it: def method_splitter(request, *args, **kwargs): get_view = kwargs.pop(โ€™GETโ€™, None) post_view = kwargs.pop(โ€™POSTโ€™, None) if request.method == โ€™GETโ€™ and get_view is not None: return get_view(request, *args, **kwargs) elif request.method == โ€™POSTโ€™ and post_view is not None: return post_view(request, *args, **kwargs) raise Http404 Here, weโ€™ve refactored method_splitter() to remove the GET and POST keyword arguments, in and **kwargs (note the asterisks). This is a Python feature that allows a function to accept a dynamic, number of arguments whose names arenโ€™t known until runtime. If you put a single asterisk in front of a function definition, any positional arguments to that function will be rolled up into a single tuple. asterisks in front of a parameter in a function definition, any keyword arguments to that function will a single dictionary. For example, with this function: def foo(*args, **kwargs):
  • 23. Wrapping View Functions (Original) Django Book Documentation, def my_view2(request): if not request.user.is_authenticated(): return HttpResponseRedirect(โ€™/accounts/login/โ€™) # ... return render(request, โ€™template2.htmlโ€™) def my_view3(request): if not request.user.is_authenticated(): return HttpResponseRedirect(โ€™/accounts/login/โ€™) # ... return render(request, โ€™template3.htmlโ€™) Here, each view starts by checking that request.user is authenticated โ€“ that is, the logged into the site โ€“ and redirects to /accounts/login/ if not. (Note that request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user either logged-in or anonymous.) It would be nice if we could remove that bit of repetitive code from each of these views and
  • 24. request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user represents the current either logged-in or anonymous.) It would be nice if we could remove that bit of repetitive code from each of these views and just mark them as requiring authentication. We can do that by making a view wrapper. Take a moment to study this: def requires_login(view): logged into the site โ€“ and redirects to /accounts/login/ if not. (Note that we request.user โ€“ Chapter 14 does โ€“ but, as you might imagine, request.user represents either Wrapping logged-in or anonymous.) View Functions (elegant) It would be nice if we could remove that bit of repetitive code from each of these views and just authentication. def new_view(We request, can do that *args, by making **kwargs): a view wrapper. Take a moment to study this: if not request.user.is_authenticated(): def requires_login(view): return HttpResponseRedirect(โ€™/accounts/login/โ€™) def return new_view(view(request, request, *args, *args, **kwargs) **kwargs): return new_view if not request.user.is_authenticated(): return HttpResponseRedirect(โ€™/accounts/login/โ€™) This function, return requires_login, takes a view function (view) and returns a new view function (The new function, view(request, args, kwargs) new_new_view is defined *within requires_**login and handles the logic of checking request.return user.new_is_authenticated() view and delegating to the original view (view). Now, we can remove the if not request.user.is_authenticated() checks from our views and wrap them with requires_login in our URLconf: from django.conf.urls.defaults import * from mysite.views import requires_login, my_view1, my_view2, my_view3 This function, requires_login, takes a view function (view) and returns a new view The new function, new_view is defined within requires_login and handles request.user.is_authenticated() and delegating to the original view (view). Now, we can remove the if not request.user.is_authenticated() checks from wrap them with requires_login in our URLconf: from django.conf.urls.defaults import * from mysite.views import requires_login, my_view1, my_view2, my_view3 urlpatterns = patterns(โ€™โ€™, (rโ€™^view1/$โ€™, requires_login(my_view1)), (rโ€™^view2/$โ€™, requires_login(my_view2)), (rโ€™^view3/$โ€™, requires_login(my_view3)), ) This urlpatterns has the same effect = patterns(โ€™โ€™, as before, but with less code redundancy. Now weโ€™ve created a nice, generic function requires_login() that we can wrap around any view in order to make it require login. (rโ€™^view1/$โ€™, requires_login(my_view1)), (rโ€™^view2/$โ€™, requires_login(my_view2)), (rโ€™^view3/$โ€™, requires_login(my_view3)),
  • 25. If you intend your code to be used on multiple Django-based sites, you should consider arranging such At Including a way that allows for โ€œincluding.โ€ any point, your URLconf Other can โ€œincludeโ€ URLconfs other URLconf modules. This essentially โ€œrootsโ€ other ones. For example, this URLconf includes other URLconfs: from django.conf.urls.defaults import * 9.2. Including Other URLconfs Django Book Documentation, Release 0.1 urlpatterns = patterns(โ€™โ€™, (rโ€™^weblog/โ€™, include(โ€™mysite.blog.urlsโ€™)), (rโ€™^photos/โ€™, include(โ€™mysite.photos.urlsโ€™)), (rโ€™^about/$โ€™, โ€™mysite.views.aboutโ€™), ) (We saw this before in Chapter 6, when we introduced the Django admin site. The admin site that you merely include() within yours.) Thereโ€™s an important gotcha here: the regular expressions in this example that point to an include() $ (end-of-string match character) but do include a trailing slash. Whenever Django encounters off whatever part of the URL matched up to that point and sends the remaining string to the further processing. Continuing this example, hereโ€™s the URLconf mysite.blog.urls: from django.conf.urls.defaults import * urlpatterns = patterns(โ€™โ€™, (rโ€™^(dddd)/$โ€™, โ€™mysite.blog.views.year_detailโ€™),
  • 26. โ€ข /about/: This matches the view mysite.views.about in the first URLconf, demonstrating mix include() patterns with non-include() patterns. How Captured Parameters Work with include() 9.2.1 How Captured Parameters Work with include() An included URLconf receives any captured parameters from parent URLconfs, for example: # root urls.py from django.conf.urls.defaults import * urlpatterns = patterns(โ€™โ€™, (rโ€™^(?P<username>w+)/blog/โ€™, include(โ€™foo.urls.blogโ€™)), ) # foo/urls/blog.py from django.conf.urls.defaults import * urlpatterns = patterns(โ€™โ€™, (rโ€™^$โ€™, โ€™foo.views.blog_indexโ€™), (rโ€™^archive/$โ€™, โ€™foo.views.blog_archiveโ€™), ) In this example, the captured username variable is passed to the included URLconf and, function within that URLconf.
  • 27. 9.2.2 How Extra URLconf Options Work with include() Similarly, you can pass extra URLconf options to include(), just as you can pass extra normal view โ€“ as a dictionary. When you do this, each line in the included URLconf will be For example, the following two URLconf sets are functionally identical. Set one: # urls.py How Extra URLconf Options Work with include() from django.conf.urls.defaults import * urlpatterns = patterns(โ€™โ€™, (rโ€™^blog/โ€™, include(โ€™innerโ€™), {โ€™blogidโ€™: 3}), ) # inner.py from django.conf.urls.defaults import * urlpatterns = patterns(โ€™โ€™, (rโ€™^archive/$โ€™, โ€™mysite.views.archiveโ€™), (rโ€™^about/$โ€™, โ€™mysite.views.aboutโ€™), (rโ€™^rss/$โ€™, โ€™mysite.views.rssโ€™), ) Set two: