urls参数转换器
-
用于限制参数
-
from django.urls import converters
查看converters -
默认的参数转换器
DEFAULT_CONVERTERS = { 'int': IntConverter(), 'path': PathConverter(), 'slug': SlugConverter(), 'str': StringConverter(), 'uuid': UUIDConverter(), }
-
各个值对应的类
class IntConverter: regex = '[0-9]+' #多个0-9 def to_python(self, value): return int(value) def to_url(self, value): return str(value) class StringConverter: regex = '[^/]+' #除了/都可以 def to_python(self, value): return value def to_url(self, value): return value class UUIDConverter: regex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' #import uuid uuid.uuid4()这个函数返回的字符串类型 def to_python(self, value): return uuid.UUID(value) def to_url(self, value): return str(value) class SlugConverter(StringConverter): regex = '[-a-zA-Z0-9_]+' #返回-或者a到z或者A-Z或者0到0或_ class PathConverter(StringConverter): regex = '.+' #都可以
-
用法
# urls.py # 参数转换器 path('app/converter/<int:param>', v.url_converter) # path('app/converter/<str:param>', v.url_converter) # path('app/converter/<uuid:param>', v.url_converter) # path('app/converter/<path:param>', v.url_converter) # path('app/converter/<slug:param>', v.url_converter) # views.py def url_converter(request, param): return HttpResponse("返回值是: {}".format(param))
to_python和to_url
- 在
path()
中使用了<int:param>
后,参数转换器会将这个param传给to_python,返回的是转换后的param。 - 在使用
reverse(view_name,kwarsg)
的时候,kwargs也会调用相应参数转换器,将kwargs的值传给to_url转换为字符串,添加进view_name对应的URL中的参数
自定义URL转换器
此处引用的知了课堂-Django开发的例子
-
django内置的url转换器不足以满足需求,可以自定义url参数转换器。
-
步骤
- 定义一个类,直接继承自object
- 参考
converters.py
里类的结构。- 定义一个属性regex,这个属性是用来限制url转换器规则的正则表达式
- 实现
to_python(self,value)
,将URL参数的值转换,再传给视图函数 - 实现
to_url(self,value)
,在做URL反转的时候,将传进来的参数转换回原来的参数类型,然后拼接成一个正确的URL
- 将定义好的转换器,使用
django.urls.converters.register_converter
方法注册进Django中
-
例子
-
需求:
- 实现一个获取文章列表的demo,用户可以根据
/articles/文章分类/
的方式来获取文章。其中文字分类的格式是分类1+分类2+分类3
的方式拼接。如果只有一个分类,无需+
- 在
文章分类
参数传到视图函数之前要把这些分类分开存储到list
中。比如参数是book1+book2
,那么传到视图函数的时候就要编程['book1', 'book2']
- 在使用reverse反转的时候,限制传递
文字分类
的参数应该是一个列表,并且要将这个列表变成book1+book2
类型
- 实现一个获取文章列表的demo,用户可以根据
-
实现:
-
使用
re_path()
,用正则要判断URL的参数#urls.py from django.contrib import admin from django.urls import path,re_path #导入re_path from book import views as v #导入视图函数 urlpatterns = [ # ()表示一个整体 # ?P<param_name>后面接对这个pram_name的格式描述 # \w 表示0-9,a-z,A-Z,_ # + 表示0个或多个 # \+ 表示纯粹的+,就是+的转义 re_path(r'article/(?P<book_name>\w+|(\w+\+\w+)+)/', v.book_list, name="book_page") ]
# views.py from django.shortcuts import render, HttpResponse from django.urls import reverse def book_list(request, book_name): target_url = reverse("book_page", kwargs={"book_name": "book1+book2"}) # 默认参数传递是str return HttpResponse("book_name is: {0} ,target_url is: {1}".format(book_name, target_url))
-
运行
-
-
更改
# app中的 converters.py(自己新建) # 然后在app中的 __init__.py中 from * inport converters from django.urls import register_converter class BookType(object): regex = "\w+|(\w+\+\w+)+" #对参数的判别 def to_python(self, value): #path中使用的时候会将参数转化为list # 将"book1+book2"转换为["book1", "book2"] book_list = value.split("+") return book_list def to_url(self, value): if isinstance(value, list): # reverse时会将参数转化为特定str # 将["book1"+"book2"]转换为"book1+book2" book_url = "+".join(value) return book_url else: raise RuntimeError("反转URL的参数必须为list") register_converter(BookType, "book_type") #注册
# urls.py urlpattern = [ path('article/<book_type:book_name>/', v.book_list, name="book_page") ]
# views.py from django.urls import reverse def book_list(request, book_name): target_url = reverse("book_page", kwargs={"book_name": book_name}) # kwargs的book_name此时要求的是list类型,而book_name就是to_python中转换而来的list return HttpResponse("book_name is: {0} ,target_url is: {1}".format(book_name, target_url))运行
-
运行
-
-