目录
数据增删改查
针对数据对象主键字段的获取可以使用更加方便的 obj.pk获取,在模型类中定义双下str方法可以在数据对象被执行打印操作的时候方便的查看。
form表单中能够触发调剂动作只要两个
<input type='submit'/>
<button></button>
步骤:
1.数据展示功能
开设接口、获取数据、传递页面、展示数据
2.数添加功能
开设接口、获取数据、发送数据、校验数据、录入数据、重定向
3.数据编辑功能
开设接口、后端如何区分所要编辑的数据(问号携带参数)、后端获取用户数据、前端展示默认数据、获取用户并完成更新
4.数据删除功能
开设接口、问号携带参数、删除二次确认
代码展示:数据库使用的是django自身自带的sqlite3
models.py
class User(models.Model):
# ORM不用写主键字段,会自动创建主键字段id
# id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name='用户名')
age = models.IntegerField(verbose_name='年纪')
def __str__(self):
return '用户对象:%s' %self.name
#便于对象打印之后的查看,不影响数据库 所有不需要执行迁移命令
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
# 访问用户数据的接口
path('user_list/',views.user_list_func),
# 添加用户数据的接口
path('user_add/',views.user_add_func),
# 编辑用户数据的接口
path('user_edt/',views.user_editor_func),
# 删除用户数据的接口
path('user_delete/',views.user_delete_func)
]
views.py
from django.shortcuts import render,HttpResponse,redirect
from app01 import models
# Create your views here.
def user_list_func(request):
# 1.获得user表中所有的数据展示到html页面上
user_date =models.User.objects.filter() # 括号里不写等于查看所有[对象1,对象2]
# print(user_date)
# 2.利用模板语法传递数据到页面并完成处理最终返回html页面
return render(request,'userlistPage.html',{'user_data':user_date})
def user_add_func(request):
#2.根据不同的请求方式做不同的处理
if request.method=='POST':
#3.获取用户相关数据
name_data = request.POST.get('name')
age_data = request.POST.get('age')
if len(name_data)==0 or len(age_data)==0:
return HttpResponse('用户名和年龄不能为空')
user_data =models.User.objects.filter(name=name_data)
if user_data:
return HttpResponse('用户名已经存在')
models.User.objects.create(name=name_data,age=age_data)
#5,重定向到数据展示页
return redirect('/user_list/')
# 1.先返回一个数据新增数据的html页面
return render(request,'userAddPage.html')
def user_editor_func(request):
#1.获取用户想要编辑的数据主键值
target_edit_id = request.GET.get('edit_id')
#4.根据不同的请求处理不同的逻辑
if request.method=='POST':
name_data = request.POST.get('name')
age_data=request.POST.get('age')
if len(name_data)==0 or len(age_data)==0:
return HttpResponse('用户名和年龄不能为空')
models.User.objects.filter(pk=target_edit_id).update(name=name_data,age=age_data)
#5,重定向到数据展示页
return redirect('/user_list/')
#2 根据主键值获取对应的数据
target_edit_obj = models.User.objects.filter(pk=target_edit_id)[0]
# print(target_edit_obj)
#3.返回一个编辑数据的页面,并且该页面需要提前展示出原来的数据
return render(request,'userEditPag.html',{'target_edit_obj':target_edit_obj})
def user_delete_func(request):
target_delete_id = request.GET.get('delete_id')
models.User.objects.filter(pk=target_delete_id).delete()
return redirect('/user_list/')
userlistPaga.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center"> 数据展示页</h1>
<div class="col-md-8 col-md-offset-2">
<a href="/user_add/" class="btn btn-primary btn-xs">数据添加</a>
<table class="table table-hover table-striped">
<thead>
<tr >
<th>Id</th>
<th>Name</th>
<th>Age</th>
<th class="text-center" >Operation</th>
</tr>
</thead>
<tbody>
{% for user_obj in user_data %}
<tr>
<td>{{ user_obj.pk }}</td>
<td>{{ user_obj.name }}</td>
<td>{{ user_obj.age }}</td>
<td class="text-center">
<a href="/user_edt/?edit_id={{ user_obj.pk }}" class="btn btn-primary btn-xs" >编辑</a>
{# <a href="/user_delete/?delete_id={{ user_obj.pk }}" class="btn btn-danger btn-xs">删除</a>#}
<a href="/user_delete/?delete_id={{ user_obj.pk }}" class="btn btn-danger btn-xs delBtn" >删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$('.delBtn').click(function (){
let res = confirm('你确定要删除吗')
if(res){
}else{
return false
}
})
</script>
</body>
</html>
userAddPage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center"> 数据添加页</h1>
<div class="col-md-8 col-md-2">
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control">
</p>
<p>age:
<input type="text" name="age" class="form-control">
</p>
<p>
<input type="submit" value="添加用户" class="btn btn-warning btn-block">
</p>
</form>
</div>
</div>
</div>
</body>
</html>
userEditPage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center"> 数据编辑页</h1>
<div class="col-md-8 col-md-2">
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control" value="{{ target_edit_obj.name }}">
</p>
<p>age:
<input type="text" name="age" class="form-control" value="{{ target_edit_obj.age }}">
</p>
<p>
<input type="submit" value="编辑用户" class="btn btn-primary btn-block">
</p>
</form>
</div>
</div>
</div>
</body>
</html>
django请求生命周期流程图(*****)
学习流程:路由层、视图层、模板层、模型层、组件、BBS项目
django请求生命周期的含义:当用户在浏览器输入URL到用户看到网页的这个时间段内,django后台所发生的事情
Django的请求生命周期流程
1.首先 用户在浏览器中输入url,发送一个GET方法的request请求。
2.Django中封装了socket的WSGI服务器,监听端口接受这个request请求,在进行解析封装,然后传送到中间件中,这个request请求再依次经过中间件。
3.对请求进行效验处理,再传输到路由系统中进行路由分发,匹配相对应的视图函数(FBV),再将request请求传输到views中的这个视图函数中,进行业务逻辑处理。
4.调用modles模型层中表对象,通过orm拿到数据库(DB)的数据。
5.同时拿到templates中相应的模板进行渲染,然后将这个封装了模板response响应传输到中间件中,依次进行处理,最后通过WSGI再进行封装处理,响应给浏览器展示给用户。
django的请求周期分布解析
1.浏览器
发送请求(HTTP协议)
2.web服务网关接口
1.请求来的时候解析封装
响应走的时候打包处理
2.django默认的wsgiref模块不能承受高并发 最大只有1000左右
上线之后会替换成uwsgi来增加并发量
3.WSGI跟wsgiref和uwsgi是什么关系
WSGI是协议
wsgiref和uwsgi是实现该协议的功能模块
3.django后端
1.django中间件(暂时不考虑 后面讲)
类似于django的保安 门户
2.urls.py 路由层
识别路由匹配对应的视图函数
3.views.py 视图层
网站整体的业务逻辑
4.templates文件夹 模版层
网站所有的html文件
5.models.py 模型层
ORM
额外扩展:缓存数据库的作用
缓存数据库
缓存数据库: 提前已经将你想要的数据准备好了 你来直接拿就可以 提高效率和响应时间
django路由层
1.路由匹配
django1.x 第一个参数是正则表达式
django2.x及以上版本 path第一个参数写什么就匹配什么 匹配到直接执行对应的视图函数
path('admin/', admin.site.urls)
路由匹配错误及原因
当浏览器要打开下面的web网页接口 ?
URL=127.0.0.1:8000/testadd
代码展示:
urlpatterns = [
url(r'test',views.test),
url(r'testadd',views.testadd)
]
原因:按照匹配规则,从上到下只要正则表达式匹配成功,就不会往下执行,当路由匹配到第一个正则(test)就成功匹配了,就不会往下执行了
如何解决上述问题?
方式1:
我们在输入URL默认会加斜杠,因为django内部帮我们做了重定向,一次匹配不行,url后面加斜杠再来一次
按照下面的顺序依次匹配
url(r'text/',views.test),
url(r'textadd/',views.test),
方式2:
settings配置文件内添加(控制django是否自动添加斜杠匹配
APPEND_SLASH = False/True # 默认是True自动添加斜杠
url方法第一个是参数 的正则表达式
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),
]
解析:
^ : 开头
$ : 结尾
2. 正则匹配
django2.X及以上版本有re_path 第一个参数是正则
匹配的本质是只要第一个正则表达式能够从用户输入的路由中匹配到数据就算匹配成功会立刻停止路由层其他的匹配直接执行对应的视图函数
re_path('^test/$', views.test)
django1.X路由匹配使用的是url() 功能与django2.X及以上的re_path()一致
3.转换器
正常情况下很多网站都会有很多相似的网址 如果我们每一个都单独开设路由不合理
django2.X及以上版本路由动态匹配有转换器(五种)
str:匹配除路径分隔符外的任何非空字符串。
int:匹配0或者任意正整数。
slug:匹配任意一个由字母或数字组成的字符串。
uuid:匹配格式化后的UUID。
path:能够匹配完整的URL路径
ps:还支持自定义转换器(自己写正则表达式匹配更加细化的内容)
# 转换器 将对应位置匹配到的数据转换成固定的数据类型
path('index/<str:info>/', views.index_func), # index_func(实参request对象,info='转换器匹配到的类型转换之后的内容')
path('index/<str:info>/<int:id>/', views.index_func) # index_func(实参request对象,info='转换器匹配到的类型转换之后的内容',id='转换器匹配到的类型转换之后的内容')
4.正则匹配的无名有名分组
无名分组
分组就是给某一段正则表达式用小括号括起来
re_path('^test/(\d{4})/', views.test)
无名分组:会将括号内正则表达式匹配到的内容当做位置参数传递给视图函数
代码实现
urls.py
# 会把括号中匹配的数字当成位置参数传给视图函数
url(r'^test/(\d(4))/',views.test)
views.py
def test(request,xx):
print(xx)
return HttpResponse('test')
正则:
\d(4) : 匹配4个任意数字
有名分组
re_path('^test/(?P<year>\d{4})/', views.test)
有名分组:会将括号内正则表达式匹配到的内容当做关键字参数传递给视图函数
注意上述的分组不能混合使用!!!
代码实现
# 会把括号中匹配的数字当成关键字参数传给视图函数
url(r'^testadd/(?P<year>\d+)',views.testadd)
def testadd(request,year):
print(year)
return HttpResponse('testadd')
注意:有名分组可以允许有多个分组名,但不允许一个无名分组一个或者多个有名分组存在。即有名分组和无名分组不能混合是使用
单个有名或者无名分组是可以使用多次的
1.无名分组单个使用多次
url(r'^index/(\d(4))/(\d(4))/(\d(4))/',views.index),
2.有名分组单个使用多次
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),
def index(request,*args,**kwargs):
print(args)
return HttpResponse('index')
反向解析
但路由频繁变化的时候,html页面与后端上的连接地址如何做到动态解析呢?
通过在url里面设置路由和视图函数的别名,动态解析出对应的路由,该路由直接执行对应的函数,函数直接执行对应的url
1.概念
通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数 实现url路由频繁变化,html界面与后端动态解析连接地址操作步骤:
基本使用
1.方向解析器路由配置
path('login001/', views.login, name='login_view') # name='login_view' 起别名
前后端反向解析
2.导入模块reverse
from django.shortcuts import render,HttpResponse,redirect,reverse
3.反向解析 reverse('login_view')
def home(request):
print(reverse('login_view'))
return render(request,'home.html')
前端反向解析
4.前端模板文件反向解析
<a href="{% url 'login_view' %}">111</a>
动态路由的反向解析
path('func1/<str:others>/', views.func1_func, name='func1_view')
html页面上模板语法 {% url 'func1_view' 'jason' %}
后端语法 reverse('func1_view', args=('嘿嘿嘿',))
标签:匹配,name,views,后端,request,django,user,路由
From: https://www.cnblogs.com/zhanglanhua/p/16977199.html