django之路由层

1.django中urls.py负责url的路由分发

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
# url的第一个参数实际为一个正则表达式,第二个参数为视图函数。浏览器访问时,会遍历该列表,匹配到则终止,不再往下匹配。

当用户访问的url不存在时,django会尝试将用户访问的url后加上“/”,返回给浏览器,浏览器负责重定向。实际上进行了2次http请求。

例如访问https://127.0.0.1:8000/admin时,由于admin和r'^admin/'并不能匹配。django会重定向。

实际上不能这么理解。如果按上述说法,将进行一个死循环,匹配不到就添加"/"重定向,岂不是无穷无尽了? 这点,我们可以通过访问一个不存在的url得到证明。

django在收到url时会自动检测有没有“/”,
如果原本就有,则直接匹配,
	- 匹配不到直接返回404。
    - 匹配的到则调用视图函数
如果原本没有'/',则拿添加上'/'以后的url进行匹配。
    - 如果匹配不到则直接返回404
    - 如果匹配得则向浏览器发送重定向的标志。

# 证明例子
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/',views.index),
    url(r'^index',views.index1),
]
访问:https://127.0.0.1:8000/index时,按照第一种说法是调用index1,而事实上时调用的index。

2.有名分组和无名分组

分组就是在url匹配关系中给某一段正则表达式加了括号。当匹配成功后,会将括号内的内容作为参数传入视图函数。有名分组是以关键字传参的方式,无名分组是以位置传参的方式。

注意:在一个匹配关系中,有名分组和无名分组不能混合使用!!!!

无名分组

urls.py
---------------------------
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^edit_user/(\d+)/',views.edit_user),
]

views.py
-----------------------------
def edit_user(request,id):
    return HttpResponse(id)

有名分组

urls.py
---------------------------
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^edit_user/(?P<user_id>\d+)/',views.edit_user),
]

views.py
----------------------------
# 此处形参名必须与urls有名分组的名字一致
def edit_user(request,user_id):
    return HttpResponse(user_id)

补充,在一个正则---视图函数的匹配关系下,

1.有名分组和无名分组不能混合使用。

2.同一种分组方式可以使用多个。

3.反向解析

反向解析的需求由来:当我们在前端或者在后端时,在用户做某些操作时希望页面跳转到我们指定的url,而一旦我们的url名字发生了改变,所有指定跳转到该页面的代码都需要被修改。这时极为不便的,反向解析由此诞生。

反向解析的使用:反向解析实际上给每一组url----视图函数的对应关系增加了一个name的属性,通过这个name属性和前后端一些函数的使用,即可找到这种对应关系。

urls.py
---------------------------
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^edit_user/',views.edit_user,name='edit'),
]

前端使用反向解析

{% url 'edit' %} ---->即name='edit'所在的url

后端使用反向解析

from django.shortcuts import reverse

reverse('edit') ----->name='edit'所在的url

明白了反向解析的由来和使用后,我们再思考一个问题。如果反向解析的url是一个带有有名分组或者无名分组的url呢?

无名分组的反向解析

urls.py
---------------------------
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^edit_user/(\d+)/',views.edit_user,name='edit'),
]

前端

{% url 'edit' 123 %}
# 只需要在后面直接跟参数即可

后端

reverse('edit',args=(123,))
# args中放入参数

有名分组的反向解析

有名分组的反向解析与无名分组的反向解析基本一致。

urls.py
---------------------------
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^edit_user/(?P<user_id>\d+)/',views.edit_user,name='edit'),
]

前端

{% url 'edit' 1 %}
{% url 'edit' user_id=1 %}
# 以上两种都可以使用,第一种使用时注意位置。

后端

reverse('edit',args=(1,))
reverse('edit',kwargs={'user_id':1})
# 以上两种都可以使用,第一种注意位置

4.路由分发

路由分发的需求由来:我们知道一个django项目由一个个app组成。当我们开发的django项目非常庞大时,也会有许多的html文件、也会有许多views视图函数,许多的url对应关系,按照我们之前的想法,所有的对应关系都会在总的urls.py上。

这其中有两个问题

  • 多个app之间不能很好的实现分离,不能很好的实现分小组开发。
  • 非常多的urls对应关系,会使代码显得比较混乱

我们设想,如果每个app都有自己的路由系统,则各app之间的urls就可以相互分隔开。

为了解决上面出现的问题,路由分发由此而来。路由分发不仅允许每个app拥有自己的urls.py文件,还允许有自己的static和templates文件夹。这使得分小组开发非常便捷,代码的简洁性和可读性也增强!

而我们的总路由-----项目目录下的urls.py则只需要根据http请求的url中app的名字,将其路由分发给相应的app路由系统。

总路由

urls.py
--------------------
from django.conf.urls import url,include
from app01 import urls as app01_urls
from app02 import urls as app02_urls

urlpatterns = [
    url(r'^app01/',include('app01_urls)),
    url(r'^app02/',include('app02_urls'))
]

以上写法可简写为:

urls.py
from django.conf.urls import url,include
import app01
import app02
urlpatterns = [
    url(r'^app01/',include('app01.urls')),
    url(r'^app02/',include('app02.urls'))
]

子路由

app01下的urls.py
-----------------------
from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/',views.index)
]
#  当访问 https://127.0.0.1:8000/app01/index/便会触发响应的函数
app02下的urls.py
-----------------------
from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^index/',views.index)
]
#  当访问 https://127.0.0.1:8000/app02/index/便会触发响应的函数

5.名称空间

心细的读者可能已经发现,路由分发导致了反向解析出现了一个问题:不同的app下可能有相同的url— name的对应关系。

当app01和app02中都有name='index'的对应关系时,我们在反向解析时到底是解析app01中的index还是app02中的index?

为了避免上述问题的出现,我们可以在总路由系统下增加一个命名空间的概念

urlpatterns = [		url(r'^app01/',include('app01.urls',namespace='app01'))
        url(r'^app02/',include('app02.urls',namespace='app02'))
]
后端解析
reverse('app01:index')
reverse('app02:index')
前端解析
{% url 'app01:index' %}
{% url 'app02:index' %}

通常我们在给视图函数与url的对应关系取别名时,可以加上app的前缀,也可以防止上述问题的产生。

6.虚拟环境

虚拟环境是我们在开发不同的项目时,可以只加载针对本项目使用的模块,来加快加载资源时的速度。虚拟环境即一个全新的python解释器环境,有如刚重装的系统一样。

7.django版本的区别

路由层
1.X用的是url
2.X、3.X用的是path

url第一个参数是一个正则表达式
而path第一个参数不支持正则表达式 写什么就匹配什么
如果你觉得path不好用 2.x、3.x给你提供了一个跟url一样的功能
re_path 等价于1.x里面的url功能

虽然path不支持正则表达式 但是它给你提供了五种默认的转换器
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)

path('login/<int:year>/',login)

除了默认的五种转换器之外 还支持你自定义转换器
class MonthConverter:
    regex='\d{2}' # 属性名必须为regex

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return value # 匹配的regex是两个数字,返回的结果也必须是两个数字

8.伪静态

伪静态
url以.html结尾 给人的感觉好像是这个文件是写死的 内容不会轻易的改变
伪静态

为了提高你的网站被搜索引擎收藏的力度 提供网站的SEO查询效率
posted @ 2020-01-06 19:11  GhostAnt  阅读(177)  评论(0编辑  收藏  举报