Django自定义url(path)转换器

需求1:

实现一个获取电影列表的demo,用户可以根据/movie/电影分类/的方式来获取电影。其中电影分类采用的是分类1+分类2+分类3...的方式拼接的,并且如果只有一个分类,那就不需要加号。示例如下:

# 1. 第一种:获取action分类下的电影
/movie/action/
# 2. 第二种:获取action和costume分类下的电影
/movie/action+costume/
# 3. 第三种:获取action和costume和love下的电影
/movie/action+costume+love/
以此类推...

首先在项目中新建一个movie的app,
在views.py中写入代码:

from django.shortcuts import render,reverse
from django.http import HttpResponse

# Create your views here.

def movie(request):
    return HttpResponse('电影首页')

def movie_list(request,categories):
    text = '你所选的分类是:%s' % categories
    return HttpResponse(text)

def movie_detail(request,movie_id):
    reverse('detail',kwargs={'movie_id':movie_id})
    print(type(movie_id))
    return HttpResponse('电影详情')

新建一个urls.py的文件,编写代码:

from django.urls import re_path,path
from . import views

urlpatterns = [
    path('',views.movie),
    re_path(r'list/(?P<categories>\w+|(\w+\+\w+)+)/',views.movie_list),
    ]
注意:正则表达式中不能随便乱加空格
#\w 0-9,a-z,A-Z,_ 中的任意字符
 	 #\w+       		 一个或多个 “\w”  这样的字符
  	 #  |  				或者
  	 #(\w+\+\w+)+:   	一个或多个 “(\w+\+\w+)”  这样的字符
				      	#			\w+  一个或多个 “\w”  这样的字符
				      	#                   \+   "+"号
				    	#                   \w+  一个或多个 “\w”  这样的字符

主urls.py中编写代码:

from django.urls import path,include

urlpatterns = [
    path('movie/',include('movie.urls')),
]

然后我们输入网址进行测试

http://127.0.0.1:8000/movie/list/action
http://127.0.0.1:8000/movie/list/action+costume+love

现在我们就实现好了需求1.

需求2:

  1. 在“文章分类”参数传到视图函数之前要把这些分类分开来存储到列表中。
    比如参数是python+django,那么传到视图函数的时候就要变成['python','django']

  2. 而在使用reverse反转的时候,限制传递“文章分类”的参数应该是一个列表如['python','django'],并且要将这个列表变成python+django的形式。

在movie中的urls.py中导入:

from django.urls import converters

然后按住ctrl键再单击converters,就能进入到Django中内置的converters.py文件中,我们可以模仿Django中内置的转换器来自定义我们自己的转换器。(Django内置的转换器
就以int这个转换器的为例,int转换器的结构为

class IntConverter:
    regex = '[0-9]+'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return str(value)

为了规范代码结构,我们在movie这个app中创建一个converters.py文件,在里面编写代码:

class CatagoryConverter(object):
	#变量名必须为'regex',否则会找不到定义的字符窜规则
    regex = r'\w+|(\w+\+\w+)+'

    def to_python(self,value):
        #python+Django+flask
        #        到
        #['python','Django','flask']
        result = value.split("+")
        return result

    def to_url(self,value):
        # ['python','Django','flask']
        #        到
        # python+Django+flask
        #if判断是为了增强代码的健壮性,如果传递过来的参数不是一个列表,就抛出异常
        if isinstance(value,list):
            result = "+".join(value)
            return result
        else:
            raise RuntimeError('转换url的时候,分类参数必须为列表!')

#在定义好了转换器之后还需要注册,否则将不能生效。
register_converter(CatagoryConverter,'cate')  #注册自定义的转换器

这样我们就完全定义好了一个转换器,我们给它取的名字为’cate’。
但是,我们将这个文件放在converters.py这个文件中,而我们没有在任何一个地方执行了这个文件。
所以我们需要执行这个文件才能使用我们自定义的转换器。
在movie目录下有一个’__init__.py’的文件,当movie这个模块被导入时,会首先执行’__init__.py‘这个文件中的内容,所以我们在’__init__.py‘导入converters.py文件,’__init__.py’中编写代码:(. 表示当前目录)

from . import converter

这样我们就完全自定义好了一个‘cate’这样的转换器。
然后,跳转至movie中的urls.py中修改代码为:

from django.urls import re_path,path
from . import views
from django.urls import converters

urlpatterns = [
    path('',views.movie),
    #re_path(r'list/(?P<categories>\w+|(\w+\+\w+)+)/',views.movie_list),
	path('list/<cate:categories>/',views.movie_list,name = 'list'),
]

views.py文件中修改代码:

from django.shortcuts import render,reverse
from django.http import HttpResponse

# Create your views here.

def movie(request):
    return HttpResponse('电影首页')

def movie_list(request,categories):
	#这两句print是为了查看转换的效果
    print('转换前:%s' % categories)
    print(reverse('list',kwargs={'categories':categories}))
    text = '你所选的分类是:%s' % categories
    return HttpResponse(text)

然后我们保存后运行代码,在浏览器中输入:

http://127.0.0.1:8000/movie/list/action+love/

然后我们可以去控制台中查看打印的信息,
在这里插入图片描述
如果在命名行中运行的项目那么就在命令窗口中查看信息。
在这里插入图片描述

总结

之前已经学到过一些django内置的url转换器,包括有int、uuid等。有时候这些内置的url转换器并不能满足我们的需求,因此django给我们提供了一个接口可以让我们自己定义自己的url转换器。

自定义url转换器按照以下五个步骤来走:
  1. 定义一个类,直接继承自object就可以了(不继承也可以,在python3中已经变的都可以了)。
  2. 在类中定义一个属性regex,这个属性是用来限制url转换器规则的正则表达式。(必须为‘regex’这个命名,否则Django会找不到转换器的规则)
  3. 实现to_python(self,value)方法,这个方法是将url中的值转换一下,然后传给视图函数的。
  4. 实现to_url(self,value)方法,这个方法是在做url反转的时候,将传进来的参数转换后拼接成一个正确的url。
  5. 将定义好的转换器,使用django.urls.converters.register_converter方法注册到django中。

猜你喜欢

转载自blog.csdn.net/xujin0/article/details/83317609