zoukankan      html  css  js  c++  java
  • 02-URLConf调度器

    1、工作原理

    django通过urlconf来映射视图函数,只区分路径,不区分http方法

    • Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值。
    • Django加载该URLconf模块并查找变量 urlpatterns,它是一个列表django.urls.path() 和 / 或django.urls.re_path()实例。根据列表的实例查找相关的路劲。
    • Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,后面相同的模式不会再进行匹配。
    • 如果某个URL模式匹配成功,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。

    2、简单示例:

    from django.urls import path
    
    from . import views
    
    urlpatterns = [
        path('blog/2003/', views.special_2003),
        path('blog/<int:year>/', views.year_archive),
        path('blog/<int:year>/<int:month>/', views.month_archive),
        path('blog/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]

    在上述路由中,有几点需要注意:

    (1)从URL中捕获,使用尖括号。

    (2)捕获的值可以包含转换器,如/<int:year>/,前面的int表示只能是整数参数,year是参数的名称,用于视图函数的参数传递

    (3)path的路径前不需要再添加“/”,

    (4)示例说明

    blog/2003/匹配的是path('blog/2003/', views.special_2003),blog/2005/匹配的是path('blog/<int:year>/', views.year_archive),

    3、格式转换器

    在上面的示例中,我们已经看到了int这个格式转换器的用法,格式转换器还有:

    str:匹配任何非空字符串,不包括路径分隔符'/'。表达式中不包含转换器,则默认为str。

    int:匹配零或任何正整数。返回一个int。

    slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如, building-your-1st-django_url。

    uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。

    path:匹配任何非空字符串,包括路径分隔符 '/',可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。

    ------------恢复内容开始------------

    1、工作原理

    django通过urlconf来映射视图函数,只区分路径,不区分http方法

    • Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值。
    • Django加载该URLconf模块并查找变量 urlpatterns,它是一个列表django.urls.path() 和 / 或django.urls.re_path()实例。根据列表的实例查找相关的路劲。
    • Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,后面相同的模式不会再进行匹配。
    • 如果某个URL模式匹配成功,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。

    2、简单示例:

    from django.urls import path
    
    from . import views
    
    urlpatterns = [
        path('blog/2003/', views.special_2003),
        path('blog/<int:year>/', views.year_archive),
        path('blog/<int:year>/<int:month>/', views.month_archive),
        path('blog/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]

    在上述路由中,有几点需要注意:

    (1)从URL中捕获,使用尖括号。

    (2)捕获的值可以包含转换器,如/<int:year>/,前面的int表示只能是整数参数,year是参数的名称,用于视图函数的参数传递

    (3)path的路径前不需要再添加“/”,

    (4)示例说明

    blog/2003/匹配的是path('blog/2003/', views.special_2003),blog/2005/匹配的是path('blog/<int:year>/', views.year_archive),

    3、格式转换器

    在上面的示例中,我们已经看到了int这个格式转换器的用法,格式转换器还有:

    str:匹配任何非空字符串,不包括路径分隔符'/'。表达式中不包含转换器,则默认为str。

    int:匹配零或任何正整数。返回一个int。

    slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如, building-your-1st-django_url。

    uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。

    path:匹配任何非空字符串,包括路径分隔符 '/',可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。

    4、自定义格式转换器

    转换器包含以下类:

    一个regex类属性,作为一个re匹配字符串。

    to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型。

    o_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串。

    转换器的定义方式如下:

    (1)新建一个converters.py文件,在文件中定义一个类,使用to_python()和to_url()方法处理

    class YearConverter(object):
        regex = '[0-9]{4}'
    
        def to_python(self, value):
            return int(value)
    
        def to_url(self, value):
            return '%04d' % value     

    (2)使用register_converter()方法在URLconf中注册自定义转换器类 :

    在需要注册的url.py文件中注册,先从django.urls中导入register_converter,同时导入自定义的类注册

       from django.urls import register_converter, path
       
       from . import converters, views
       
      # 注册自定义的转换器 register_converter(converters.YearConverter,
    'yyyy') urlpatterns = [ path('blog/2003/', views.special_2003), path('blog/<yyyy:year>/', views.year_archive) ]

    5、正则表达式的使用

    使用正则表达式匹配路径时,使用re_path()。

    在python正则表达式中,命名正则表达式的语法是(?P<year>pattern),year是组的名称,pattern是需要匹配的模式。

    from django.urls import path, re_path
    
    from . import views
    
    
    # url() 是 re_path 的别名,不推荐使用
    urlpatterns = [
        path('blog/2003/', views.special_2003),
        path('blog/<int:year>/', views.year_archive),
        re_path(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive),
        re_path(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',
        views.month_archive),
        re_path(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[w-]+)/$', views.article_detail),
    ]

    在上述正则表达式中:

    ^表示匹配开头,$表示匹配结束。

    [0-9]{4}表示匹配4位0到9的数。

    6、错误处理

    - handler400- 状态码400
    - handler403- 状态码403
    - handler404- 状态码404
    - handler500- 状态码500

    (1)setting中修改设置

       DEBUG = False
       
       ALLOWED_HOSTS = ['*', ]

    (2)在主应用urls中配置

    # blog表示子应用名
    handler404 = "blog.views.page_not_found"

    (3)在视图函数中定义以下函数

       def page_not_found(request, exception):
           return HttpResponse('这是一个自定义的404错误页面')

    我们看一下页面显示结果:当url找不到时,便会展示我们定义的404错误信息。

    7、应用其他url调度器

    在同一个url中,为了避免重复的路由输入,可以采用多个patterns的方法,示例如下:

       from django.urls import include, path
       
        """原生代码:
        urlpatterns = [
           path('blog/reports/', credit_views.report),
           path('blog/reports/<int:id>/', credit_views.report),
           path('blog/charge/', credit_views.charge),
       ]
    """
        # 修改后的代码
       blog_patterns = [
           path('reports/', credit_views.report),
           path('reports/<int:id>/', credit_views.report),
           path('charge/', credit_views.charge),
       ]
       
       urlpatterns = [
           path('blog/', include(blog_patterns)),
       ]

    采用include()的方法

       from django.urls import path
       from . import views
       
       urlpatterns = [
           path('<page_slug>-<page_id>/history/', views.history),
           path('<page_slug>-<page_id>/edit/', views.edit),
           path('<page_slug>-<page_id>/discuss/', views.discuss),
           path('<page_slug>-<page_id>/permissions/', views.permissions),
       ]
       
       # 修改为:
       from django.urls import include, path
       from . import views
       
       urlpatterns = [
           path('<page_slug>-<page_id>/', include([
               path('history/', views.history),
               path('edit/', views.edit),
               path('discuss/', views.discuss),
               path('permissions/', views.permissions),
           ])),
       ]

    7、URL反向解析

    (1)url调度器除了从用户发起请求,到匹配对应的view,还能在python程序中调用进行匹配,通过 path或re_path 中 的name属性进行解析。

    在模板中,使用url模板标签,在url中,使用了name属性

    from django.urls import path
    from . import views
    
    
    urlpatterns = [
        #...
        path('blog/<int:id>/', views.id_archive, name='id-archive'),
        #...
    ]

    在HTML模板中,我们可以使用url标签进行解析,方法示例如下:

    <a href="{% url 'id-archive' 20 %}">20 Archive</a>
    <ul>
    {% for idvar in id_list %}
    <li><a href="{% url 'id-archive' idvar %}">{{ idvar }} Archive</a></li>
    {% endfor %}
    </ul>
    href="{% url 'id-archive' 20 %}中"id-archive"就是name的属性。
    (2)在Python代码中(主要是views视图中),使用 reverse() 函数。
    from django.urls import reverse
    from django.http import HttpResponseRedirect
    
    def redirect_to_id(request):
        # ...
        num = 20
        # ...
        return HttpResponseRedirect(reverse('news-year-archive', args=(num,)))

    使用reverse进行重定向,完成url的一个跳转链接。

    (3)在模型实例中,使用 get_absolute_url() 方法.

    在模型中的实现方法如下:

    def get_absolute_url(self):
            from django.urls import reverse
            return reverse('new-id-archive', args=[str(self.id)])

    在模板中的实现方法如下:

    <a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

    在上述实现方法中,"new-id-archive"是name属性的值,args是传入的参数值

    8、命名空间

    主要用于配合url反向解析使用,多个不同的urls文件中可能配置同名的name,那么为了进行区分,给不同的urls进行不同的命名,同一个项目下命名空间一定不能重复。

    在url调度器的模块中,使用app_name = "名字"来命名。

    from django.urls import path
    
    from . import views
    # 定义,一般命名空间和子应用名相同,便于记忆
    app_name = 'blog'
    urlpatterns = [
        path('', views.IndexView.as_view(), name='index'),
        path('<int:pk>/', views.DetailView.as_view(), name='detail'),
        ...
    ]

    当使用了命名空间之后,调用时必须有命名空间的前缀,其方法如下所示:

    def test_app_name(request):
        return HttpResponseRedirect(reverse('blog:index'))
    'blog:index',blog表示命名空间的名字,index表示name属性的值

    命名空间的嵌套使用,嵌套与patterns中,如下所示:
    from django.urls import path
    
    from . import views
    # 定义命名空间,一般命名空间名和子应用名相同,便于记忆
    app_name = 'blog'
    
    blog_patterns = (
        [
            path('app_name/', views.app_name, name='app_name'),
        ],
        # 此处就是嵌套的命名空间
        'reading'
    )
    
    urlpatterns = [
        path('', views.IndexView.as_view(), name='index'),
        path('<int:pk>/', views.DetailView.as_view(), name='detail'),
        path('reading/', include(blog_patterns)),
        ...
    ]
    
    

    在模板中使用嵌套空间的方法

    <a href="{% url 'blog:reading:app_name' %}">点击链接</a>

    <a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

  • 相关阅读:
    什么是回归测试?
    单元测试、集成测试、系统测试的侧重点是什么?
    一个测试工程师应具备那些素质?
    你所了解的的软件测试类型都有哪些,简单介绍一下。
    Python
    爬虫-urllib3模块的使用
    爬图片(附,源码)
    MySQL存储引擎:MyISAM和InnoDB的区别
    员工管理系统
    MySQL锁(二)表锁:为什么给小表加字段会导致整个库挂掉?
  • 原文地址:https://www.cnblogs.com/clearlie/p/13251815.html
Copyright © 2011-2022 走看看