zoukankan      html  css  js  c++  java
  • Django----路由控制

    一、概述

    '''
    URL是服务器的入口,用户通过浏览器发送过来的任何请求,都是发送到一个指定的url地址,然后被响应
    在Django项目中编写路由,就是向外界暴露我们接收哪些url请求,除此之外的任何url都不被处理,也没有返回。通俗的理解,url就是web服务对外暴露的api 
    要设计应用程序的url,可以创建一个非正式的称为URLconf的Python模块。此模块是纯Python代码,是URL路径表达式与Python函数之间的映射
    '''

    、简单的路由配置

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views      # 导入后端逻辑
    
    urlpatterns = [
        url(正则表达式,views视图函数,参数,别名),
    ]
    • 正则表达式:一个正则表达式字符串,每个正则表达式前面的r是可选的但是建议加上,它是告诉Python这个字符串是原始的,字符串中的任何字符都不能转义 
    • views视图函数:一个可调用的对象,通常为一个视图函数或一个指定视图函数路径的字符串
    • 参数:可选的要传递给视图的默认参数(字典形式)
    • 别名:一个可选的name参数
    • urlpatterns中的元素是书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继

    path  re_path  path的区别:

    '''
    url格式: url(r'^admin/', admin.site.urls)
        需要到导入url模块: from django.conf.urls import url 
        可用使用正则表达式
        Django1.0中使用
    re_path: re_path(r'^publish/([0-9]{4})/([0-9]{2})$',views.publish),
        Django2.0中使用,完全兼容url
    需要导入re_path模块: from django.urls import re_path
    path:
    需要导入path模块: from django.urls import path 不能使用正则表达式,2.0独有
    '''

    三、django2.0版的path 

    from django.contrib import admin
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('server/<int:proj_id>/',views.proj_detail)
    ]
    •  要捕获一段URL中的值,需要使用尖括号<> ,而不是之前的小括号()
    • 捕获值中可以包含一个转换器类型(converter type),比如使用<int:proj_id>捕获一个整数变量,如果没有转换器,将匹配任意字符
    • 如果使用int转换器类型,而url中实际传入了string字符,将没法匹配到这条路由 直接抛出404  例如 http://127.0.0.1:8000/server/project/
    • 使用path转换器,默认情况下不能使用正则匹配(可以注册自定义转换器),所以要么使用url/re_path 正则匹配,要么使用path 

    django默认支持的以下5个转换器

    • str 匹配除了路径分隔符(/)之外的非空字符串,默认就是str
    • init 匹配整数,包含0 
    • slug 匹配字母、数字以及横杠、下划线组成的字符串
    • uuid 匹配格式化的uuid 如 353b3f42-4b83-11e9-8eff-9cb6d0129e8e
    • path 匹配任何非空字符 包含了路径分隔符,不能用?

    注册自定义转换器

    class FourDigitYearConverter:
        regex = '[0-9]{4}'      # 匹配规则
    
        def to_python(self, value):
            return int(value)     
    
        def to_url(self, value):
            return '%04d' % value
        # 两个def是固定语法

    使用 register_converter将其注册到url配置中

    from django.contrib import admin
    from django.urls import path,register_converter
    from app01 import views,converteres
    
    register_converter(converteres.FourDigitYearConverter.,'yyyy')
    urlpatterns = [ 
        path('admin/', admin.site.urls),
        path('app/<int:proj_id>/',views.proj_detail),
        path('articles/2003/', views.special_case_2003),
        path('articles/<yyyy:year>/', views.year_archive)
    ]

    四、APPEND_SLASH 

    # 是否开启URL访问地址后面不为/ 跳转至带有/ 的路径配置项
    APPEND_SLASH = True 
    
    # django setting.py配置文件中没有APPEND_SLASH这个参数,但django默认这个参数为APPEND_SLASH = True,其作用就是自动在url结尾后面加/
    # 如果 APPEND_SLASH = False url中如果没有加/ 会报404

    五、无名分组

    • 按位置传参
    • 分组后,会把分组出来的数据,当做位置从参数传给视图函数,视图函数必须要定义形参接收,否则报错
    • url示例:re_path(r'^publish/([0-9]{4})/([0-9]{2})$',views.publish),
    • 视图函数示例:def publish(request,*args):

    六、有名分组

    • 按关键字传参
    • 分组后,会把分组出来的数据,当关键字参数传给视图函数,所以视图函数需要定义形参,形参名要跟分组的名字对应,与顺序无关
    • url示例: re_path('^app/(?P<proj_id>[0-9]{2})',views.proj_detail),
    • 视图函数示例:  def proj_detail(request,proj_id):
    • 注意:有名分组和无名分组不要混用
    • 分组后捕获的数据默认都是str类型
    from django.contrib import admin
    from django.urls import path,re_path
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path('^app/(?P<proj_id>[0-9]{2})',views.proj_detail),
    ]
    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    
    
    def proj_detail(request,proj_id):
        print(proj_id,type(proj_id))
        return HttpResponse('ok')

     七、反向解析(通俗的理解就是,通过url层中的name反向解析出真正的url地址)

    '''
    在使用django项目时,一个常见的需求是获得url的最终形式,以用于嵌入到生成的内容中(视图中和限时给用户的url等)或用于处理服务端的导航(重定向等)。
    此时这些url尽量不要写死(如果多出调用这个URL,会导致扩展时容易产生错误),或者设计一种与URLconf毫不相关的专门的UR生成机制
    因为这样容易导致一定程度上产生过期的URL  
    
    在需要URL的地方,对于不同的层级,django提供不同的工具用于URL反差
        模板层: 使用url模板标签
        视图层: 使用from django.urls import reverse()函数  
    '''

    1、无参数(未分组)

    url('^proj/app/index', views.index, name='app_index') #name就是反向解析的名字
    from django.conf.urls import url  # 导入url
    from django.urls import path, re_path  # 导入path re_path
    from app01 import views
    
    urlpatterns = [
        url('^proj/app/index', views.index, name='app_index'),
        url('^proj/app/edit', views.edit, name='app_edit')
    ]

     模板层调用:# 实际等于:<a href="/proj/app/edit">新增项目</a>

    <a href="{% url 'app_edit' %}">新增项目</a>    

    视图层调用:(需要导入reverse模块)

    from django.shortcuts import render,reverse,redirect
    
    # Create your views here.
    
    def index(request):
        return render(request,'index.html')
    
    
    def edit(request):
        url=reverse('app_index')  # 传url中定义的name值
        print(url)
        return redirect(url)

    2、无名分组

    url层

    url('^proj/app/delete/([0-9]{1})',views.app_delete,name='app_delete')

    模板层调用,通过位置传参:

    <a href="{% url 'app_delete' 1 %}">删除项目</a>      # 参数紧跟name后面

    视图函数中调用:

    def index(request):
        url=reverse('app_detail',args=(1,))     # 通过args传参
        print(url)
        return redirect(url)

    3、有名分组

    url层

    url('^proj/app/delete/(?P<app_id>[0-9]{1})',views.app_delete,name='app_delete')

    模板层调用:

    {#<a href="{% url 'app_delete' 1 %}">删除项目</a>#}        # 既可以按位置传参
    <a href="{% url 'app_delete' app_id=1 %}">删除项目</a>     # 也可以按关键字传参   注意:此处的关键字就是url中有名分组中定义的

    视图层中调用:

    from django.shortcuts import render,HttpResponse,reverse,redirect
    
    def index(request):
        # url=reverse('app_detail',kwargs={'app_id':1})     # 既可以按kwargs关键字传参
        url=reverse('app_detail',args=(1,))                 # 也可以按args位置传参
        return redirect(url)

     八、路由分发

    当一个django项目里面有多个APP目录时,前期共用的一个url系统,会容易造成混淆,维护非常不方便,于是路由分发就让每个APP拥有自己的单独的url,然后向总的url中注册。

     总路由(不能加结束符$)

    from django.conf.urls import url,include
    
    urlpatterns = [
        url(r'^server/', include('server.urls')),      
        url(r'^account/', include('account.urls'))
    
    ]

    子路由

    from django.conf.urls import url
    from server import views
    
    urlpatterns = [
        url(r'^server_add/$',views.server_add),
    ]

     九、名称空间

    名称空间(namespace)是标识符的可见范围。一个标识符可在多个名称空间中定义,它在不同空间中的含义是互不相干的。这样在一个新的名称空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他名称空间中

    由于name没有作用域,django在反向解析url时,会在项目全局顺序搜索,当查到第一个name指定的url时,立即返回

    在开发项目时,会经常使用name属性反解出url,当不小心在不同app的urls中定义相同的name时,可能会导致url反解错误,为了避免这种事情发生,引入了名称空间

    不同app的urls中定义相同的name时,可能出现反解错误

    总urls.py 

    from django.conf.urls import url, include
    
    urlpatterns = [
        url(r'^server/', include('server.urls')),
        url(r'^account/', include('account.urls'))
    
    ]

    account的urls.py

    from django.conf.urls import url
    
    from account import views
    
    urlpatterns = [
        url(r'^account_list',views.account_list,name='list'),
        url(r'^account_add/$',views.account_add,name='add'),
    
    ]

    server的urls.py

    from django.conf.urls import url
    from server import views
    
    urlpatterns = [
        url(r'^server_list/$',views.server_list,name='list'),
        url(r'^server_add/$',views.server_add,name='add')
    
    ]

    account的视图函数

    from django.shortcuts import HttpResponse, reverse, redirect
    
    
    # Create your views here.
    
    def account_list(request):
        return HttpResponse('this is account_list page')
    
    
    def account_add(request):
        url = reverse('list')
        print(url)
        return redirect(url)

    server的视图函数

    from django.shortcuts import HttpResponse, reverse, redirect
    
    
    # Create your views here.
    
    def server_list(request):
        return HttpResponse('this is a server_list page')
    
    
    def server_add(request):
        url = reverse('list')
        print(url)
        return redirect(url)

    这样就会在反解时,出现错误,如下图,访问server和account都跳account的路由

    如何解决呢

    在总urls.py里指定namespace

    from django.conf.urls import url, include
    
    urlpatterns = [
        url(r'^server/', include(('server.urls', 'server'))),
        url(r'^account/', include(('account.urls', 'account')))
    
    ]
    
    # django2.0 不支持namespace格式,include中把子路由和namespace用元组包起来

    在视图函数反向解析的时候,指定是哪个名称空间下的

    def account_add(request):
        url = reverse('account:list')
        print(url)
        return redirect(url)

    在模板里:

    <a href="{% url 'server:list' %}">服务器列表</a> 

     十、伪静态

    '''
      伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页面,
    但是有的朋友为了实时的显示一些信息。或者还想运用动态脚本解决一些问题。
    不能用静态的方式来展示网站内容。但是这就损失了对搜索引擎的友好面。
    怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。就是展示出来的是以html一类的静态页面形式
    '''

    urls.py中配置

    url(r'^server_edit/(?P<id>[0-9]{1}).html',views.server_edit)

    浏览器中访问:必须带html

    http://127.0.0.1:8000/server/server_edit/1.html

     十一、根路径响应到指定函数

    根路径的url配置必须放到第一行(因为URLconf是自上而下匹配的)

    urlpatterns = [
        url(r'^$',views.server_index),    # 根路径响应到指定函数
        url(r'^server_list/$', views.server_list, name='list'),
        url(r'^server_add/$', views.server_add, name='add'),
        url(r'^server_edit/(?P<id>[0-9]{1}).html',views.server_edit),
    ]

    十二、没有配置的路径,响应到指定错误的视图函数

    必须写到url配置文件中的最后一行

    urlpatterns = [
        url(r'^$',views.server_index),
        url(r'^server_list/$', views.server_list, name='list'),
        url(r'^server_add/$', views.server_add, name='add'),
        url(r'^server_edit/(?P<id>[0-9]{1}).html',views.server_edit),
        url(r'',views.server_error)    # 最后一行
     
    ]
  • 相关阅读:
    ASP.NET 缓存 @ OutputCache
    转:Windows下JDK1.6.0+Tomcat6.0的安装配置
    bit、byte、位、字节、汉字、字符之间的区别
    JDK1.6 tomcat 6.0环境变量配置
    DataList和Repeater里的自定义button控件的使用
    Button控件的onclick、oncommand、commandname、CommandArgument的区别
    GridView里的Button控件用法
    ASP.NET2.0 文本编辑器FCKeditor用法
    应用系统架构设计补全篇
    java.util.vector中的vector的详细用法
  • 原文地址:https://www.cnblogs.com/lichunke/p/10566670.html
Copyright © 2011-2022 走看看