Django之路由系统

路由系统

2017年12月2号,Django2.0发布,路由系统添加了path函数,与url共存。

 

 说明:

第一,目前 路由(url)到视图(View)的流程可以概括为四个步骤:

  1. url匹配
  2. 正则捕获
  3. 变量类型转化
  4. 视图调用

Django2.0 和之前相比多了 变量类型转化 这一步骤。

第二,新的path语法可以解决一下以下几个场景:

  • 类型自动转化
  • 公用正则表达式

一、url(2.0依然支持url)

1、单一路由对应

url(r'^index$', views.index),

2、基于正则的路由

url(r'^index1/(\w*)/(\d*)$',views.index1),  # 可通过*args获取tupple数据,也可通过制定名称参数
url(r'^index2/(?P<name>\w*)/(?P<id>\d*)$', views.index2),  # 通过**kwargs获取字典数据
    def index1(request,*args,**kwargs):
        if request.method == "GET":
            print(request)  # request: < WSGIRequest: GET '/index1/abc/123' >
            print(args)  # args: ('abc', '123')
            print(kwargs)  # kwargs: {}
            return render(request,"index.html")

    def index2(request,*args,**kwargs):
        if request.method == "GET":
            print(request)  # request: <WSGIRequest: GET '/index2/abc/123'>
            print(args)  # args: ()
            print(kwargs)  # kwargs: {'name': 'abc', 'id': '123'}
            return render(request,"index.html")
views.py及结果

3、添加额外的参数

url(r'^index3/(?P<name>\w*)/(?P<id>\d*)', views.index3,{'age':18}),    # 仅针对views里**kwargs
    def index3(request,*args,**kwargs):
        if request.method == "GET":
            print(request)  # request: <WSGIRequest: GET '/index3/abc/123'>
            print(args)  # args: ()
            print(kwargs)  # kwargs: {'name': 'abc', 'id': '123', 'age': 18}
            return render(request,"index.html")
views.py及结果

4、为路由映射设置名称

url(r'^index4/(\w*)/(\d*)$', views.index4,name="h1"),  # 数据匹配的个数与reverse和HTML里的参数个数一致

设置名称之后,可以在不同的地方调用,如:

  • 模板中使用生成URL     {% url 'h2' 2012 %}
  • 函数中使用生成URL     reverse('h2', args=(2012,))      路径:django.urls.reverse
  • Model中使用获取URL  自定义get_absolute_url() 方法
    用法一
    <h2>{% url 'h1' "abcdefghigjklmn" 2012 %}</h2>  # /index4/abcdefghigjklmn/2012

    用法二
    r = reverse('h1', args=("abcdefg",2012,))  # /index4/abcdefg/2012

    用法三
    class NewType(models.Model):
        caption = models.CharField(max_length=16)

    def get_absolute_url(self):
        """
        为每个对象生成一个URL
        应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
        :return:
        """
        # return '/%s/%s' % (self._meta.db_table, self.id)
        #
        from django.urls import reverse
        return reverse('NewType.Detail', kwargs={'nid': self.id})
以上三种用法

namespace

  reverse("{0}:{1}".format(namespace,urlname))

示例

"""first_review URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path,include

urlpatterns = [
    re_path("testurls/",include("testurls.urls")),
    re_path("testurls_fornamespace/",include("testurls.urls",namespace="forurls")),
]
urls.py
"""first_review URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path,include
from testurls import views

app_name = "testurls"  # 使用了namespace,则必须定义app_name

urlpatterns = [
    re_path("index.html/$",views.Index.as_view(),name="index"),
    re_path("index.html/(?P<page>\d+)/$",views.Index.as_view(),name="index_with_kwargs"),
    re_path("index/(\d+).html$",views.Index.as_view(),name="index_with_args"),

    re_path("index2.html/$",views.Index2.as_view(),name="index2")

]
/testurls/urls.py
from django.shortcuts import render
from django.views import View
from django.urls import reverse

