Django路由控制

1、精准匹配

#由于是正则匹配,匹配成功后不再往下匹配,输入loginaaa时只能访问到login,
urlpatterns = [
    url(r'^admin/', admin.site.urls), 
    url('login',views.login),
    url('loginaaa',views.login),
]

#精准匹配(^以什么开头,$以什么结尾)   'r'可选项,一般建议加上
    url(r'^login/',views.login),
    url(r'^loginaaa/',views.login),

#严格模式
#APPEND_SLASH = True
    配置文件中默认没有 APPEND_SLASH 这个参数,
    Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'
    可以在在settings.py中设置了 APPEND_SLASH=False

 

 

 二、路由分发

1、无名分组(按位置参数传参)

1、一般模式
#
publish/匹配四位数字 url(r'^login/[0-9]{4}/$', views.login), #匹配任意长度的数字 url(r'^login/\d+/$', views.login), 2、无名分组 #无名分组,与上边的唯一区别就是外边有小括号 #但是,会把括号内的内容当作位置参数传给视图函数 #如果有两个分组,后端需要两个参数接收 url(r'^login/([0-9]{4})/$', views.login), url(r'^login/([0-9]{4})/([0-9]{2})$', views.login), def login(request,year) 一个分组 def login(request,year,month)    两个分组 def publish(request,*args): #可以这样接收多个参数,不推荐这么使用

 

2、有名分组(按关键字参数传参)

#用法和无名分组类似,(有名分组和无名分组,不要混用)
#固定写法  ?P<参数>

url(r'^publish/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.publish),
-def publish(request, mounth,year):

#视图函数需要有关键字参数接收,顺序无所谓,关键得有对应的参数
def publish(request, mounth,year):

 

 

三、路由分发

#首先创建app,在app下创建urls,这些app下的路由为子路由#主路由是django项目下的urls

1、主路由

from django.conf.urls import url,include
忘记怎么导入也不要紧,上边官方注释中有

#注意!!!,不要使用$
#方式一,取别名
from app01 import urls as a1
from app02 import urls as a2
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/',include(a1)),
    url(r'^app02/',include(a2))
]

#方式二(推荐使用)
#直接使用app名.urls,注意这里是字符串,django内部会通过反射的方式找到
#并且,不需要导入from app01 import urls
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/',include('app01.urls')),
    url(r'^app02/',include('app02.urls'))
]

子路由

#正常使用就行,注意导入自己app的views
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',views.login),

from app02 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',views.login),
]

 

  

四、 反向解析

#先命一个名:
    -1 无参数:url(r'^publishadd133/$', views.publishadd,name='ddd'),    #先取别名
    -2 无名分组:url(r'^publishadd/([0-9]{4})/([0-9]{2})/$', views.publishadd,name='ddd'),
    -3 有名分组:url(r'^publishadd/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.publishadd,name='ddd'),
#在模板层:
    -1 无参数:{% url 'ddd' %}     #直接使用别名,需要参数的传参数
    -2 无名分组的:{% url 'ddd' 2018 12 %}
    -3 有名分组:{% url 'ddd' 2018 12 %}  还可以 {% url 'ddd' year=2018 mounth=12 %}
    
#在视图层:
    from django.shortcuts import reverse
    在视图函数里:
    1 无参数:url=reverse('ddd')
       return redirect(url)
1 无名分组:url=reverse('ddd',args=(2018,12,)) 1 有名分组:url=reverse('ddd',args=(2018,12,)) 还可以 url=reverse('ddd',kwargs={'year':2018,'mounth':12})

五、 名称空间

我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
创建一个app02:python manage.py startapp app02
urls.py
from django.urls import path,re_path,include
urlpatterns = [
    path('app01/', include('app01.urls')),
    path('app02/', include('app02.urls'))
]

app01 的urls.py

from django.urls import path,re_path
from app01 import views
urlpatterns = [
    re_path(r'index/',views.index,name='index'),
]

app02 的urls.py

复制代码
from django.urls import path, re_path, include
from app02 import views

urlpatterns = [
    re_path(r'index/', views.index,name='index'),

]
复制代码

app01的视图函数

def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app01')

 

app02的视图函数

def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app02')

这样都找index,app01和app02找到的都是app02的index

如何处理?在路由分发的时候指定名称空间

总urls.py在路由分发时,指定名称空间

 path('app01/', include(('app01.urls','app01'))),
 path('app02/', include(('app02.urls','app02')))
 url(r'app01/',include('app01.urls',namespace='app01')),
 url(r'app02/',include('app02.urls',namespace='app02'))
 url(r'app01/',include(('app01.urls','app01'))),
 url(r'app02/',include(('app02.urls','app02')))

 

在视图函数反向解析的时候,指定是那个名称空间下的

 url=reverse('app02:index')
 print(url)
 url2=reverse('app01:index')
 print(url2)

在模版里:

<a href="{% url 'app02:index'%}">哈哈</a>

七 django2.0版的path

django2.0的re_path和1.0的url一样

思考情况如下:

urlpatterns = [  
    re_path('articles/(?P<year>[0-9]{4})/', year_archive),  
    re_path('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),  
    re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),  
    re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),  
]

考虑下这样的两个问题:

第一个问题,函数 year_archive 中year参数是字符串类型的,因此需要先转化为整数类型的变量值,当然year=int(year) 不会有诸如如TypeError或者ValueError的异常。那么有没有一种方法,在url中,使得这一转化步骤可以由Django自动完成?

第二个问题,三个路由中article_id都是同样的正则表达式,但是你需要写三遍,当之后article_id规则改变后,需要同时修改三处代码,那么有没有一种方法,只需修改一处即可?

在Django2.0中,可以使用 path 解决以上的两个问题。

基本示例

这是一个简单的例子:

复制代码
复制代码
from django.urls import path  
from . import views  
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>/', views.article_detail),  
  # path才支持,re_path不支持
  path('order/<int:year>',views.order), ]
复制代码
复制代码

基本规则:

  • 使用尖括号(<>)从url中捕获值。
  • 捕获值中可以包含一个转化器类型(converter type),比如使用 <int:name> 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
  • 无需添加前导斜杠。

以下是根据 2.0官方文档 而整理的示例分析表:(跟上面url的匹配关系)

path转化器

文档原文是Path converters,暂且翻译为转化器。

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

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

 

 

注册自定义转化器

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

  • regex 类属性,字符串类型
  • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
  • to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。

 

例子:

 

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

 

使用register_converter 将其注册到URL配置中:

 

复制代码
复制代码
from django.urls import register_converter, path  
from . import converters, views  
register_converter(converters.FourDigitYearConverter, 'yyyy')  
urlpatterns = [  
    path('articles/2003/', views.special_case_2003),  
    path('articles/<yyyy:year>/', views.year_archive),  
    ...  
]  
复制代码
复制代码

 

 
#伪静态
#路由
url(r^book/(?p<id>\d+.html)',viws.book),
+.html)

#访问
:=http://127.0.0.1:8000/book/4.html

 

 
 
 
posted @ 2019-04-16 07:29  pdun  阅读(229)  评论(0编辑  收藏  举报