Django基础之路由层

路由的作用

路由即请求地址与视图函数的映射关系,在Django中路由默认配置在urls.py中,如下图:

路由配置的格式

# urls.py
from django.conf.urls import url
from django.contrib import admin

# 由一条条映射关系组成的urlpatterns这个列表称之为路由表
urlpatterns = [
    url(r'^admin/', admin.site.urls),  # Django自带的后台管理系统的路由匹配关系
    url(regex, view, kwargs=None, name=None), 
] 

# url参数介绍:
# 1、regex:正则表达式,专门用来匹配url地址(url地址中所有内容均被当作字符串)的路径部分,不考虑请求方法如GET、POST或者域名,例如:
# 请求url地址为:https://www.example.com/myapp/,,正则表达式要匹配的部分是myapp/
# 请求url地址为: https://www.example.com/myapp/?page=3, 正则表达式要匹配的部分是myapp/
# 注意:
# 1.1 django的url配置不会考虑请求方法,换句话说,对于相同的URL地址,所有的请求方法如POST、GET、HEAD等,都将被路由到相同的功能view上
# 1.2 切记正则表达式开头无需加/

# 2、view:通常为一个视图函数,写函数的内存地址用来处理业务逻辑
# 3、kwargs:额外传递给视图函数的参数,可选(用法详见:分组)
# 4、name:为正则表达式匹配到的url地址起别名,可选(用法详见:反向解析

注意事项

注意一:
正则表达式不需要添加一个前导的反斜杠,因为每个URL都有。例如,应该是^index而不是 ^/index。

注意二:
每个正则表达式前面的'r' 是可选的但是建议加上。

注意三:
如果我们想匹配的路径就只是index/,那么正则表达式应该有开始符与结束符, 如 ^index/$。这样逻辑才算严谨

注意四:
刚刚我们在浏览器输入:http://127.0.0.1:8001/index/ ,Django会拿着路径部分index/去路由表中自上而下匹配正则表达式,一旦匹配成功,则立即执行其后的视图函数,不会继续往下匹配,此处匹配成功的正则表达式是 r'^index/$'。

注意五:
但是我们在浏览器输入:http://127.0.0.1:8001/index Django同样会拿着路径部分index去路由表中自上而下匹配正则表达式,貌似并不会匹配成功任何正则表达式( r'^index/$'匹配的是必须以 / 结尾,所以不会匹配成功index),但实际上仍然会看到结果 index page...,原因如下:

在配置文件settings.py中有一个参数APPEND_SLASH,该参数有两个值True或False。

默认是True,此时,Django会自动拿着路径部分(即index)去路由表中匹配正则表达式,发现匹配不成功,那么Django会在路径后加 / (即index/)再去路由表中匹配,如果匹配失败则会返回路径未找到,如果匹配成功,则会返回重定向信息给浏览器,要求浏览器重新向 http://127.0.0.1:8001/index/ 地址发送请求。

APPEND_SLASH = False

当APPEND_SLASH=False时,则不会执行上述过程,即一旦url地址的路径部分匹配失败就立即返回路径未找到,不会做任何的附加操作。

正则表达式

1.url函数第一个参数只写test

url(r'test', views.test),


验证:
http://127.0.0.1:8000/test/  可以连接
http://127.0.0.1:8000/testadd/  可以连接
http://127.0.0.1:8000/testaddghiaohahihio/  可以连接
http://127.0.0.1:8000/gjieohaionaknatestaddghiahiio/  可以连接

# 只要网址中存在test就能够连接服务端

2.^test/

url(r'^test/', views.test),

验证:
http://127.0.0.1:8000/test/  可以连接
http://127.0.0.1:8000/testadd/  不能
http://127.0.0.1:8000/test/agion/fag  可以连接
http://127.0.0.1:8000/bsznnztest/ehp/fjiphuu  不能
http://127.0.0.1:8000/ahruiht/test/agia/toim/  不能

# 只要以test/开头就能够连接服务端

3.^test/$

url(r'^test/$', views.test),

验证:
http://127.0.0.1:8000/test/  可以连接
http://127.0.0.1:8000/test/agia/toim/  不能
http://127.0.0.1:8000/hta/test/agia/toim/  不能

