Django-路由控制

URL配置(URLconf)就像Django 所支撑网站的目录。

它的本质是URL与要为该URL调用的视图函数之间的映射表;

你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。

from django.urls import path,re_path

from app01 import views  #导入视图函数 逻辑部分

urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003), #模式一
re_path(r'^articles/([0-9]{4})/$', views.year_archive), #view视图中必须要有函数名字为year_archive #模式二
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), #模式三
re_path(r
'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), #模式四
]

每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的

一些请求的例子:

/articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数views.month_archive(request, '2005', '03')。
/articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
/articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。
/articles/2003 不匹配任何一个模式,因为每个模式要求URL 以一个反斜线结尾。
/articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数views.article_detail(request, '2003', '03', '03')。

一、静态文件配置说明

# Static files (CSS, JavaScript, Images) # 静态文件包括:css,js和图片
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATIC_URL = '/static/'

# 上面的static路径是Django提供给我们的用于代指下面拼出的绝对路径;即使urls.py中没有静态文件夹(static),client浏览器也能通过static来获取static文件夹中的文件;(静态文件夹都放在static中)
# STATICFILES_DIRS 一个字都不能错
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static"),
]
# 上面两个要配合使用

二、有名分组

在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式 

from django.urls import path,re_path

from app01 import views

urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), #year 是名字 [0-9]{4} 是正则 匹配成功走views视图函数中的 special_case_2003 函数
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(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')函数,而不是views.month_archive(request, '2005', '03')。
/articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。

请求会带着有名分组的名字 去请求函数  

三、分发  

如果所有的路径对应关系都在项目文件夹下的urls.py中

后期管理会很费劲

因此 让每个应用管理自己的url

导入 include模块  项目文件夹下的urls.py中

from django.urls import include
from django.urls import path,re_path,include  #导入include 模块
from app01 import views  #导入app01 的视图 views

urlpatterns = [
re_path(r'^admin/', admin.site.urls),
re_path(r'^blog/', include('blog.urls')), #只要匹配上blog,后面的内容就交给app01.urls来匹配
]

四、反向解析

 反向解析一:urls.py(模版中)

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path("login/",views.login,name="log")  # name=log 是这个url的别名(反向解析); path()的第一个参数是接口,用户需要知道

app01/views.py

from django.shortcuts import render,HttpResponse
def login(request):
    # request 是请求对象;所有的请求信息都在request里面
    print(request.method)
    # request.method 表示获取 请求方式(GET/POST)

    if request.method == "GET":
        print(request.GET)
        # request.GET 表示获取所有的 GET请求数据;字典的形式
        # <QueryDict: {}>
        return render(request, "login.html")
        # 反向解析的过程:用户通过 /login/ 这个接口 到达urls.py,然后通过 path("login/",views.login,name="log") 到达 views.py;
        # render(request, "login.html") 方法在渲染 login.html 这个页面的时候,会在 action="{% url 'log' %}" 这一步 找到别名为 "log" 的url,并将 {% url 'log' %} 替换为该url
    else:
        print(request.POST)
        # request.PSOT 表示获取所有的 POST请求数据;字典的形式
        # < QueryDict: {'username': ['123'], 'psw': ['123']} >

        # 获取请求体(POST)
        user = request.POST.get("username")
        psw = request.POST.get("psw")

        if user == "abc123" and psw == "abc123":
            # 每次请求一定要有 返回值
            return HttpResponse("成功")
        else:
            return HttpResponse("用户名密码错误")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#action如果不写IP和Port,默认是发送到当前的IP端口#}
{#<form action="http://127.0.0.1:8000/login/" method="post">#}
{#{% url "log" %} 反向解析的语法#}
{#通过这种反向解析方法,不管 urls.py 中的路径接口如何改变,action中的路径能始终自动与其保持一致#}
<form action="{% url 'log' %}" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="psw">
    <input type="submit">
</form>

</body>
</html>

反向解析二:在python脚本的视图函数中(views.py)

app01/urls.py

from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns
= [ path('admin/', admin.site.urls), # 路由配置:路径 ----> 视图函数 re_path(r'^articles/2003/$', views.special_case_2003,name="s_c_2003"), # ^articles/2003/$ :正则匹配;匹配以articles/2003/开头、以articles/2003/结尾的路径;唯一匹配 re_path(r'^articles/([0-9]{4})/$', views.year_archive,name="y_a"), # 通过 name="y_a" 给这个url起一个别名 ]

app01/views.py

from django.shortcuts import render,HttpResponse
# Create your views here.
from django.urls import reverse
def special_case_2003(request):  # request指请求对象
    # 在视图函数中也可以反向解析获取其他的url
    url1 = reverse("s_c_2003")  # 反向解析
    url2 = reverse("y_a",args=("1999",))
    # 由于别名为 "y_a" 的那个url含有正则匹配的分组,而我们指向解析出来的应该是一个具体的路径,而不是一个匹配规则,所以在reverse("y_a",args=("1999",)) 中需要手动添加一个元组如args=("1999",),元组中的元素得满足 该url的正则匹配规则
    print(url1)
    print(url2)

    return HttpResponse("special_case_2003")
    # HttpResponse 指响应对象;参数是字符串,响应体的内容

五、路由控制之名称空间

命名空间(英语:Namespace)是表示标识符(如:路径的别名name属性)的可见范围。

一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。

这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间

project的urls.py:

from django.contrib import admin
from django.urls import path,re_path,include

urlpatterns = [
    path('admin/', admin.site.urls),

    # 分发:全局分发器;用于把路径分发到不同的应用(application)里面
    re_path(r"^app01/",include(("app01.urls","app01"))),

    re_path(r"^app02/",include(("app02.urls","app02"))) # 元组的第二个参数表示该url的名称空间

]

app01.urls:

from django.contrib import admin
from django.urls import path,re_path

from app01 import views

urlpatterns = [
    re_path(r"^index/$",views.index,name="index") # name为路径的别名
]

app01.views 

from django.shortcuts import render,HttpResponse

# Create your views here.

from django.urls import reverse

def index(request):

    return HttpResponse(reverse("app01:index")) # 反向解析的时候,reverse("app01:index")中 app01:index 表示 app01这个名称空间中的别名 index

app02.urls:

from django.contrib import admin
from django.urls import path,re_path

from app02 import views

urlpatterns = [
    re_path(r"^index/$",views.index,name="index"),
]

app02.views

from django.shortcuts import render,HttpResponse

# Create your views here.

from django.urls import reverse

def index(request):

    return HttpResponse(reverse("app02:index"))

 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),  #<int:year> int 是path内置的转换器 :后面的是自己起的名字
    path('articles/<int:year>/<int:month>/<slug>/', views.article_detail),  
]

1)使用尖括号(<>)从url中捕获值;<>就代表一个分组;

2)捕获值中可以包含一个转化器类型(converter type),比如使用 <int:name> 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符;

3)无需添加前导斜杠。

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

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

