zoukankan      html  css  js  c++  java
  • 仿制Django的admin组件完成的Xadmin组件设计——url分发

    在前面分析admin组件的过程中我们了解了admin组件的实现流程,今天我们来完成一个url的设计,再看看整个URL的设计思路

    URL设计思路

    admin组件下的URL设计 

    admin组件完成了每个app下的model里的ORM都设计了增删改查的URL,比方我们在app01下的model里有个book类,可以看看他的这四个URL是怎么设计的。

    127.0.0.1:8000/admin/app01/book/
    
    127.0.0.1:8000/admin/app01/book/add
    
    127.0.0.1:8000/admin/app01/book/1/change/
    
    127.0.0.1:8000/admin/app01/book/1/delete/

    每个模型下都有这四条URL,但是如果有7个数据Model就会有28条URL,显然Django不是直接写死这28条URL的,那是怎么写出来的呢?

    首先我们要了解url指的是具体哪一部分:

    整个URL应该是这样的

    http://127.0.0.1:admin/app01/book/1/

    前面的http是协议名,后面紧跟的是地址和端口号下面的那一段用/分割的才是url(有些情况下还有参数,是用?来开头的,参数部分不算URL)也就是说我么需要设计的URL就是整条用/来分隔的路径参数,而我们在路由里匹配的url也是这个路径。

    我们注意看一下第一级的URL里面带了下面的一句代码

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

    进去看一看django的源代码里的urls方法

    def urls(self) -> Tuple[List[URLResolver], str, str]: ...

     可以发现,这个url返回的是一个元组,主要的参数是第一个列表,后面两个字符串参数暂时没什么用,先放个None就行了。

    也就是这样的效果

    def test01(response):
        return HttpResponse('test01')
    
    def test02(request):
        return HttpResponse('test02')
    urlpatterns
    = [ url('^abc/',([ url(r'test01/',test01), url(r'^test02/',test02) ],None,None)), ]

    上面就是一个一级的路由的分发过程,首先是前面的abc/,后面就按照test01和test02的url分发,整个就是个1*2的URL分发过程。

    同理,在一级分发的过程中我们还可以通过嵌套来完成二级的分发:

     1 def test01(response):
     2     return HttpResponse('test01')
     3 
     4 def test02(request):
     5     return HttpResponse('test02')
     6 
     7 def test04(request):
     8     return HttpResponse('test04')
     9 
    10 def test05(response):
    11     return HttpResponse('test05')
    12 
    13 
    14 
    15 urlpatterns = [
    16     
    17     url('^abc/',([
    18         url(r'test01/',test01),
    19         url(r'^test02/',test02)
    20     ],None,None)),
    21 ]    
    22 urlpatterns = [
    23     
    24     url('^abc/',([
    25         url(r'test01/',test01),
    26         url(r'^test02/',test02),
    27         url(r'^test03/',([
    28             url(r'test04/',test04),
    29             url(r'^test05/',test05),
    30         ],None,None))
    31     ],None,None)),
    32 ]

    上面的这段代码就是个二级分发的过程,分别对应了下面几个url(前面的地址和端口号省略了。)

    abc/test01
    abc/test02
    abc/test03/test04
    abc/test03/test05

    注意test03是没有视图对应的,直接分发下去了。

    为Xadmin设计新的URL

    知道了admin的URL设计思路,我们就可以为我们的Xadmin设计一套URL

    首先,我们可以把整个URL的生成部分放到一个函数中,通过函数返回的元祖来完成URL的分发

    def get_urls():
        temp = []
        temp.append(url('app01/book/',test01))
        temp.append(url('app01/publish/',test02))
        temp.append(url('app01/author/',test04))
        return temp,None,None
    
    urlpatterns = [
        url(r'^Xadmin',get_urls())
    ]

    这样就完成了一个1*3的分发。但是有个最大的问题,我们在这里把所有的类都写死了(book,publish,author),而我们的需求是能够操作所有注册的表,所以这里就不能写死。

    app名称和models名称的获取

    因为我们在用上面的方式添加url的时候,必须要拿到字符串类型的app的名称和models的名称,前提是我们已经在各个app下的admin.py下做好了注册,那么看一看下面的代码

    from Xadmin.service.Xadmin import site
    
    def get_urls():
        print(site._registry)
        temp = []
        temp.append(url('app01/book/',test01))
        temp.append(url('app01/publish/',test02))
        temp.append(url('app01/author/',test04))
        return temp,None,None
    
    urlpatterns = [
        url(r'^Xadmin',get_urls())
    ]

    这里要注意的是,由于我们新做的Xadmin组件,所以这里要导入的是我们新创建的site,不是django源代码里的admin.site。

    有个知识点要注意一下:

    get_urls()方法是在django启动的时候就执行了,不是在用户访问Xadmin这个url的时候才执行

    所以下面的这一段总结只讲get_urls这个函数,后面的url的列表就先不关注了。看一看django项目运行以后打印出来的数据

    {<class 'app01.models.Books'>: <Xadmin.service.Xadmin.ModelAdmin object at 0x7ffb1792d1d0>, 
    <class 'app01.models.Publisher'>: <Xadmin.service.Xadmin.ModelAdmin object at 0x7ffb1792d208>,
    <class 'app02.models.Order'>: <Xadmin.service.Xadmin.ModelAdmin object at 0x7ffb1792d470>}

    site._registry对应的数据是一个字典,字典的key就是ORM的类,而value就是一个配置类。所以我们可以用for循环的方式拿到各个类

    def get_urls():
        for model,admin_class_obj in site._registry.items():
            print(model)
            print(admin_class_obj)
    
    ##########输出##########
    <class 'app01.models.Books'>
    <Xadmin.service.Xadmin.ModelAdmin object at 0x7f0dd58ac1d0>
    <class 'app01.models.Publisher'>
    <Xadmin.service.Xadmin.ModelAdmin object at 0x7f0dd58ac208>
    <class 'app02.models.Order'>
    <Xadmin.service.Xadmin.ModelAdmin object at 0x7f0dd58ac470>

    但是一定要注意到这个model是一个类,不是一个字符串,还好Django给我们预留了下面的方法

    def get_urls():
        for model,admin_class_obj in site._registry.items():
            print(model._meta.model_name)          #获取model名称
            print(model._meta.app_label)             #获取app名称
    
    ##########输出##########
    books
    app01
    publisher
    app01
    order
    app02

    用上面的方法获取到注册的模型类,然后用字符串拼接的方式就可以直接做好URL的一级分发设计工作了。

    def get_urls():
        temp = []
        for model,admin_class_obj in site._registry.items():
            app_name = model._meta.app_label
            model_name = model._meta.model_name
            
            temp.append(url(r"^{0}/{1}/".format(app_name,model_name),test01))
    
        
        return temp,None,None

    二级分发

    一级分发我们完成了各个table的获取,但是每个table都有对应的增删改查的操作,这些操作是放在二级分发来实现的。需要的就是我们在test01处再放一个元组,当然也可以抽到另一个函数中

     1 def list_view(request):
     2     return HttpResponse('list_view')
     3 
     4 def add_view(request):
     5     return HttpResponse('add_view')
     6 
     7 def change_view(request,id):
     8     return HttpResponse('change_view')
     9 
    10 def delete_view(request,id):
    11     return HttpResponse('delete_view')
    12 def get_urls_2():
    13     temp = []
    14 
    15     temp.append(url(r'^$',list_view))
    16     temp.append(url(r'^add/$',add_view))
    17     temp.append(url(r'^(d+)/change/$',change_view))
    18     temp.append(url(r'^(d+)/delete/$',delete_view))
    19 
    20     return temp,None,None
    21 
    22 
    23 def get_urls():
    24     temp = []
    25     for model,admin_class_obj in site._registry.items():
    26         app_name = model._meta.app_label
    27         model_name = model._meta.model_name
    28         
    29         temp.append(url(r"^{0}/{1}/".format(app_name,model_name),get_urls_2()))
    30 
    31     
    32     return temp,None,None
    33 
    34 urlpatterns = [
    35     url(r'^Xadmin/',get_urls())
    36 ]
    二级分发

    注意点:

    在上面的代码中我们构造了四个视图函数,比方说查询的页面对应的视图,book和publisher的对应的是一个视图,但是url是不同的。

  • 相关阅读:
    iOS越狱后必装软件
    构建iOS交叉编译环境
    pycurl库使用详解
    iFiles浏览iphone文件
    Iphone通过ssh进行访问
    YShow性能测试平台搭建
    from my mac
    LR性能分析
    react服务端渲染(七)redux添加
    react服务端渲染(六)路由
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/13311344.html
Copyright © 2011-2022 走看看