• django之反向解析和命名空间


    背景:当我们页面中存放的请求路径与url文件中的url一致时,如果url改了是不是所有的请求路径都要跟着改?显然不现实,这里我们就要用到反向解析。

    如下图所示,输入url后会跳转到登录页面,输入用户名密码后跳转到欢迎页面。

    #  在公共项目中urls中的url
    
    from django.contrib import admin
    from django.urls import path, re_path, include
    from website import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('data/', views.data),
        path('login./', views.login),
    ]
    
    
    # 在应用中views文件中的视图函数
    from django.shortcuts import render, HttpResponse
    
    def login(request):if request.method == 'GET':
            return render(request, 'login.html')
        elif request.method == 'POST':
            if request.POST.get('user') == 'admin' and request.POST.get('pwd') == '123456':
                return HttpResponse('welcome to world')
            else:
                return HttpResponse('用户名或密码错误')
    # 在公共项目统一目录层建的templates层存放页面文件
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="/static/js.js">
    
        </script>
    </head>
    <body>
    
    <h4>
        登录页面
    </h4>>
    
    <form action="http://127.0.0.1:8000/login/" method="post"> 
        用户名<input type="text" name="user">
        密码<input type="password" name="pwd">
        <input type="submit">
    </form>
    </body>
    </html>

    现在我需要把公共项目中的url改变,再次点击登录后报错了

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('data/', views.data),
        path('login.html/', views.login),
    ]

    报错如图所示:

     因为我们登录时action中的路径找不到http://127.0.0.1:8000/login/路径,现在已经被改成了http://127.0.0.1:8000/login.html/,此时难道我们需要一直改这个路径吗?不存在的!

    接下来到了反向解析的重点

    在公共项目中的urls文件中把url加一个属性name

    from django.contrib import admin
    from django.urls import path, re_path, include
    from website import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('data/', views.data),
        path('login.html/', views.login, name='hello')
    ]

    在html中把action路径改为{{% url 'hello' %}}

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="/static/js.js">
    
        </script>
    </head>
    <body>
    
    <h4>
        登录页面
    </h4>>
    
    <form action="{% url 'hello' %}" method="post">
        用户名<input type="text" name="user">
        密码<input type="password" name="pwd">
        <input type="submit">
    </form>
    </body>
    </html>

    此时再次去访问页面就不会报错啦!

    还有个反向解析办法就是导入reverse模块 

    在公共项目中的urls文件中

    from django.contrib import admin
    from django.urls import path, re_path, include
    from website import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
       path('login/', views.login, name='hello'),
    
    
        # 路由配置 路径--------》视图函数
    
        re_path(r'^articles/2003/', views.special_case_2003, name='one'),
        re_path(r'^articles/([0-9]{4})/$', views.year_archive, name='two'),
        re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[[0-9]{2})/$', views.month),
     

    在应用中的views文件中的视图函数

    from django.shortcuts import render, HttpResponse
    import time
    from django.urls import reverse
    
    # Create your views here.
    
    
    def special_case_2003(request):
    
        return HttpResponse('special_case')
    
    
    def year_archive(request, year):
    
        return HttpResponse(year)
    
    
    def month(request, m, y): 
    
        return HttpResponse(y+'+'+m)
    
    
    def login(request):
    
        print(reverse('one')) #  reserve中放的是路径中的name
        print(reverse('two', args=(4099,))) #  当有元祖时参数必须放在args中
    
        if request.method == 'GET':
            return render(request, 'login.html')
        elif request.method == 'POST':
            if request.POST.get('user') == 'admin' and request.POST.get('pwd') == '123456':
                return HttpResponse('welcome to world')
            else:
                return HttpResponse('用户名或密码错误')

    输入ur:http://127.0.0.1:8000/login/后,查看reserve中的路径为下图所示

     这样就把反向解析的路径获取到了 !!!

    此时有个问题就来了,如果在两个应用中的url相同且对应的name也相同,那会获取到哪个路径呢?经测试得出会获取到第二个,因为第一个被第二个覆盖了。那怎么解决呢?

    如下图所示

    # 公共项目中的url
    
    from django.contrib import admin
    from django.urls import path, re_path, include
    from website import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('data/', views.data),
        path('login/', views.login, name='hello'),
    
        # 路由配置 路径--------》视图函数
    
    
        # 分发
        re_path(r'website/', include(('website.urls', 'website'))),
        re_path(r'website1/', include(('website1.urls', 'website1')))
    # 在第一个项目中的url文件
    
    from django.urls import path, re_path
    from website import views
    
    
    urlpatterns = [
    
        # 路由配置 路径--------》视图函数
    
        re_path('index', views.index, name='index')
    
    ]
    
    # 在第一个项目中的views文件
    
    from django.shortcuts import render, HttpResponse
    from django.urls import reverse
    
    def index(request):
    
        return HttpResponse(reverse('website:index')) 这里返回第一个项目的index
    # 在第二个项目中的url文件
    
    from django.urls import path, re_path
    from website1 import views
    
    
    urlpatterns = [
    
        # 路由配置 路径--------》视图函数
    
        re_path('index', views.index, name='index')
    
    ]
    
    # 在第二个项目中的views文件
    
    from django.shortcuts import render, HttpResponse
    from django.urls import reverse
    
    
    def index(request):
    
        return HttpResponse(reverse('website1:index')) # 这里返回第二个项目的index

    在django2.0版本中又出现了path的用法,可以简便的使用有名分组

    # 公共项目中的urls
    
    from django.contrib import admin
    from django.urls import path, re_path, include
    
    from pro import views
    
    urlpatterns = [
        
        # 路由分发
        re_path(r'pro/', include('pro.urls')),
    ]    
    # pro中的urls文件
    
    from pro import views
    
    urlpatterns = [
    
        # path('test/<int:year>', views.timer) # 参数为int型
        # path('test/<slug:year>', views.timer)  # 参数为字母,数字以及横杠,下划线组成的字符串
        # path('test/<str:year>', views.timer)  # 匹配除了/之外的非空字符串
        # path('test/<uuid:year>', views.timer)  # 匹配格式化的uuid
        # path('test/<path:year>', views.timer)  # 匹配任意非空字符串
    ]
    # pro中的views文件
    
    def timer(request, year):
    
        print(year)
        print(type(year))
    
       return HttpResponse('欢迎大脸猫')

    此时pro中的url中的写法就是简单的有名分组,<>中间是规定的参数类型及参数

    以上介绍了5种转换器方法,显而易见在项目中肯定是不够用的,我们也可以自定义转换器

    首先在需要的App项目中,建一个自定义转换器的类

    # 此文件为pro.urlconvert  自己pro中新建
    
    class YearConvert:
    
        regex = "[0-9]{4}"  # 这个regex参数必须这样写
    
        def to_python(self, value):  # 处理返回的参数
    
            return int(value)
    
        def to_url(self, value):
    
            return '%04d' % value

    接下来去项目中注册

    from django.contrib import admin
    from django.urls import path, re_path, include, register_converter  # 这个需要导入
    from pro.urlconvert import YearConvert
    from pro import views
    
    register_converter(YearConvert, 'yy')  # 注册刚才新建的转换器类
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('pro/<yy:year>', views.year_func) 此时的yy就是转换器的名称
    ]

    最后一步写个对应的year_func,查看效果

    # 此时在pro.views
    
    from django.http import HttpResponse
    
    # Create your views here.
    
    
    def year_func(request, year):
        print(year)
        print(type(year))
    
        return HttpResponse('year....')

    浏览器请求效果:

     此时,我们自定义的转换器就生效啦!!!!

    请尊重作者劳动成果,有需要请转载,标明出处!!! 

  • 相关阅读:
    Unity3D脚本使用:物体调用物体
    Unity3D脚本使用:游戏对象访问
    Unity3D 浏览工具
    spring的工厂方法
    spring运用的设计模式
    Jquery ajax 与 lazyload的混合使用(实现图片异步加载)
    关于线程安全的一点总结
    lazyload的使用心得
    ajax原理及应用
    $.ajax和$.load的区别
  • 原文地址:https://www.cnblogs.com/huizaia/p/11991316.html
Copyright © 2020-2023  润新知