# ^以什么开头,$以什么结尾。所以只有test/才可以连接服务器

首页的路由:

url(r'^$', views.home),

分组

无名分组

无名分组:把一个正则表达式用小括号括起来。

单个分组:

url(r'^test/(\d+)/$', views.test),

多个分组:

url(r'^test/(\d+)/(\d+)/(\d+)/$', views.test),

无名分组就是把匹配的内容当成位置参数传递给视图函数,有几个分组,视图函数中就需要几个形参(形参可以任意取名)来接收。或者直接使用*args来接收(元组形式)。

路由传参数的方式:

1.问号传值
2.无名分组传值

具体使用:

def test(request, *args):
    print(args)
    return HttpResponse('test page')

# > ('257',)
# > ('333', '555', '666')

有名分组

有名分组:把一个正则表达式用小括号括起来,然后给这个括起来的内容起个名字

单个分组:

url(r'^testadd/(?P<year>\d+)/$', views.testadd),

多个分组:

url(r'^testadd/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/$', views.testadd),

有名分组就是把匹配的内容当成key=value关键字参数传递给视图函数,有几个分组,视图函数就用几个形参来接收,并且形参名必须与有名分组中的名字一致。也可以使用**kwargs来接收,字典形式,可以用字典的键来取值。

具体使用:

def testadd(request, year, month, day):
    print(year, month, day)  # 2023 05 13
    return HttpResponse('testadd page')

def testadd(request, **kwargs):
    print(kwargs)  # {'year': '2023', 'month': '05', 'day': '13'}
    print(kwargs['year'])  # 2023
    return HttpResponse('testadd page')


'''无名和有名不要混合使用,但是,单个无名或者单个的有名可以多次使用'''

总结

无名分组和有名分组都是为了获取路径中的参数,并传递给视图函数,区别在于无名分组是以位置参数的形式传递,有名分组是以关键字参数的形式传递。

反向解析

可以给每一个路由起一个别名,然后,通过一些方法反向解析这个路由名字,可以得到这个路由对应的地址。是在一个函数中反向解析出另外一个路由名称。

关键函数

Django提供了一个reverse()函数来实现反向解析。该函数接受视图函数的名称和可选参数作为参数,并返回关联的URL字符串。reverse()函数会返回一个字符串,我们可以将其传递给HttpResponseRedirect()函数,达到重定向的效果。需要注意的是,args参数必须以列表或元组的形式传递,即使只有一个参数。

使用场景:

使用reverse()函数可以避免在代码中硬编码URL字符串,方便维护和修改。

案例

urls.py

url(r'^index/$', views.index, name='xxx'),  # 此时就可以动态修改路由url函数中的第一个参数的值,写的是什么,就可以反向解析出什么

后端反向解析

from django.shortcuts import  reverse
print(reverse('xxx'))  # /index/  /index/a/

前端反向解析

<a href="{% url 'xxx' %}">qqqqq</a>

无名分组反向解析

1.单个无名分组的使用:

urls.py

url(r'^index/(\d+)/', views.index, name='xxx')

后端的反向解析

print(reverse('xxx', args=(111,)))  # /index/111/
# 需要指定一个参数,这个参数必须符合正则表达式

前端的反向解析

<a href="{% url 'xxx' 222 %}">qqqqq</a>

2.多个无名分组的使用:

urls.py

url(r'^index/(\d+)/(\w+)/$', views.index, name='xxx'),

后端的反向解析

print(reverse('xxx', args=(111, 'sss')))  # /index/111/sss/
# 多个参数都是写在arg元组中

前端的反向解析

<a href="{% url 'xxx' 555 'kkk' %}">qqqqq</a>  # 多个参数用空格隔开

对于前端的反向解析,中间的参数一般会写什么?一般情况下都写的是主键id,可以在前端模板语法,for循环中使用。例如:

<a href="{% url 'yyy' foo.id  %}">修改</a>

有名分组反向解析

1.单个有名分组的使用:

urls.py

url(r'^index/(?P<year>\d+)/', views.index, name='youming')

后端的反向解析

print(reverse('youming', kwargs={'year': 2023}))  # /index/2023/

