本文的view基于cbv模式,django为1.11,1.8到1.11下面的大部分内容使用。
django解析url过程。
- 一般情况下,django从setting中找到ROOT_URLCONF ,使用这个URLconf的作为根模块。
- 加载这个模块,找到urlpatterns变量,这个变量必须是django.conf.urls.url对象的一个列表。
- 遍历整个列表,通过正则表达式匹配到第一个view函数或基于类的view。
- 这个view会得到三种类型的参数(最多):
request实例,通过正则表达式传过来的参数,额外的参数 - 如果没有匹配到,那么会调用相关的error-handling view.
简单的URLconf
from django.conf.urls import url
from articles.view import ArticleListView
urlpatterns = [
url('^articles/$', ArticleListView.as_view()),
]
带参数的URLconf
1. 位置参数(不推荐使用)
from django.conf.urls import url
from articles.view import ArticleListView
urlpatterns = [
# url表示某年某月的文章列表
url('^articles/([0-9]{4})/([0-9]{2})$', ArticleListView.as_view()),
]
url如articles/2018/01/,这样相当于调用这个类(cbv)下面的get(request, ‘2018’, ‘01’)
2. 关键参数(推荐)
from django.conf.urls import url
from articles.view import ArticleListView
urlpatterns = [
# url表示某年某月的文章列表
url('^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})$', ArticleListView.as_view()),
]
同样的例子,这样写法表示调用get(request, year=’2018’, month=’01’)
需要注意的是,使用关键参数,在定义相关方法,如get,post等,参数的名字一定要匹配。
3. 嵌套参数
urlpatterns = [
url('^articles/(page-(\d+)/)?$', ArticleListView.as_view()), #bad
url('^articles/(?:page-(?P<page_number>\d+)/)?$', ArticleListView.as_view()), #good
]
上述2个url匹配表达同样的意思,获取到当前页的page作为参数传递给view,url要么只是articles/,要么就是articles/page-2/(例子),当第一个会传递2个参数,page-2以及2,很明显page-2这个参数我们并不需要,而第二个只会传递2这个参数,很明显,第二个优于第一个,正则(?:)表示只用于匹配但不把值保留。
- 额外参数
urlpatterns = [
url(r'^articles/(?P<year>[0-9]{4})/$', ArticleListView.as_view(), {'foo': 'bar'}),
]
如 /articles/2018/,相当于调用了类下面的get(request, year=’2005’, foo=’bar’)
include
试想一下,某个app下定义了十几个view,如果全部写到同一个urlpatterns下,这当然可以,但管理起来就会很混乱,这个时候,include就发挥作用了。
# 全部写在根URLconf下
from django.conf.urls import include, url
...
extra_patterns = [
url(r'^info/$', UserInfoView.as_view()),
url(r'^fav/$', UserFavView.as_view()),
]
urlpatterns = [
# 注意不要写末尾符号$
url(r'^user/', include(extra_patterns)),
]
更优的应该是在app下建立一个urls.py文件,专门存放这个app的相关url
# urls.py
urlpatterns = [
# 注意不要写末尾符号$
url(r'^user/', include(users.urls)),
]
# users/urls.py
urlpatterns = [
url(r'^info/$', UserInfoView.as_view()),
url(r'^fav/$', UserFavView.as_view()),
]
如果是在根URLconf传递的参数,那么在子的urlpatterns中,每一个view都会去接受这个参数
反解url
这部分内容应该是整个URLconf最重要的内容了,试想一下,每一个url都相对比较长,而且又难记,我们肯定希望有一个方法能够解决这个问题,那么就是name了,给每一个url进行命名! 通过这个name来反解出url。
urlpatterns = [
url(r'^article/detail/(?P<ariticle_id>[0-9]{4})/$', ArticleListView.as_view(), name='article_detail'),
]
这样子,我们可以使用article_detail来代表这个url了,在template中,我们可以使用url这个tag来表示!
<ul>
{% for ariticle in ariticles %}
<li>
{# 注意参数的传递}
<a href="{% url 'article_detail' ariticle.id %}">{{ ariticle.name }} </a>
</li>
{% endfor %}
</ul>
反解url在进行重定向的时候也经常使用,例如在成功登录后重定向到主页
from django.urls import reverse
from django.http import HttpResponseRedirect
class LoginView(View):
def post(request):
# ...
return HttpResponseRedirect(reverse('index'))
reverse 函数还可以传递参数:
reverse('article_detail', args=(ariticle_id,))
反解namespace urls
现在存在一个问题,就是如果我们使用了include,那么我们要怎么做到name与url的一对一呢,namespace就是来解决这个问题的!
# urls.py
urlpatterns = [
# 注意不要写末尾符号$
url(r'^user/', include(users.urls, namespace=users)),
]
# users/urls.py
urlpatterns = [
url(r'^info/$', UserInfoView.as_view(), name='info'),
url(r'^fav/$', UserFavView.as_view(), name='fav'),
]
还有另外一种写法!在子URLconf设置app_name属性
# urls.py
urlpatterns = [
# 注意不要写末尾符号$
url(r'^user/', include(users.urls)),
]
# users/urls.py
app_name = 'users'
urlpatterns = [
url(r'^info/$', UserInfoView.as_view(), name='info'),
url(r'^fav/$', UserFavView.as_view(), name='fav'),
]
那么, 怎么去调用他们呢!格式:’namespace:name’
reverse('users:info')
template中:
{% url 'users:info' %}
本篇内容还缺少error-handling view, 等博主研究完了再更新~
总结
本篇重点应该是namespace以及name的使用,还有参数的传递!
如果有什么错误,欢迎各位的指出~ 感谢!