day52(路由层相关知识)
今日内容详细
先看黑丝
昨日内容回顾:
#HttpResponse
首先我们看这个这个他是主要用于返回字符串类型的数据,我们只需关注自己的核心业务其他一概不用管他会帮我们封装好
#render
# 首先我们来想web框架可以结合前后端所以我们返回到前端的肯定不能是一些文字所以我们就用到了这个模块,render 主要用于返回html页面专用 并且支持django自己写的模板语法怎么说他就是可以给这个html页面传值
# redirect
主要用于重定向 括号内可以写其他网站的全称 也可以自己网站的后缀
#静态文件配置
1.静态文件的概念
前端页面需要使用到的不经常被修改的文件
css文件、js文件、img文件、第三方框架文件
2.一般情况下针对静态文件都会有专门的存储位置
static文件夹 # 默认都叫static
3.暴露django静态文件资源
配置文件中添加配置
STATICFILES_DIRS = [os.path.join(BASE_DIR,'static')]
4.接口前缀与静态文件夹名称区别
接口前缀是访问静态文件资源的前提
符合前提之后才可以去列表中罗列的路径下一次查找具体文件
5.接口前缀动态绑定
{% load static %}
href={% static 'a.txt' %}
#request对象方法
1.request.method
获取当前请求方式的纯大写字符串
# django的基础阶段就两个,一个是GET/一个是POST
2.request.POST
获取post请求提交的普通数据(不包含文件)
request.POST 看成是一个字典
request.POST.get() 获取值列表最后一个元素
request.POST.getlist() 获取整个值列表
3.request.GET
获取url问号后面携带的数据
request.GET 看成是一个字典
request.GET.get() 获取值列表最后一个元素
request.GET.getlist() 获取整个值列表
#django连接MySQL:
'''django默认自带一个小型的sqlite3数据库'''1.修改配置文件配置2.指定链接模块 尤其是django1.X版本 第二步千万不要忘记
#orm相关操作
1.ORM的概念
对象关系映射
类 表
对象 记录
属性 字段
2.orm的基本使用
models.py 模型层(专门用于数据库层面交互)
class UserInfo(models.Model):
models.AutoField(prmiry_key=True)# 等价于uid int primary key auto_increment
name = models.CharField(max_length=32)# 等价于name varchar(32)
3.迁移命令
python3 manage.py makemigrations # 记录
python3 manage.py migrate # 将操作迁移到数据库
"""
只要修改了models.py中与数据库相关的代码 那么都需要重新执行迁移
"""
#数据增删改查
from app01 import models
# 查
models.UserInfo.objects.filter()
结果可以看成是列表套一个个数据对象
# 增
models.UserInfo.objects.create(name='jason')
返回值就是当前被创建的数据对象本身
# 改
models.UserInfo.objects.filter().update(name='jasonNB')
# 删
models.UserInfo.objects.filter().delete()
作业讲解
1.使用自带的sqlite3数据库
第一次使用pycharm链接sqlite3也需要先下载驱动
2.编写注册、登录功能
'''静态文件无法拖拽到pycharm文件栏:C盘不支持 采用cv操作'''
前期提交post请求初选403 需要配置文件注释一行
def reg(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
confirm_pwd = request.POST.get('confirm_password')
# 1.先判断两次密码是否一致
if not password == confirm_pwd:
return HttpResponse('两次密码不一致')
# 2.判断用户名是否已存在
is_user = models.UserInfo.objects.filter(name=username)
if is_user:
return HttpResponse('当前用户已存在')
# 3.写入数据库
models.UserInfo.objects.create(name=username, pwd=password)
# return HttpResponse(f'{username}注册成功')
# 4.直接跳转到登录页面:后面还可以实现 注册之后自动登录
return redirect('/login/')
return render(request, 'reg.html')
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
is_user = models.UserInfo.objects.filter(name=username).first()
# filter结果是列表套对象
if not is_user:
return HttpResponse('用户名不存在')
if str(is_user.pwd) == password: # 获取到的用户输入是字符串 数据库字段是整型
return HttpResponse("登录成功")
return HttpResponse('密码错误')
return render(request, 'login.html'
django请求生命周期流程图
整体概括请求的走向以及django的核心组成部分
参考群内截图
后期django的学习就按照图上的部分 一块一块的详细学!!!
路由层之路由匹配
学习路由之前我们先简单回顾一下我们以前所学的一个正则
我们看一下下面这个正则表达式
正则表达式 '^[a-zA-Z0-9''-'\s]{1,30}$' 代表什么意思?
[A-z] 等于 [a-zA-Z] 表示匹配所有大小写字母
0-9 表示数字
"-' 都是表示本义字符,匹配这三个符号.
\s 匹配非换行的所有空白字符
以上全部在[]中代表匹配以上所有内容.
然后{1,30}代表匹配1次到30次,最少1次.
头尾的^和$代表匹配一个完整的字符串,如果这个字符串中出现任何一个不是[]中内容的字符这个字符串就无法匹配.
最后^$匹配的定义可以是单行的也可以是多行的,这需要靠正则的选项判断.
首先我们来看一下他的一个特点
路由匹配特点:只要匹配上了就会立刻结束执行对应的视图函数 并且url方法的第一个参数其实是一个正则表达式 只要这个正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了这个····
1 路由参数
# 第一个参数是正则表达式
# 第二个参数是视图函数内存地址
# 第三个参数是个字典 {'name':lqz,'age':18},给视图函数传递默认值
# 第四个参数name,当前路由的别名,用作反向解析
url(r'^home2/', views.home,{'name':'ayca','age':19},name='home'),
2 访问根路径,触发视图函数执行(路由怎么配)
-url(r'^$', admin.site.urls),
3 在路由中配置多个相同路由会怎么样?
只会执行第一个
4 如下路由会怎么样?永远不会匹配到第二个
url(r'^login', views.home),
url(r'^login2', views.home),
演变过程
正则是base/ 内容是base 那么首次无法匹配
# django二次追加斜杠机制
首次匹配不上 那么django还会让浏览器默认加斜杠再次发送请求
base 301
base/ 200
讲述一个了解知识点如何取消斜杠机制(/)但是不推荐
1 路由配置如下
url(r'^login/$', views.home),
访问:http://127.0.0.1:8000/login/
访问:http://127.0.0.1:8000/login 两次请求,重定向了一次
2 是否开启URL访问地址后面部位/跳转至带有/的路径的配置项 ?
Django settings.py配置文件中默认没有APPEND_SLASH这个参数,但 Django默认这个参数为APPEND_SLASH=True,其作用就是自动在网址结尾加'/'
如果要去掉这种特性,需要在settings.py中写
APPEND_SLASH=False #但是注意一般不要加这个
设置为False就是关闭URL访问地址后面不为/跳转至带有/的路径的配置项
# 由于第一个参数是正则 所以当项目特别大 对应关系特别多的时候要格外的注意是否会出现路由顶替的现象
小扩展:
可以定制一个主页面 用户不携带后缀可以直接访问(掌握)
url(r'^$',views.home)
也可以定义一个尾页 用户输入一个没有对应关系的直接返回(了解)
url(r'.*',views.error)
无名分组
无名分组:
urlpatterns = [
url(r'^login/([0-9]{4})$',views.login),
]
在普通的正则匹配中加上()就是无名分组,那么这样有什么意义呢?
首先在后端的views上,会得到一个分组的参数,以上面代码为例,那么views.login函数的参数除了request,还需要添加一个参数(名字随意),进行几次分组那么就需要多添加几次参数
进入view页面,其中xxx的名字是随意的,传进来的分组的数据例如我输入的网址是:login/222,那么xxx的值为222
def login(request,xxx):
print(xxx)
有名分组:
有名分组其实就是在无名的分组的基础上加上了名字
urlpatterns = [
url(r'^login/(?P<year>[0-9]{4})$',views.login),
]
语法为:(?P<名字> 正则表达式),就是在无名分组的括号里面加上了?P<名字>,注意其中P为大写
既然有了名字,那么在views页面就不能给函数传递随意的参数了:
def login(request,year):
print(year)
第二个参数year是urls页面命名的名字:
如果名字不一样则会报错
这里有一个坑,既然分组有有名分组和无名分组,那么能不能一起使用?
答:不行,别问,问就是不行
teacher:
url(r'^test/([0-9]{4})/$', views.test)
"""
路由匹配成功之后就会调用视图函数默认情况下会自动给视图函数传递一个request位置参数
test(request)
如果路由匹配中使用括号对正则表达式进行了分组 那么在调用视图函数的时候
会将括号内匹配到的内容当做位置参数传递给视图函数
test(request,括号内正则表达式匹配到的内容)
上述特性django称之为'无名分组'
"""
url(r'^testadd/(?P<user_id>[0-9]{4})$', views.testadd)
"""
给括号内的正则表达式起别名之后 匹配成功则会讲括号内匹配到的内容按照关键字参数传递给视图函数
testadd(request,user_id=括号内正则表达式匹配到的内容)
上述特性django称之为'有名分组'
"""
# 两者是否可以混合使用
url(r'^test/(\d+)/(?P<user_id>[0-9]{4})/$', views.testadd) # 不可以
无名有名分组不能混合使用!!! 单个可以重复使用
url(r'^test/(\d+)/(\d+)/$', views.testadd) # 可以
url(r'^test/(?P<a>\d+)/(?P<b>\d+)',views.testadd) # 可以
反向解析
首先回顾一下a标签
a标签在html里面称为——超链接,起作用就是跳转页面,比如从a页面跳转到b页面就需要使用到a标签 a标签是超链接,可以通过它的href属性创建通向其它页面,文件,同一页面中的位置,打开、发送电子邮件
1.在href属性中设置超链接,
在href属性中输入需要跳转的页面,当在页面中点击这个a标签时,会跳转到指定路径下
代码:
<a herf="./Microsoft首页.html"></a>
详解
"""
a标签的href可以写网址的全称 也可以写后缀
href='https://www.baidu.com'
href='/login/' # 自动补全当前服务的ip和port
href='127.0.0.1:8000/login/'
"""
"""
a标签的href可以写网址的全称 也可以写后缀
href='https://www.baidu.com'
href='/login/' # 自动补全当前服务的ip和port
href='127.0.0.1:8000/login/'
"""
1.页面上有很多a标签链接了其他路由
2.路由匹配表达式出现了变化 html页面上的地址全部失效
反向解析
在建立路由的时候,为路由指定标签(别名),使用的时候调用别名
# 反向解析
通过反向解析可以获取到一个结果 该结果可以访问到一个路由
步骤1:给对应关系起别名
url(r'^func666/',views.func,name='func_view')
步骤2:使用反向解析获取结果
前端:
{% url 'func_view' %} # func666/ 结果可以访问路由
后端:
from django.shortcuts import reverse
reverse('func_view',) # func666/ 结果可以访问路由
# 无名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
'''无法明确括号内正则表达式的内容 需要人为指定'''
前端:
{% url 'func_view' 123 %} # func666/123/
后端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
# 有名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(?P<id>\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果
'''无法明确括号内正则表达式的内容 需要人为指定'''
前端:
{% url 'func_view' 123 %} # func666/123/
{% url 'func_view' id=123 %} # func666/123/
后端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
reverse('func_view',kwargs={'id':1}) # func666/1/
"""
疑问:无名有名反向解析中的手动传值 这个值在实际工作中到底可以是什么
一般情况下这个值可以是数据的主键值、页面的页码、区域的编号等
"""
反向解析代码
路由代码:
# 首页home
url(r'^$',views.home)
url(r'^func/',views.func)
视图views.py
def home(request):
return render(request, 'home.html')
def func(request):
return HttpResponse('牛马浪漫至死不渝')
home.html
<a href="/func/">大牛马<\a>
<a href="/func/">小牛马<\a>
<a href="/func/">行文至此<\a>
<a href="/func/">落笔为终<\a>
如何实现反向解析?
当url中的路由名不管怎么变都能找到对应的视图函数
路由
# 给路由与对应视图函数起一个名字(别名):name='A6'
url(r'^func66',views.func,name='A6')
后端反向解析
导入模块:reverse
from django.shortcuts import render, HttpResponse, redirect, reverse
视图views.py
def home(request):
print(reverse('A6'))# 这里写上反向解析的别名
return render(request, 'home.html')
前端反向解析
在a标签的href中使用{% url '别名' %}
#注:使用了上述方法后无论路由中的url怎么变都能被前端的{% url '别名' %}解析出来
代码:
<a href="{% url 'n' %}">牛马A<\a>
{# 会被自动解析成:<a href="/func_k/">牛马A</a>#}
在a标签的href中使用{% url '别名' 数据的主键值 %}
作用:前端中反向解析 别名后面的放数据的主键值,主要用于数据的编辑和删除
# home.html
<a href="{% url 'xxx' 123 %}"></a> # 必须还要传入一个数字匹配
无名分组的反向解析
# 首页
url(r'^$',views.home)
# 无名分组反向解析
url(r'^index/(\d+)/'views.index,name='xxx') # 起了别名xxx,只要是index/数字/都能访问
视图views.py(后端反向解析)
from django.shortcuts import render,HttpResponse,reverse
def home(request):
# print(reverse('xxx')) # 后端反向解析,报错,必须还需要指定一个参数能够被\d+匹配
print(reverse('xxx',args=(1,))) # 必须手动匹配一个数字,返回结果/index/1/
return render(request,'home.html')
def index(request,args):
return HttpResponse('index')
有名分组的反向解析
路由:
url(r'^func/(?P<year>\d+)/'views.func,name='ooo')
视图views.py(后端反向解析)
def func(request,year):
return HttpResponse('func')
def home(request):
# print(reverse('ooo')) # 会报错
print(reverse('ooo',kwargs={'year':123})) # 反向解析
return render(request,'home.html')
前端反向解析
<a href="{% url 'ooo' year=123 %}">111</a>
路由分发
"""
如果一个django项目特别庞大 里面有很多应用 每个应用下有很多对应关系
那么django自带的路由层里面的代码就会非常非常的多 如何优化???
根据应用的不同拆分到不同的应用中
django支持每个应用都可以有自己独立的
路由层、模板层、静态文件、视图层(默认)、模型层(默认)
上述特性能够让django在分组开发上更加的方便、快捷
所有人都可以在应用中开发完整的项目功能
最后汇总到一个空的django项目中 然后通过路由分发整合所有人的应用
"""
1.创建多个应用 并去配置文件中注册
INSTALLED_APPS = [
'app01',
'app02'
]
2.在多个应用中编写相同的路由
urlpatterns = [
url(r'^index/',views.index111)
]
urlpatterns = [
url(r'^index/',views.index)
]
3.路由分发
总路由
from django.conf.urls import url, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))
"""总路由只负责分发 不负责视图函数对应"""
上述代码还可以简写
from django.conf.urls import url, include
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
名称空间
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。
由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
1.不同的应用使用了相同的别名 那么反向解析是否自动识别
index_view app01/index/
index_view app02/index/
2.验证发现默认情况下是不会自动识别应用前缀的 如何解决反向解析问题
方式1:名称空间
总路由添加名称空间
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
应用反向解析自动提示
reverse('app01:index_view')
reverse('app02:index_view')
{% url 'app01:index_view' %}
{% url 'app02:index_view' %}
方式2:只需要确保反向解析的别名在整个项目中不重复即可!!!
可以在别名的前面加上应用名的前缀
url(r'^index/',views.index,name='app01_index_view')
url(r'^index/',views.index,name='app02_index_view')
"""
名称空间其实是可有可无的知识 但是在实际工作中还是有不少程序员喜欢使用
"""
单词仅供参考
注一切一切以实际代码为主
render:提供
redirect:重新使用改变方向
static:静止的
request:请求 要求
method:方法 措施
getlist:获取列表
make:制作
migrations:迁移 移居
makemigrations:进行迁移
migrat:迁移
userinfo:用户信息
info:信息
filter:滤器 ; 过滤器 ; 滤光器 ; 滤声器 ; 滤波器 ; 筛选程序
object:对象
create:创造
update:更新
delete:删除
models:模型
test:测验;考查;试验;检查;化验;检验;测试;考验
error:错误 差错
views 看法,意见,见解 ; 态度 ; 方法,方式 ; 观看 ;
home:家的;家庭的;在家里做的;
func 功能 ; 作用
shortcuts: 近路;捷径 ; 快捷办法,捷径 ; 快捷方式 ;
revers:逆转
index:(物价和工资等的)指数;指标;索引;标志;表征;量度;指数
为…编索引;将…编入索引;将(工资等)与(物价水平等)挂钩;使指数化
patterns 模式 ; 方式 ; 范例 ; 典范 ; 榜样 ; 样板 ;
INSTALLED_APPS:已安装的应用程序
INSTALLED:已安装
include:包括;包含
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下