django-反向解析
什么是反向解析 在上节课中,我们如果要在后台中,使用某个url地址 是需要自己进行设置的 如: from django.shortcuts import redirect def login(

django-反向解析

发布时间:2023-11-23 (2023-11-23)

什么是反向解析

在上节课中,我们如果要在后台中,使用某个url地址 是需要自己进行设置的 如:

from django.shortcuts import redirect


def login(request):
    ...
    return redirect('/login/')
# 我们需要自己去写登录成功之后进行跳转的地址,这样其实特别不方便
# 如果项目稍微大一点,我们就需要去记很多的跳转地址

为什么不一开始就给这些url起一个别名,类似于一个变量名 下次要使用这个url,就直接使用这个变量名即可

path('login/', views.login, name='login'),
# 在urls中,进行路由分发的时候,多加一个name参数
# 那么我们就可以在后端,或者是前端进行使用这个路径了

我们先来看在后端中,怎么接收到这个login地址的

from django.urls import reverse
from django.shortcuts import redirect


def login(request):
    print(reverse('login'))
    # 根据别名反向解析出url
    login_path = reverse('login')
    return redirect(login_path)

那么在前端中,我也想使用这个路径,就需要这么写了


<form action="{% url 'login' %}" method="post">
    ...
</form>

{% url 'login' %}是一种专门做反向解析的固定写法,叫模板标签,我们下节课再讲 现在会用即可

名称空间

好了,现在问题又出现了,如果我有多个app

可不可能存在两个一样的别名?

这是完全可能的!!

例如qq的登录,微信的登录

我都要用login这个别名,那么怎么区分出这个别名对应那个app呢?

我们在include进行路由分发的时候,为这个app起一个namespace, 可以理解为,为app起一个别名

re_path('^app01/', include(('app01.urls', 'app01'))),  # /app01/index/
re_path('^app02/', include(('app02.urls', 'app02'))),  # /app02/index

# 这里的写法一定不要写错了,是include里面有一个元组,元组里面依此填内容
# 第一个参数是app下面urls的地址,第二个参数就是app的别名(namespace)

后端如何取值?

def login(request):
    ...
    print(reverse('app01:login'))
    # 有include的反向解析,需要加上别名,
    # 格式:namespace:name
    return ...

前端取值,和后端一样


<form action="{% url 'app01:login' %}" method="post">
    ...
</form>

注意:有的时候编辑器会没有提示,不要怕,大胆写,你没有写错

补充:

如果在反向解析的时候,遇到的是含正则表达式的有分组匹配的

需要为你的reverse多传一个参数

# 无名分组用 args
print(reverse('login', args=(12,)))
# 你可以将匹配的内容放到这里
# 有名分组用 kwargs
print(reverse('login', kwargs={'y': 112}))

在前端中,也是这样进行操作

不过不用区分无名分组与有名分组


<form action="{% url 'login' 12 %}" method="post">
    ...
</form>

path方法

之前我们讲到re_path的时候,在里面可以写正则表达式,进行匹配路径,特别的方便

其实在我们的path中,也可以进行这样的操作

path('login/<int:y>/', views.login, name='login'),

这里的<int:y>就是一种通用匹配方式

int 匹配数字 str 匹配除了路径分隔符之外的其他非空字符 slug 匹配字母,数字,下划线,横杠 path 匹配任何字符,包括路径分割符

使用path中的通用匹配,就好比re_path中的有名分组

将匹配的内容传递给y

并且需要注意的是,int这个匹配规则,会将匹配上的数字,转换为int类型

所以我们叫这个写法为 转换器

自定义转换器

使用django自带的path方法中的匹配规则,有点不太够用,我们需要自定义转换器

如何自定义转换器?

  1. 新建一个类
  2. 在类中编写代码,to_python,to_url方法必不可少
  3. 将这个类注册在转换器中
from django.urls import path, register_converter
from app01 import views


# 自定义转换器
class MonConvert:
    # 自定义规则(正则表达式)
    regex = '\d\d'

    def to_python(self, value):
        # 这里的value就是匹配的值
        # 可以在这里对匹配的值进行一个操作
        return int(value)

    # 反向解析
    def to_url(self, value):
        return value


# 注册转换器   类,转换器名称
register_converter(MonConvert, 'yyy')

urlpatterns = [
    path('login/<yyy:y>/', views.login, name='login'),
]

# <转换器名称:关键字参数名称>

编写好之后,最好是将这个类放入到一个公共的地方

例如我放在app01下的converter.py

我需要在app01下的__init__.py中注册这个模块

# init.py
from app01 import converter

如果需要编写多个自定义转换器,只需要写多个类即可

请求对象与响应对象

请求对象

获取请求路径 request.path 请求方式 request.method 请求的参数 request.GET get请求参数 请求的主机 request.get_host()

响应对象

三剑客