• Django框架 之 URLconf


    浏览目录

    一、URL

    1、摘要

    我们要在Django项目中为应用程序设计URL,我们可以创建一个名为URLconf(通常为urls.py)的Python模块。
    这个模块是纯Python代码,是一个简单的正则表达式到Python函数(视图)之间的映射。

    这种映射关系可以很简短也可以很复杂。它还可以引用其他的映射关系。

    2、Django如何处理一个请求

    如果用户请求一个由Django提供服务的站点,它将按照以下逻辑决定执行哪些代码:

    1、通常不考虑中间件的情况下,Django将会确定要使用的根URLconf模块。

    2、Django加载该Python模块并查找变量 urlpatterns,这个变量应该是一个由django.conf.urls.url() 实例组成的列表。

    3、Django按照顺序遍历每一个URL模式,并停在与本次请求的URL匹配的第一个URL模式。

    4、一旦一个正则表达式匹配上用户请求的URL,Django就会导入并调用给定对的视图,该视图是一个简单的Python函数(或基于类的视图)。

    该视图将被传入以下参数:

    ①一个请求示例--request

                   ②正则表达式中使用分组捕获的值将会以位置参数传递给视图。

                   ③正则表达式中的命名分组捕获的值将会以关键方式传递给视图。

    5、如果没有正则表达式匹配或者在此过程中发生了异常,Django都会调用适当的错误处理视图。

    注意

    1、分组和命名分组不能同时使用。

    请求URL:

    http://127.0.0.1:8000/kwargs_test/123/abc/
    
    url(r'^kwargs_test/(d+)/(?P<name>w+)/', views.kwargs_test),  

    视图:

    def kwargs_test(request, *args, **kwargs):
        print(args, kwargs)
        return HttpResponse("OK")  

    输出:

    () {'name': 'abc',}  

    注:位置参数取不到值。  

    2、django.conf.urls.url()的关键字参数会覆盖正则表达式中命名分组捕获的值。

    请求URL:

    http://127.0.0.1:8000/kwargs_test/123/abc/
    
    url(r'^kwargs_test/(d+)/(?P<name>w+)/', views.kwargs_test, {"name1": "yaya"}),  

    视图:

    def kwargs_test(request, *args, **kwargs):
        print(args, kwargs)
        return HttpResponse("OK")  

    输出:

    () {'name': 'abc', 'name1': 'yaya'}  

    注:分组和命名分组不能同时使用,位置参数取不到值,关键字相同,则全输出,否则覆盖正则表达式中命名分组捕获的值。

    小总结 

    我们现在掌握了三种向视图函数传递参数的方法:

    1. 在正则匹配模式中使用分组模式从请求的URL中捕获参数并以位置参数的形式传递给视图。

    2. 在正则匹配模式中使用命名分组模式从请求的URL中捕获参数并以关键字参数的形式传递给视图。

    3. 通过给django.conf.urls.url()传递参数。 

    二、反向解析URL

    在我们的Django项目中,我们经常会遇到要在视图中返回一个重定向到具体URL的响应,或者要将具体的URL地址嵌入到HTML页面中(如:a标签的href属性等)的情况,Django框架充分考虑了这种需求,所以提供了工具来反向解析(推导)出具体的URL。

    1、name模式

    在Django的URLconf中,我们可以通过给匹配模式起别名,然后我们可以通过别名来反向推导出具体的URL。

    1.1、普通情况

    # urls.py
    urlpatterns = [
        # 为匹配模式起别名
        url(r'^student_list/', views.student_list, name="students"),
    ]
    
    # 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
    from django.urls import reverse
    def add_student(request):
        if request.method == "POST":
            # 根据别名反向推导出具体的URL,避免出现硬编码URL的情况。
            url = reverse("students")  # 得到URL: /student_list/
            return redirect(url)
    
    # HTML中
    <a href="{% url 'students' %}">点击查看所有学生信息</a>
    

    1.2、URL中需要位置参数

    # urls.py
    urlpatterns = [
        # 为匹配模式起别名,并且正则表达式中有分组匹配
        url(r'^student/(d+)', views.student_detail, name="student_detail"),
    ]
    
    # 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
    from django.urls import reverse
    def add_student(request):
        if request.method == "POST":
            # 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
            url = reverse("student_detail", args=(1,))  # 得到URL:/student/1/
            return redirect(url)
    
    # HTML中
    <a href="{% url 'student_detail' 1 %}">点击查看学生详细信息</a>
    

    1.3、URL中需要关键字参数

    # urls.py
    urlpatterns = [
        # 为匹配模式起别名,并且正则表达式中有分组匹配
        url(r'^student/(?P<num>d+)', views.student_detail, name="student_detail"),
    ]
    
    # 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
    from django.urls import reverse
    def add_student(request):
        if request.method == "POST":
            # 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
            # 得到URL:/student/10/
            url = reverse("student_detail", kwargs={"num": 10})
            return redirect(url)
    
    # HTML中
    <a href="{% url 'student_detail' num=10 %}">点击查看学生详细信息</a>  

    2、namespace模式

    我们的项目比较庞大,其URL可能成百上千,不可避免的会出现别名重复的情况。这个时候就需要使用namespace了,我们可以为不同的urlpatterns设置一个namespace(命名空间),这样在不同的命名空间下即使别名相同,还是可以通过namespace来区分不同的URL匹配模式。

    # urls.py中
    urlpatterns = [
        # 为app01.urls设置命名空间名:beijing
        url(r'^beijing/', include("app01.urls", namespace="beijing")),
        # 为app02.urls设置命名空间名:shanghai
        url(r'^shanghai/', include("app02.urls", namespace="shanghai")),
    ]
    
    # app01/urls.py
    urlpatterns = [
        # app01/urls.py中有一个别名为index的匹配模式
        url(r'^index/$', views.index, name="index"),
    ]
    
    # app02/urls.py
    urlpatterns = [
        # app02/urls.py中也有一个别名为index的匹配模式
        url(r'^index/$', views.index, name="index"),
    ]
    
    # 视图views.py中
    def index(request):
        # 通过 namespce:name 的方式来反向推导出准确的URL
        url = reverse("shanghai:index")
    
    # HTML中
    <a href="{% url 'shanghai:index' %}">上海分公司首页</a>

    app_name

    也可以通过在app/urls.py中定义app_name来设置app级别的namespace

    # 在上面示例的app01/urls.py文件中:
    
    app_name = "beijing"
    urlpatterns = [
        url(r'^index/$', views.index, name="index"),
    ]
    

      

      

  • 相关阅读:
    新组件或功能怎么依附到已有的架构上
    高内聚、低耦合
    软件质量的定义
    软件架构与组件
    架构设计之拥抱着变化而设计(部分讲义分享)
    组件设计原则之概念篇(四)
    抽象类(接口类)的作用
    类,抽象基类,接口类三者间的区别与联系(C++)
    软件的可变性
    软件设计的复杂度
  • 原文地址:https://www.cnblogs.com/gaoya666/p/8696206.html
Copyright © 2020-2023  润新知