前端的反向解析

<a href="{% url 'youming' year=2023 %}">qqqqq</a>

2.多个有名分组的使用:

urls.py

url(r'^index/(?P<year>\d+)/(?P<kk>\w+)/', views.index, name='youming'),

后端的反向解析

print(reverse('youming', kwargs={'year': 2023, 'kk': 'nian'}))  # /index/2023/nian/

前端的反向解析

<a href="{% url 'youming' year=2023 kk='nian' %}">qqqqq</a>

路由分发

随着项目功能的增加,app会越来越多,路由也越来越多,每个app都会有属于自己的路由,如果再将所有的路由都放到一张路由表中,会导致结构不清晰,不便于管理,所以我们应该将app自己的路由交由自己管理,然后在总路由表中做分发。路由分发是做应用的整合。

项目中的urls.py,叫总路由。每一个应用自己的路由文件称为,子路由。在应用里面默认是没有urls.py的,需要手动创建一个。

总路由分发的两种方式:

第一种方式

from app01 import urls as app01_urls  # 起别名
from app02 import urls as app02_urls

urlpatterns = [
    # app01/reg/
    url(r'^app01/', include(app01_urls)),

    # app02/reg/
    url(r'^app02/', include(app02_urls)),
]

第二种方式

# app01/reg/
url(r'^app01/', include('app01.urls')),
    
# app02/reg/
url(r'^app02/', include('app02.urls')),

路由分发后,总路由就不用动了,以后就直接修改子路由。总路由中的后缀坚决不能加 $。

子路由:

# app01的urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^reg/$', views.reg)
]

# app02的urls.py
from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^reg/$', views.reg)
]

伪静态的概念

1.静态文件:文件中的内容是固定的。

2.伪静态:是把一些动态的网页伪装成静态网页。

3.为什么要伪装呢?
其实是因为静态的网页更加容易被搜索引擎抓取到。

4.怎么伪装?
在后缀上加.html。

url(r'^index.html/', views.index),

虚拟环境

一个虚拟环境相当于是一个纯净的python解释器!!!针对一个新的项目,解释器上只装跟本项目有关的模块,其余没用的都不装。

创建虚拟环境:
1.pycharm创建

使用虚拟环境:

2.命令行创建
python3.6以前的版本需要先下载一个模块。

命令行的方式:

python(解释器) -m venv 虚拟环境名字
示例:
python -m venv py38venv

注意:python命令此处不支持多版本共存的操作 python27 python36 python38这种不支持,想要给哪个解释器创建虚拟环境,需要把这个解释器在环境变量中的位置移动到上面。

需要激活虚拟环境:

先进到虚拟环境中:
cd py38venv
cd Scripts

激活
    activate
关闭
    deactivate

cmd终端中,如果左侧有有个括号,括号内是你建立的虚拟环境名称。就表示你已经进入到虚拟环境中了。

命令行创建虚拟环境也可以直接百度。一个博客

django2

1. django2中路由使用的是path

  • django1中路由使用的是url

  • django2中路由使用的是path

url支持的是正则,path不支持正则,path是精准匹配(写什么就匹配什么)

2.django2也可以使用正则

from django.urls import path, re_path

re_path就相当于django1中的url----------->支持正则

3.path支持5种转换器

转换器,是将对应位置匹配到的数据转换成固定的数据类型。Django2中默认支持以下5中转换器:

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

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

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

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

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

  • 还支持自定义转换器(自己写正则表达式匹配更加细化的内容)

具体使用:

path('index/<str:info>/', views.index),  # index(实参request对象,info='转换器匹配到的类型转换之后的内容')

path('index/<str:xxx>/<int:id>/', views.index_func)  # index_func(实参request对象,xxx='转换器匹配到的类型转换之后的内容',id='转换器匹配到的类型转换之后的内容')

'''转换器<>匹配到的类型是关键字传参,传给对应的视图函数,所以视图函数要接收'''

4. 创建表关系

  • django1中的表关系是级联更新级联删除

  • django2需要执行on_delete参数

posted @ 2023-04-27 19:42  星空看海  阅读(51)  评论(0编辑  收藏  举报