美文网首页
Django:02.URLconf路由

Django:02.URLconf路由

作者: Zzmi | 来源:发表于2019-02-26 15:51 被阅读0次

    1、URLconf

    — URL配置(URLconf)就像Django所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表。以这种方式告诉Django,对于不同请求的URL需要去调取哪段代码。

    # URLconf配置
    from django.conf.urls import url
    urlpatterns = {
        url(正则表达式, views试图函数, 参数, 别名)
    }
    """
    正则表达式:一个正则表达式字符串
    views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
    参数:可选的要传递给视图函数的默认参数(字典形式)
    别名:一个可选的name参数
    """
    

    Django2.0版本中的路由系统已经替换成下面的写法 官方文档

    from django.urls import path
    urlpatterns = [
        path('articles/2003/', views.special_case_2003),
        path('articles/<int:year>/', views.year_archive),
        path('articles/<int:year>/<int:month>/', views.month_archive),
        path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]
    

    2、URLconf的正则字符串参数

    2.1 简单配置
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/([0-9]{4})/$', views.year_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
        url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
    ]
    

    规则:
    1. 一旦匹配成功则不再继续
    2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号
    3. 不需要添加一个前导的反斜杠,因为每个URL中Django都会主动添加。如: 应该是^articles,而不是^/articles
    4. 每个正则表达式前面的'r',是可选的但是建议加上,防止字符转义
    实例分析:
    ⒈/articles/2005/3/ 不匹配任何URL模式,因为列表中的第三个模式要求月份应该是两个数字
    ⒉/articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配
    ⒊/articles/2005/03/ 请求将匹配列表中的第三个模式。Django将调用view.py中的函数:views.month_archive(request, '2005', '03')
    APPEND_SLASH:
    Django seetings.py配置文件中默认没有这个参数,但Django默认这个参数为 APPEND_SLASH = True。作用就是自动在网址结尾加'/'。

    2.2 name group

    — 除了可以用未经命名的正则表达式组来捕获URL中的值,并以位置参数传递给视图 。还可以用命名的正则表达式组来捕获URL中的值,后以关键字参数传递给视图。区别就是位置参数变成了关键字参数,其余不变。注意:参数永远只以字符串形式传递给对应的函数
    — 在Python正则表达式中,命名正则表达式组的语法为【(?P<name>pattern)】,其中name是组的名称,pattern是要匹配的模式

    • 重写未命名的正则表达式组
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
        url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
        url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
    ]
    

    /articles/2005/03/
    请求将调用views.month_archive(request, year='2005', month='03')
    /articles/2003/03/03/
    请求将调用views.article_detail(request, year='2003', month='03', day='03')

    2.3 URLconf如何处理URL

    — URLconf将请求的URL当作一个普通的Python字符串,不区分请求方式的参数及域名
    — eg:
    http://www.admin.com/restapi/请求中,URLconf只查找restapi/
    http://www.admin.com/restapi/?number=12请求中,URLconf仍只查找restapi/
    — URLconf不检查请求的方法。也就是说,在同一个URL中无论是POST、GET、HEAD亦或DELETE请求方法,都将被路由到相同的函数

    2.4 指定视图参数的默认值
    # URLconf
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^blog/$', views.page),
        url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
    ]
    
    # View (in blog/views.py)
    def page(request, num="1"):
        ....
    

    — 上面两条URL都指定同一个page视图函数,但第一个并不会从URL中捕获到任何参数,如果第一个进行模式匹配,page()将使用【num="1"】作为默认值;如果是第二个进行模式匹配,page()将使用正则表达式捕获num值。

    3、传递额外的选项给视图函数

    — URLconf有一个钩子,可以传递一个Python字典作为额外的参数传递给视图函数
    — django.conf.urls.url()函数可以接收一个可选的字典类型的第三个参数,表示想要传递给视图函数额外的关键字参数

    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^api/(?<year>[0-9]{4})/$', views.year_archive, {'cookie': 'lee'})
    ]
    

    — 在这个例子中,对于/api/2018/请求,Django将调用views.year_archive(request, year='2018', cookie='lee')。这个技术在Syndication 框架中使用,来传递元数据和选项给视图。

    4、URL反向解析

    — Django中提供了一个关于URL的映射的解决方案,你可以做两个方向的使用:
    ① 有客户端的浏览器发起一个url请求,Django根据URL解析,把url中的参数捕获,调用相应的试图,获取相应的数据,然后返回给客户端显示。
    ② 通过一个视图的名字,再加上一些参数和值,逆向获取相应的URL。
    :| 第一个就是平常的请求有URLconf来解析的过程,第二个叫做,url的逆向解析,url逆向匹配,url的逆向查阅等

    — Django提供了不同的层级的url逆向处理工具:
    ⑴ 在模板templates中,使用url标记,如:{% url %}
    ⑵ 在Python代码中,使用django.core.urlresolvers.reverse()方法
    ⑶ 在更高一层级的处理url中,用get_absolute_url()方法

    from django.conf.urls import patterns, url
    
    urlpatterns = [
        url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
    ]
    # 根据设计,这个url的目的是将是nnnn年的文章存档(archive),即/articles/nnnn/
    
    // 在模板中,可以这样来使用:
    <a href="{% url 'news.views.year_archive' 2012 %}">2012 Archive</a>
    {# Or with the year in a template context variable: #}
    <ul>
        {% for yearvar in year_list %}
        <li><a href="{% url 'news.views.year_archive' yearvar %}">{{ yearvar }} Archive</a></li>
        {% endfor %}
    </ul>
    
    {# 别名设置
    {% url 'some-url-name' arg arg2 as the_url %}
    <a href="{{ the_url }}">链接到:{{ the_url }}</a>
     #}
    

    — 根据视图 'news.views.year_artichive'可以定位到指定的URLconf中,然后后面的2012来填充articles/\d{4},最终的结果为<a href="articles/2012/">2012 Archive</a>,这里就是根据试图和所提供的值来逆向查询url

    from django.core.urlresolvers import reverse
    from django.http import HttpResponseRedirect
    
    def redirect_to_year(request):
        year = 2006
        return HttpResponseRedirect(reverse('news.views.year_archive', args=(year,)))
    

    — 必须引入django.core.urlresolvers.reverse()方法,然后原理就是,根据提供的试图和参数的值来逆向查找URLconf,匹配相应的url然后把值拿回来,最后,reverse()返回的值为:articles/2006/,这样就逆向的查出了需要的url

    5、Namespace(命名空间)

    ——命名空间是表示标识符的可见范围。一个标识符可以在多个命名空间中定义,并且在不同的命名空间中的含义互不相干,不会引起冲突。
    ——我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
    ——由于name没有作用域,Django在反向解析URL时,搜索顺序是从全局开始,依次往里查找,当找到第一个name指定的URL后,马上返回停止查找

    # 项目的urls.py
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^test1/', include("test1.urls",namespace="test1")),
        url(r'^test2/', include("test2.urls",namespace="test2")),
    ]
    
    # test1中的urls.py
    app_name = 'test1'
    urlpatterns = [
        url(r'^(?P<pk>\d+)/$', views.detail, name='idnex')
    ]
    # test2中的urls.py
    app_name = 'test2'
    urlpatterns = [
        url(r'^(?P<pk>\d+)/$', views.detail, name='index')
    ]
    
    # test1中的views.py
    from django.core.urlresolvers import reverse
    def index(request, pk):
        return  HttpResponse(reverse("test1: index", kwargs={'pk': 5}))
    # test2中的views.py
    from django.core.urlresolvers import reverse
    def index(request, pk):
        return  HttpResponse(reverse("test2: index", kwargs={'pk': 5}))
    

    ——现在,我的两个app中url名称重复了,但是反转URL的时候就可以通过命名空间的名称得到我当前的URL。
    语法'命名空间名称: URL名称'
    模板中使用:{% url 'test1: index' pk=5 %}
    views中的函数中使用:v = reverse('test1: index', kwargs={'pk': 5})
    ——这样即使app中URL的命名相同,也可以反转得到正确的URL了。

    6、CBV(示例)

    url(r'^rate/$', rate.RateView.as_view(),
    # --------------------------------------------------------
    class RateView(ViewSetMixin, APIView):
        def list(self, request, *args, **kwargs):
            """
            :param request:
            :param args:
            :param kwargs:
            :return:
            """
            ret = {'code': 1000, 'data': None}
            try:
                queryset = models.Rate.objects.all()
                ser = RateSerializer(instance=queryset, many=True)
                ret['data'] = ser.data
            except Exception as e:
                ret['code'] = 1001
                ret['error'] = '获取费率失败'
            return Response(ret)
    
        def retrieve(self, request, *args, **kwargs):
            """
            :param request:
            :param args:
            :param kwargs:
            :return:
            """
            ret = {'code': 1000, 'data': None}
            try:
                pk = kwargs.get('pk')
                obj = models.RateDetail.objects.filter(rate_id=pk).first()
                ser = RateDetailSerializer(instance=obj, many=False)
                ret['data'] = ser.data
            except Exception as e:
                ret['code'] = 1001
                ret['error'] = '获取费率失败'
            return Response(ret)
    
    结语:
    ——django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁

    相关文章

      网友评论

          本文标题:Django:02.URLconf路由

          本文链接:https://www.haomeiwen.com/subject/zyareqtx.html