Django的生命周期及路由层
目录
django请求生命周期流程图(必会)
# 扩展知识点
"""
缓存数据库
提前已经将你想要的数据准备好了 你来直接拿就可以
提高效率和响应时间
当你在修改你的数据的时候 你会发现数据并不是立刻修改完成的
而是需要经过一段时间才会修改
博客园
了解即可
"""
路由层
路由匹配
规则:
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
# 在url.py里写下面参数
url(r'test',views.test),
url(r'testadd',views.testadd)
# 在view.py里写对应视图函数
def test(request):
return HttpResponse('test')
def testadd(request):
return HttpResponse('testadd')
访问网站
分析出现的现象:
为什么访问test的时候可以正常返回test页面
但是访问testadd还是返回test的页面呢
这是因为路由匹配是正则匹配,只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
你输入testadd的时候,路由匹配匹配到test就不往后面继续了,直接去找test函数了,所以不找testadd函数
解决方案:
url(r'test/',views.test), # 进行加/处理
url(r'testadd/',views.testadd) # 进行加/处理
原理:
先按用户输入的url(用户没加/)进行匹配
一次匹配不行
在输入url的时候会默认加斜杠
django内部再帮你做到重定向
url后面加斜杠再来一次匹配
所以此时test/是匹配不到的,而testadd第一次不行,django加/重定向之后就可以了
# 取消自动加斜杠(了解)
APPEND_SLASH = False # 默认是自动加斜杠的True
url严谨化
首页
# 首页
url(r'^$',views.home),
def home(request):
return HttpResponse('首页')
分组
定义:就是给某一段正则表达式用小括号扩起来
无名分组
无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
eg:
url(r'^test/(\d+)/',views.test)
# 这里的(\d+)就是无名分组
访问页面:
结论:
无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
有名分组
有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
可以给正则表达式起一个别名(关键字参数名)
eg:
url(r'testadd/(?P<year>\d+)/(?P<age>\d+)', views.testadd),
# 这里的意思是给一个(\d+)赋值给关键字参数year 一个(\d+)赋值给关键字参数age
无名有名是否可以混合使用
"""
嘻嘻 不能混用
但是同一个分组可以使用N多次
"""
# 单个的分组可以使用多次
url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),
反向解析
普通反向解析
定义:通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数
前端反向解析
# 先给路由与视图函数起一个别名
url(r'^func_asd/',views.func,name='xxx')
# 前端反向解析
<a href="{% url 'xxx' %}">111</a>
<a href="{% url 'xxx' %}">222</a>
<a href="{% url 'xxx' %}">333</a>
后端反向解析
# 先给路由与视图函数起一个别名
url(r'^func_asd/',views.func,name='xxx')
# 后端反向解析
先导入模块reverse
from django.shortcuts import render,HttpResponse,redirect,reverse
def func(request):
print(reverse('xxx'))
return HttpResponse('func')
有名无名分组反向解析
结论: 只要你的正则表达式带有分组,那么对应的函数就必须指定一个分组能匹配到的内容当作参数
无名分组
前端:
<a href="{% url 'xxx' %}">111</a>
# 无名分组反向解析
url(r'^index/(\d+)/', views.index, name='xxx')
不传值会报错
传值
<a href="{% url 'xxx' 123 %}">111</a>
后端:
同样也需要传值
def index(request, args):
return HttpResponse('index')
def home(request):
# print(reverse('xxx')) 报错 因为缺少参数
print(reverse('xxx', args=(1,))) # 在这传值
return render(request, 'home.html')
# 无名分组反向解析
url(r'^index/(\d+)/', views.index, name='xxx')
这个数字写代码的时候应该放什么?
数字一般情况下放的是数据的主键值!!!!!!!!!!!!!!!
有名分组
# 有名分组反向解析
url(r'^func/(?P<year>\d+)/',views.func,name='ooo')
前端
<a href="{% url 'ooo' 123 %}">222</a> 记忆
<a href="{% url 'ooo' year=123 %}">111</a> 了解
后端
def home(request):
print(reverse('ooo', args=(111,)))
return render(request, 'home.html')
总结
用来实现不用手写url后缀并且能够按需求传入与客户对应的信息
urlpatterns = [
# 展示信息页面
url(r'^look/', views.look),
# 编辑信息页面
url(r'^editor/(\d+)/', views.editor, name='xxx'),
# 查看信息
def look(request):
user_list = models.Userinfo.objects.all()
if request.method == 'POST':
return render(request, 'editor.html')
return render(request, 'look.html', locals())
# 编辑
def editor(request, editor_id):
appoint_obj = models.Userinfo.objects.filter(id=editor_id).first()
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
models.Userinfo.objects.filter(id=editor_id).update(name=username, pwd=password)
return redirect('/app02/look/')
return render(request, 'editor.html', locals())
路由分发
django的每一个应用都可以有自己的templates文件夹 urls.py、static文件夹
正是基于上述的特点 django能够非常好的做到分组开发(每个人只写自己的app)
作为组长 只需要将手下书写的app全部拷贝到一个新的django项目中 然后在配置文件里面注册所有的app再利用路由分发的特点将所有的app整合起来当一个django项目中的url特别多的时候 总路由urls.py代码非常冗余不好维护
这个时候也可以利用路由分发来减轻总路由的压力利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理,识别当前url是属于哪个应用下的 直接分发给对应的应用去处理
总路由:
from django.contrib import admin
from django.conf.urls import url, include
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
from app01 import views
urlpatterns = [
url(r'^reg/', views.reg)
]
效果:
名称空间(了解)
# 当多个应用出现相同的别名的时候 反向解析的时候会出现冲突
"""
正常情况下的反向解析是没有办法自动识别前缀的!!!
"""
# 名称空间
# 总路由
url(r'^app01/',include('app01.urls',namespace='app01')), # 用namespace区分就行了
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里填的要带名字
reverse('app02:reg')
{% url 'app01:reg' %}
{% url 'app02:reg' %}
# 其实只要保证名字不冲突 就没有必要使用名称空间
"""
一般情况下 有多个app的时候我们在起别名的时候会加上app的前缀
这样的话就能够确保多个app之间名字不冲突的问题
"""
urlpatterns = [
url(r'^reg/',views.reg,name='app01_reg') # 这样前面加app的名字就不会冲突了
]
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
在同一个django项目中 别名不能冲突
即只要别名不冲突 那么反向解析就不会出错!!!
伪静态(了解)
"""
静态网页
数据是写死的 万年不变
伪静态
将一个动态网页伪装成静态网页
为什么要伪装呢?
https://www.cnblogs.com/Dominic-Ji/p/9234099.html
伪装的目的在于增大本网站的seo查询力度
并且增加搜索引擎收藏本网上的概率
搜索引擎本质上就是一个巨大的爬虫程序
总结:
无论你怎么优化 怎么处理
始终还是干不过RMB玩家
"""
urlpatterns = [
url(r'^reg.html',views.reg,name='app02_reg') # 在url后面加.html就行了
]
虚拟环境(了解)
"""
在正常开发中 我们会给每一个项目配备一个该项目独有的解释器环境
该环境内只有该项目用到的模块 用不到一概不装
linux:缺什么才装什么
虚拟环境
你每创建一个虚拟环境就类似于重新下载了一个纯净的python解释器
但是虚拟环境不要创建太多,是需要消耗硬盘空间的
扩展:
每一个项目都需要用到很多模块 并且每个模块版本可能还不一样
那我该如何安装呢? 一个个看一个个装?
开发当中我们会给每一个项目配备一个requirements.txt文件
里面书写了该项目所有的模块即版本
你只需要直接输入一条命令即可一键安装所有模块即版本
"""
django版本区别
"""
1.django1.X路由层使用的是url方法
而在django2.Xhe3.X版本中路由层使用的是path方法
url()第一个参数支持正则
path()第一个参数是不支持正则的 写什么就匹配什么
如果你习惯使用path那么也给你提供了另外一个方法
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
2.虽然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,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
3.除了有默认的五个转换器之外 还支持自定义转换器(了解)
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'),
]
4.模型层里面1.X外键默认都是级联更新删除的
但是到了2.X和3.X中需要你自己手动配置参数
models.ForeignKey(to='Publish')
models.ForeignKey(to='Publish',on_delete=models.CASCADE...)
"""