Advanced Views and URLconfs
10/08 @ Django Girls meetup
Kelly Chang
What we've got now
in Django 1.8
from django.conf.urls import include, url
from django.contrib import admin
from mysite.views import hello, current_datetime, hours_ahead
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^hello/$', hello),
url(r'^time/$', current_datetime),
url(r'^time/plus/(\d{1,2})/$', hours_ahead),
]Avoiding imports
by importing views module
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^hello/$', views.hello),
url(r'^time/$', views.current_datetime),
url(r'^time/plus/(d{1,2})/$', views.hours_ahead),
]Avoiding imports
by using strings
from django.conf.urls.defaults import *
urlpatterns = [
url(r'^hello/$', 'mysite.views.hello'),
url(r'^time/$', 'mysite.views.current_datetime'),
url(r'^time/plus/(d{1,2})/$', 'mysite.views.hours_ahead'),
]DEBUG only!
from django.conf import settings
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.homepage),
url(r'^(\d{4})/([a-z]{3})/$', views.archive_month),
]
if settings.DEBUG:
urlpatterns += [url(r'^debuginfo/$', views.debug),]Named Groups
capture values from named arguments
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^reviews/2003/$', views.special_case_2003),
url(r'^reviews/([0-9]{4})/$', views.year_archive),
url(r'^reviews/([0-9]{4})/([0-9]{2})/$', views.month_archive),
]from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^reviews/2003/$', views.special_case_2003),
url(r'^reviews/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^reviews/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
]named
unnamed
Things to keep in mind...
- Always strings
- named groups first
- you can set default values
# URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^reviews/$', views.page),
url(r'^reviews/page(?P<num>[0-9]+)/$', views.page),
]
# View (in reviews/views.py)
def page(request, num="1"):
# Output the appropriate page of review entries, according to num.
...Including other URLconfs
from django.conf.urls import include, url
from .views import *
urlpatterns = [
url(r'', 'schedule.views.dashboard'),
url(r'book/', 'shedule.views.booking'),
]from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^schedule/', include('schedule.urls')),
]
mysite/mysite/urls.py
mysite/schedule/urls.py
File Structure
mysite/
manage.py
mysite/
schedule/
Examples
/schedule/
/schedule/book/
Other includes...
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/history/$', views.history),
url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/edit/$', views.edit),
url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/discuss/$', views.discuss),
]Reduce common prefix to...
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
])),
]Extra options
passing argument to views
# 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
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})example:
# 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})URL Reversing
Start from the view to obtain certain url.
Avoid hard-coded urls.
Edit just in one place.
case 1, in templates:
Using the url template tag.
# urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^reviews/([0-9]{4})/$', views.year_archive, name='reviews-year-archive'),
url(r'^index/$', views.index_view, name='indexpage'),
#...
]<!--template.html-->
<a href="{% url 'reviews-year-archive' 2012 %}">2012 Archive</a>
<div>{% url 'indexpage' %}</div>case 2, in python code:
Using django.core.urlresolvers.reverse() function
# urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^reviews/([0-9]{4})/$', views.year_archive, name='reviews-year-archive'),
#...
]# views.py
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def redirect_to_year(request):
# ...
year = 2012
# ...
return HttpResponseRedirect(reverse('reviews-year-archive', args=(year,)))What if names duplicate?
URL Namespace
Allow you to uniquely reverse named URL patterns even if different applications use the same URL names
Simple example:
# mysite/urls.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^author-polls/', include('polls.urls', namespace='authors')),
]# polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
]<!--index.html-->
{% url 'authors:index' %}Specify namespace in URLConfs
# mysite/urls.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')),
]# polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
]<!--index.html-->
{% url 'polls:index' %}# views.py
reverse('polls:index', current_app=self.request.resolver_match.namespace)Thanks for attention!
Django
By Kelly Chang
Django
- 6,473