• django之路由分发


    路由分发决定哪一个路由由哪一个视图函数来处理。

    注意:django2.0里的re_path和django1.0里的url除了名字不一样,其他都一样。

    简单配置

    from django.urls import path,re_path
    
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('timer/',views.timer),
    
    
        # 路由配置:  决定哪一个路由由哪一个视图函数来处理
        # repath和django1.0里的url用法一样
        # 不写^,articles前面可以写任何东西(edward/123/articles);同理,不写$,2003后面也可以写任何东西。
        re_path(r'^articles/2003/$',views.special_case_2003),
    
        # 正则匹配年份
        # 如果是2003,会匹配第一个
        # 如果去掉$就不走第三个了,因为匹配到年份那就不往后匹配了,而是直接执行arvhive_year了。
        re_path(r'^articles/([0-9]{4})/$',views.archive_year), # year_archive(request,1999)。django2.1.5不用传第二个参数了
    
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
    
        # re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
    ]

    注意:

    • 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。

    • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles

    • 每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义

    有名分组

    # urls
        # 有名分组,?P<year>相当于是起了个名字,然后把名字当做参数传给视图函数,后面才是正则部分。
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',views.month_archive),
       '''
       month_archive(request,year=2009,momth=12)  
       这样在views视图,不管传入的参数的顺序是什么,year就是year,month就是month,但是名字必须是year和month
       '''
    
    #views
    def month_archive(request, month,year):  # 顺序颠倒也没有问题,不管顺序是什么都会正常显示year和month
        return HttpResponse('year:%s,month:%s' % (year,month))

    路由分发

    在app01下面重新创建一个urls的文件,把关于app01的url放到里面,然后再在公共项目的urls里导入app01的urls

    # app01 urls.py
    from django.urls import path, re_path
    
    from app01 import views
    
    urlpatterns = [。
        re_path(r'^articles/2003/$', views.special_case_2003),
        re_path(r'^articles/([0-9]{4})/$', views.archive_year),  # year_archive(request,1999)。
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    ]
    
    # demo urls.py
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('timer/', views.timer),
    
        # 分发:
        re_path(r'^app01', include('app01.urls')),   
        # re_path(r'^', include('app01.urls')   #  路径里面不用写app01了
    ]

    反向解析

     反向解析就是给url起一个别名,我们用别名去找这个url就行,这样不管url如何改变,我们都可以用别名找到它。

    1. 在模板中进行反向解析

    urls.py

    from django.urls import path, re_path, include
    
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('timer/', views.timer),
        path('login.html/',views.login,name='Log'),
    
        # 分发:
        re_path(r'^', include('app01.urls')),
    ]

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
    </head>
    <body>
    
    <!-- 在render的时候,去urls里找一个name叫Log的url,这样action里永远都是最新的url -->
    <form action="{% url 'Log' %}" method="post">
        用户名 <input type="text" name="user">
        密码 <input type="password" name="pwd">
        <input type="submit">
    </form>
    
    </body>
    </html>

    2. 在视图函数里进行反向解析

    # app01 urls
    
    re_path(r'^articles/2003/$', views.special_case_2003,name ='s_c_2003'),
    re_path(r'^articles/([0-9]{4})/$', views.archive_year,name='y_a'),
    
    from django.urls import reverse
    def special_case_2003(request):
        url = reverse('s_c_2003')  #  不需要参数,因为不含正则是一个完整的url,找到后直接匹配
        url2 = reverse('y_a',args=(4009,))   #  ^articles/([0-9]{4})/ 需要给一个四位数字的参数,匹配正则,参数可以是任意四位数字,具体数字按需求写。
        print(url)  # /articles/2003/
        print(url2)  # /articles/4009/
        return HttpResponse("<h3>special_case_2003</h3>")  # HttpResponse里面写的是响应体的内容

    命名空间

    主项目 urls.py

    from django.urls import path, re_path, include
    
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('timer/', views.timer),
        path('login.html/', views.login, name='Log'),
    
        # 分发:
        # 命名空间不可以重名
        re_path(r'^app01', include(('app01.urls', 'app01'))),
        re_path(r'^app02', include(('app02.urls', 'app02'))),
    ]

    app01

     # urls
    re_path('index/',views.index,name='index')
    
    # views
    def index(request):
    
    
        # return HttpResponse(reverse('index'))  # 找到的也是app02的index,用名称空间解决这个问题。
    
        # 用命名空间解决
        return HttpResponse(reverse('app01:index')) # # 冒号之前是namespace,冒号之后是名字

    app02

    # urls
    re_path('index/',views.index,name='index')
    
    # views
    def index(request):
    
        # return HttpResponse(reverse('index'))  # 找到的app02的index,用命名空间解决名字冲突的问题
    
        return HttpResponse(reverse('app02:index'))

    path方法(django2.0)

    re_path有两个问题:

     

    1.不能进行字符转换。

    def month_archive(request, month, year):
        print(type(month))  # str
        print(type(year))  # str
        return HttpResponse('year:%s,month:%s' % (year, month))

    2.同样的正则表达式,需要写多遍,不易于维护。

    urlpatterns = [  
        re_path('articles/(?P<year>[0-9]{4})/', year_archive),  
        re_path('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),  
        re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),  
        re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),  
    ]

    而path可以解决这两个问题

    # urls
    from django.urls import path
    path('articles/<int:year>',views.path_year)
    
    #views
    def path_year(request,year):
        print(type(year))   # int
        return HttpResponse('path year')

    基本规则:

    • 使用尖括号(<>)从url中捕获值。

    • 捕获值中可以包含一个转化器类型(converter type),比如使用 <int:name> 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。

    • 无需添加前导斜杠。

    path转换器

    Django默认支持以下5个转化器:

    • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式

    • int,匹配正整数,包含0。

    • slug,匹配字母、数字以及横杠、下划线组成的字符串。

    • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。

    • path,匹配任何非空字符串,包含了路径分隔符

    自定义path转换器

    在实际开发中,django自带的转换器是不能满足我们的需求的,这就需要自定义转换器了

    操作步骤:

    1.在app里创建一个类,写自定义转换的规则

    url_convert.py

    class MonConvert:
        regex = "[0-9]{2}"   # 只能叫regex
    
        def to_python(self, value):
            return int(value)  #  不转化就是字符串,可以根据需求做任何操作。
    
        def to_url(self, value):  # 用于反向解析
            return "%04d" % value

    2.在urls里注册自定义转换器

    from django.urls import path, re_path, include,register_converter
    from app01.url_convert import MonConvert
    
    # 注册自定义转换器
    register_converter(MonConvert,'mm')

    3.在路由分发里使用自定义转换器

    urlpatterns = [
        path('articles/<mm:month>',views.path_month),
    ]

    Registering custom path converters

    For more complex matching requirements, you can define your own path converters.

    A converter is a class that includes the following:

    • regex class attribute, as a string.
    • to_python(self, value) method, which handles converting the matched string into the type that should be passed to the view function. It should raise ValueError if it can’t convert the given value.
    • to_url(self, value) method, which handles converting the Python type into a string to be used in the URL.

  • 相关阅读:
    XML
    基于SQL的全文检索引擎Sphinx
    php中的Session与Cookie
    公共网关接口CGI(Common GatewayInterface)
    Memcached、memcached、memcache
    MemCache
    在windows上使用symfony创建简易的CMS系统(三)
    在windows上使用symfony创建简易的CMS系统(二)
    在windows上使用symfony创建简易的CMS系统(一)
    Window7上搭建symfony开发环境(PEAR)
  • 原文地址:https://www.cnblogs.com/lshedward/p/10351098.html
Copyright © 2020-2023  润新知