class Index(View):
    def get(self,request,*args,**kwargs):

        # 访问/testurls/index.html/
        this_url = reverse("index",)  # 若有app_name = "testurls",则为testurls:index如下,已实验
        print(this_url)  # /testurls/index.html/
        # this_url = reverse("testurls:index", )
        # print(this_url)  # # /testurls/index.html/

        # 访问/testurls/index.html/22/
        # this_url = reverse("index_with_kwargs",kwargs=kwargs)
        # print(this_url)  # /testurls/index.html/22/


        # 访问 /testurls/index/33.html
        # this_url = reverse("index_with_args",args=args)
        # print(this_url)  # /testurls/index/33.html

        context = {"args":args}
        return render(request,"index2.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>{% url 'index' %}</div>
    <div>{% url 'index_with_kwargs' 213  %}</div>
    <div>{% url 'index_with_args' args.0 %}</div>
</body>
</html>
index.html

namespace也验证成功

5、根据app对路由规则进行分类

    urls.py
        url(r'^index/',include('web.urls')),
    web/urls.py
        url(r'^(?P<name>\w*)/(?P<id>\d*)$',views.index)  # 。。。/index/abc/123

6、命名空间

project.urls.py

        from django.conf.urls import url,include
 
        urlpatterns = [
            url(r'^a/', include('app01.urls', namespace='author-polls')),
            url(r'^b/', include('app01.urls', namespace='publisher-polls')),
        ]

app01.urls.py

    app01.urls.py
        from django.conf.urls import url
        from app01 import views
         
        app_name = 'app01'
        urlpatterns = [
            url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
        ]

app01.views.py

    app01.views.py
        def detail(request, pk):
            print(request.resolver_match)
            v = reverse('app01:detail', kwargs={'pk':11})  # ResolverMatch(func=app01.views.detail, args=(), kwargs={'pk': '123'}, url_name=detail, app_names=['app01'], namespaces=['author-polls'])
            print(v)
            return HttpResponse(pk)

以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

  • v = reverse('app01:detail', kwargs={'pk':11})
  • {% url 'app01:detail' pk=12 pp=99 %}

 

二、path,re_path(版本2.0及之后)

1、re_path

from django.urls import path,re_path,include

 其中,re_path具有上述url的6个功能且用法一样,只需把url替换为re_path即可。

 2、path

转换器Path converters

  • 默认converters
  • 自定义converters

(1)Django默认支持以下5个转化器:

  • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
  • int,匹配正整数,包含0。
  • slug,匹配字母、数字以及横杠、下划线组成的字符串。
  • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path,匹配任何非空字符串,包含了路径分隔符
################# urls.py #################

from django.urls import path

urlpatterns = [
    path(r"index1/<str:name>/<int:num>",views.index1),  # result为一个str,一个数字
    path(r"index2/<int:num1>/<int:num2>",views.index2),  # 若url中num1/num2为字符串,则无法匹配此条目
]


################# views.py #################

访问http://127.0.0.1:8000/index1/456/123

def index1(request,*args,**kwargs):
    if request.method == "GET":
        print(request.path_info)
        print(request)  # request: < WSGIRequest: GET '/index1/456/123' >
        print(args)  # args: ('abc', '123')
        print(kwargs)  #kwargs: {'name': '456', 'num': 123},一个是str,一个是int
        return render(request,"index.html")

 

(2)自定义转换器

注册自定义转化器
对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:

regex 类属性,字符串类型

to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。

to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。


############# project/converters.py ############
class FourDigitYearConverter:  
    regex = '[0-9]{4}'  
    def to_python(self, value):  
        return int(value)  
    def to_url(self, value):  
        return '%04d' % value  


############# project/urls.py ############
from django.urls import register_converter, path  
from . import converters, views  
register_converter(converters.FourDigitYearConverter, 'yyyy')  
urlpatterns = [  
    path(r"index1/<name>/<yyyy:year>",views.index1),   # 根据yyyy匹配四个数字,result类型为int,kwargs: {'name': 'abc', 'year': 1231}
    ...  
]  

 

 

参考:

  http://www.cnblogs.com/wupeiqi/articles/5237704.html

  https://kinegratii.github.io/2017/09/25/django2-url-path/

posted @ 2018-03-19 11:44  fat39  阅读(244)  评论(0编辑  收藏  举报