Django——路由层
路由层
路由匹配
url(r'test/',views.test),
url(r'^$',views.testadd)
"""
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
在输入url的时候会默认加斜杠
django内部帮你做到重定向
一次匹配不行
url后面加斜杠再来一次
"""
# 取消自动加斜杠
APPEND_SLASH = False/True # 默认是自动加斜杠的(True)
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首页
url(r'^$',views.home),
# 路由匹配
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
# 尾页(了解)
url(r'',views.error),
]
无名分组
"""
分组:就是给某一段正则表达式用小括号扩起来
"""
url(r'^test/(\d+)/',views.test)
def test(request,xx):
print(xx)
return HttpResponse('test')
# 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
有名分组
"""
可以给正则表达式起一个别名
"""
url(r'^testadd/(?P<year>\d+)',views.testadd)
def testadd(request,year):
print(year)
return HttpResponse('testadd')
# 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
单个分组的多次使用
'''注意:无名分组与又名分组不能同时混合使用'''
# 单个分组可以使用多次
url(r'^index/(\d+)/(\d+)/(\d+)/...', views.index),
url(r'^index/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/...', views.index),
反向解析
#本质:通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数
# 先给路由与视图函数起一个别名 (别名不能冲突)
url(r'^func_kkk/',views.func,name='ooo')
# 反向解析
# 后端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
reverse('ooo')
# 前端反向解析
<a href="{% url 'ooo' %}">111</a>
无名有名分组反向解析
# 反向解析的本质:通过一些方法得到一个结果,该结果可以访问到对应的url从而触发视图函数的运行
# 无名分组反向解析
# 路由层
url(r'index/(\d+)/', views.index,name='xxx')
# 前端
# {% url 'xxx' %} 同样会报相同的错误
{% url 'xxx' 123 %}
# 后端
# reverse('xxx') 直接写会报错,必须要手动指定一个参数能够被\d+匹配到
reverse('xxx', args=(1, ))
# 有名分组反向解析
# 路由层
url(r'^func/(?P<year>\d+)/',views.func,name='ooo')
# 前端
<a href="{% url 'ooo' year=123 %}">111</a> # 了解
<a href="{% url 'ooo' 123 %}">222</a> # 记忆
# 后端
# 正规写法 了解
print(reverse('ooo',kwargs={'year':123}))
# 简便的写法 记忆
print(reverse('ooo',args=(111,)))
# 数字一般情况下放的是数据的主键值 数据的编辑和删除
url(r'^edit/(\d+)/',views.edit,name='xxx')
def edit(request,edit_id):
reverse('xxx',args=(edit_id,))
{%for user_obj in user_queryset%}
<a href="{% url 'xxx' user_obj.id %}">编辑</a>
{%endfor%}
路由分发
- 路由分发:能够实现一个人写一个功能应用,最后直接通过路由分发来将功能应用整合到一起,只需要访问不同的url前缀就能够访问对应功能应用下的资源
'''
路由分发的优点:
1、一个人写一个功能应用,整合时只需要将对应的app的路由加到总路由中即可(项目多人开发)
2、当一个django项目中url特别多的时候,为了减轻总路由的压力,便于维护,也可以使用路由分发
3、路由分发之后,总路由不再与视图函数有直接对应关系,所有的资源访问请求都转交给对应的app来处理
'''
# 总路由
# 方式一:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include(app01_urls)), # 只要url前缀是app01开头,全都交给app01处理
url(r'^app02/', include(app02_urls)), # 只要url前缀是app02开头,全都交给app02处理
]
# 方式二:
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
'''注意:总路由的url千万不要加$结尾'''
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
]
# app01.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg/', views.reg)
]
# app02.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^reg/', views.reg)
]
名称空间
- 当多个应用出现相同别名时,正常情况下反向解析无法自动始别前缀,可以利用名称空间来解析
# 名称空间
# 总路由
url(r'^app01/', include('app01.urls',namespace='app01')),
url(r'^app02/', include('app02.urls',namespace='app02')),
# 解析的时候
# app01
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
# app02
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
# 视图函数使用:reverse('app01:reg')、reverse('app02:reg')
# 前端页面使用:{% url 'app01:reg' %}、{% url 'app02:reg' %}
# 只要保证名字不冲突就没有必要使用名称空间
'''
一般情况下,有多个app时在起别名时会加上app的前缀,这样就能够保证多个app之间名字不冲突
'''
# 子路由下:
urlpatterns = [
url(r'^reg/',views.reg,name='app01_reg')
]
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
# 视图函数直接使用别名即可
伪静态
'''
静态网页:数据是写死的
伪静态:将一个动态网页伪装成静态网页
伪装的目的:增大网站的seo查询力度,增加了搜索引擎收藏网站的概率
搜索引擎本质上就是一个巨大的爬虫程序
'''
urlpatterns = [
url(r'reg.html/', views.reg, name='app02_reg')
]
虚拟环境
'''
正常开发中,我们会给每个项目配备独有的解释器环境用来安装只有该项目内使用的模块,用不到的一概不装
虚拟环境就是单独的python解释器环境,每创建一个虚拟环境就相当于重新下载了一个全新的python解释器
扩展:
如何批量安装模块
开发当中我们会给每一个项目配备一个requirements.txt文件
里面书写了该项目所有的模块即版本
只需要直接输入一条命令即可一键安装所有模块即版本
'''
django版本区别
1、路由层使用方法
django1:url(),第一个参数支持正则
django2、django3:path(),第一个参数不支持正则,写什么就匹配什么
re_path()支持正则,就类似django1的url()
2、django2、django3的path()提供了五种转换器以及能够自定义转换器
3、级联删除更新
django1:默认自动级联删除更新
django2、django3:需要自己手动设置参数来实现级联删除更新
on_update=models.CASCADE
on_delete=models.CASCADE
-
路由层的方法使用不同
# django1.X路由层使用的是url方法 url()第一个参数支持正则 # django2.X、3.X版本中路由层使用的是path方法 path()第一个参数是不支持正则的 写什么就匹配什么 re_path()就等价于1.X中的url from django.urls import path, re_path from django.conf.urls import url re_path(r'^index/',index), url(r'^login/',login) # 2.X和3.X里面的re_path就等价于1.X里面的url
-
path内部的转换器
虽然path不支持正则 但是它的内部支持五种转换器 path('index/<int:id>/',index) # 将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数 def index(request,id): print(id,type(id)) return HttpResponse('index') ''' str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?) '''
-
自定义转换器
class MonthConverter: # 固定写法 regex='\d{2}' # 属性名必须为regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是两个数字,返回的结果也必须是两个数字 from django.urls import path,register_converter from app01.path_converts import MonthConverter # 先注册转换器 register_converter(MonthConverter,'mon') from app01 import views urlpatterns = [ path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'), ]
-
模型层中
1.X外键默认都是级联更新删除的 models.ForeignKey(to='Publish') 2.X和3.X中需要你自己手动配置参数 models.ForeignKey(to='Publish',on_delete=models.CASCADE)