django url配置篇

686 阅读2分钟

本文的view基于cbv模式,django为1.11,1.8到1.11下面的大部分内容使用。

django解析url过程。

  1. 一般情况下,django从setting中找到ROOT_URLCONF ,使用这个URLconf的作为根模块。
  2. 加载这个模块,找到urlpatterns变量,这个变量必须是django.conf.urls.url对象的一个列表。
  3. 遍历整个列表,通过正则表达式匹配到第一个view函数或基于类的view。
  4. 这个view会得到三种类型的参数(最多):
    request实例,通过正则表达式传过来的参数,额外的参数
  5. 如果没有匹配到,那么会调用相关的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')

  1. 关键参数(推荐)
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等,参数的名字一定要匹配。

  1. 嵌套参数
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这个参数,很明显,第二个优于第一个,正则(?:)表示只用于匹配但不把值保留。

  1. 额外参数
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的使用,还有参数的传递!

如果有什么错误,欢迎各位的指出~ 感谢!