path的自定义转化器:

对于一些复杂或者复用的需要,可以定义自己的转化器。

(1) 需要自定义一个path转化器,如下:

app01/urlconvert.py  在app01下创建文件urlconvert.py,这个是一个单独的一个模块

# 自定义path转化器
class FourDigitYearConvert:  #自定义一个类 四个数字的类
    regex = "[0-9]{4}" # 匹配规则  #必须有的一个类属性

    def to_python(self,value): #必须有的方法
        return int(value)
#to_python(self,value) 方法value是由类regex所匹配到的字符串,返回具体的python变量,从供Django传递到对应的视图中。

    def to_url(self,value):  #必须有的方法
        return "%04d" %value
#to_url(self,value) 与 to_python(self,value) 相反,value是具体的一个变量 返回其中字符串,常用于url反向引用

(2)使用register_converter在全局urls.py中注册该path转化器

from django.contrib import admin
from django.urls import path,re_path,include,register_converter #导入注册模块

from app01.urlconvert import FourDigitYearConvert #导入自定义类
register_converter(FourDigitYearConvert,"yyyy")  # 把自定义的path转化器注册一下;第二个参数是为该转化器起的一个别名,后面用的时候就用这个别名

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),

    path("articles/<yyyy:year>",views.path_year), # 调用该自定义的path转化器
]

路由控制到此结束。。。。

posted on 2020-10-09 12:20  I我非柠檬为何心酸I  阅读(111)  评论(0编辑  收藏  举报