一、可视化界面之数据增删改查

小知识点:

  • 针对数据对象主键字段的获取可以使用更加方便的 obj.pk获取
  • 在模型类中定义双下str方法可以在数据对象被执行打印操作的时候方便的查看
  • form表单中能够触发调剂动作的按钮只有两个
<input type='submit'/>
<button></button>

数据增删改查功能

1.数据展示功能

开设接口、获取数据、传递页面、展示数据

view.py

def user_list_func(request):
user_data = models.UserInfor.objects.filter()
return render(request,'userListPage.html',{'user_data':user_data})

html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<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-success">数据添加</a>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Pwd</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.pwd }}</td>
<td class="text-center">
<a href="/user_edit/?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 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>

2.数据添加功能

开设接口、获取数据、发送数据、校验数据、录入数据、重定向

view.py

def user_add_func(request):
if request.method == 'POST':
name_infor = request.POST.get('name')
pwd_infor = request.POST.get('pwd')
if len(name_infor) == 0 or len(pwd_infor) == 0:
return HttpResponse('用户名或年龄不能为空')
user_infor = models.UserInfor.objects.filter(name=name_infor)
if user_infor:
return HttpResponse('用户名已存在')
models.UserInfor.objects.create(name=name_infor, pwd=pwd_infor)
return redirect('/user_list/')
return render(request, 'userAddPage.html')

html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据添加页</h1>
<div class="col-md-6 col-md-offset-3">
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control">
</p>
<p>pwd:
<input type="text" name="pwd" class="form-control">
</p>
<input type="submit" value="添加用户" class="btn btn-warning btn-block">
</form>
</div>
</div>
</div> </body>
</html>

3.数据编辑功能

开设接口、后端如何区分所要编辑的数据(问号携带参数)、后端获取用户数据、前端展示默认数据、获取用户并完成更新

view.py

def user_edit_func(request):
target_edit_id = request.GET.get('edit_id')
if request.method == 'POST':
name_infor = request.POST.get('name')
pwd_infor = request.POST.get('pwd')
if len(name_infor) == 0 or len(pwd_infor) == 0:
return HttpResponse('用户名或年龄不能为空')
models.UserInfor.objects.filter(pk=target_edit_id).update(name=name_infor, pwd=pwd_infor)
return redirect('/user_list/') target_edit_obj = models.UserInfor.objects.filter(pk=target_edit_id)[0]
print(target_edit_obj)
return render(request, 'userEditPage.html', {'target_edit_obj': target_edit_obj})

html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>edit</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据编辑页</h1>
<div>
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control" value="{{ target_edit_obj.name }}">
</p>
<p>pwd:
<input type="text" name="pwd" class="form-control" value="{{ target_edit_obj.pwd }}">
</p>
<input type="submit" value="编辑用户" class="btn btn-primary btn-block">
</form>
</div> </div>
</div>
</body>
</html>

4.数据删除功能

开设接口、问号携带参数、删除二次确认

view.py

def user_delete_func(request):
target_delete_id = request.GET.get('delete_id')
models.UserInfor.objects.filter(pk=target_delete_id).delete()
return redirect('/user_list/')

二、django请求生命周期流程图

1、Django请求的生命周期的含义

Django请求的生命周期是指:当用户在浏览器上输入url到用户看到网页的这个时间段内,Django后台所发生的事情。**

2、Django请求的生命周期图解及流程

这个图很重要 无论是学习阶段还是复习阶段

学习流程

通过这个生命周期图我们可以了解到接下去的学习流程为:路由层、视图层、模板层、模型层、组件、BBS项目

  • Django自带的web服务网管接口是wsgiref,因为他能承受的并发量特别低,因此我们在项目中会换成uwsgi,它的并发量比wsgiref高很多。
  • WSGI与wsgiref和uwsgi之间的关系是:WSGI是协议,wsgiref和uwsgi是实现协议功能的模块。
  • 中间件可以看成保安,数据的进出都会经过他的检查。
  • 路由层就是存放网址后缀与视图之间的关系。
  • 视图层存放功能函数,通过函数调用模版层中的html网页,同时在函数内通过models.py建立与数据库的交互。

三、django路由层

1.路由匹配

​ django2.X及以上 path第一个参数写什么就匹配什么

​ django1.X第一个参数是正则表达式

​ 无论什么版本django都自带加斜杠后缀的功能,也可以取消

ps:当我们在用网址访问网页的时候,有些网址需要在末尾加上‘/’符号,有些则不用,但是这些不用‘/’结尾的网址在跳转后,末尾自动补了一个‘/’。我们在配置文件中修改APPEND_SLASH 配置就可以设置这个功能,当他的值为True,就会自动添加斜杠进行匹配,如果改成False就不会自动匹配。

APPEND_SLASH = False

2.转换器

什么时候用转换器?

  • 当网址后缀不固定的时候 可以使用转换器来匹配

如何写path转换器?

  • path('login/<int:year>/<str:desc>/', views.login)

具体情况分析

  • 正常情况下很多网站都会有很多相似的网址 如果我们每一个都单独开设路由不合理,因此使用转换器动态匹配

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='转换器匹配到的类型转换之后的内容')

3.正则匹配

不同版本的区别

django1.x版本用的是url的形式直接使用正则进行匹配网址后缀,代码如下:

from django.conf.urls import url

urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]

django2.X及以上版本则替换成了path,django1.X路由匹配使用的是url() 功能与django2.X及以上的re_path()一致,第一个参数是正则。

from django.urls import path

urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
re_path('^test/$', views.test)
]

正则匹配斜杠导致的区别

正则匹配的时候要区分斜杠的作用,如果后面不写斜杠,匹配的结果就是网址中间有符合匹配条件的内容就会跳转,如果加了斜杠结尾,就是连着斜杠一起匹配(相当于匹配网址的结尾符合条件的网址)。

ps:正则匹配的本质是只要第一个正则表达式能够从用户输入的路由中匹配到数据就算匹配成功会立刻停止路由层其他的匹配直接执行对应的视图函数

4、正则匹配的无名有名分组

分组匹配

分组匹配就是使用小括号,产生分组优先,然后括号内匹配到的数据会当成参数传递给对应的函数。

无名分组

re_path('^test/(\d{4})/', views.test)

re_path('^test/(\d{4})/(.*?)/', views.test)
# test(实参request对象,括号内正则匹配到的内容)

会将括号内正则匹配到的内容当做位置参数传递给视图函数,在函数的参数中写位置参数接收即可。

有名分组

re_path('^test/(?P<year>\d{4})/', views.test)

re_path('^test/(?P<year>\d{4})/(?P<others>.*?)/', views.test)
# test(实参request对象,year='\d{4}匹配到的内容',others='.*?匹配到的内容') re_path('^test/(\d{4})/(?P<others>.*?)/', views.test)
# test(实参request对象,year='\d{4}匹配到的内容',others='.*?匹配到的内容')

会将括号内正则匹配到的内容当做关键字参数传递给视图函数,也需要使用位置参数接收。

ps:注意上述的有名分组和无名分组不能混合使用!!!

四、反向解析

1.引入反向解析

​ 页面上的一些超链接、重定向等路由都是写死的,一旦路由发生变化则会导致所有页面相关链接失效,而反向解析就是用来防止出现该问题的。

2.反向解析使用

方式一:路由对应关系起别名

在路由中给对应关系再取一个别名这样网页中使用时直接调用这个别名,就相当于调用了对应的后缀

路由层:
path('后缀',views.视图函数,name='关系名')

方式二:使用反向解析语法

html页面与后端都可以进行调用

html调用:
{% url '关系名' %} 后端跳转调用(需要先导入模块):
from django.shortcuts import reverse
reverse('关系名')

ps:反向解析的操作三个方法都一样:path()、re_path()、url()

3.有名无名反向解析(动态路由反向解析)

​ 如果路由里面有不确定的因素那么在使用反向解析的时候必须人为传递数据,且有几个不确定因素就得穿几个值

eg:
路由层:
path('func1/<str:others>/', views.func1_func, name='func1_view')
视图层:
reverse('func1_view', args=('嘿嘿嘿',))
html页:
{% url 'func1_view' 'jason' %}

ps:html页面上模板语法(因为定义动态路由的时候有一部分是动态匹配,所以需要指定一个参数)

五、作业

利用路由匹配与反向解析改写作业讲解

urls.py

from django.contrib import admin
from django.urls import path,re_path
from app001 import views urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index_func),
path('login/', views.login_func),
path('jump/',views.jump_func),
path('haohaohao/',views.haohaohao_func),
path('signin/',views.signin_func), # 访问用户数据的接口
path('user_list/', views.user_list_func, name='list_view'), # user_list_func(实参request对象)
# 添加用户数据的接口
path('user_add/', views.user_add_func, name='add_view'),
# 编辑用户数据的接口
path('user_edit/<str:edit_id>/', views.user_edit_func, name='edit_view'),
# 删除用户数据的接口
re_path('^user_delete/(?P<delete_id>.*?)/', views.user_delete_func, name='delete_view'),
]

views.py

from django.shortcuts import render, HttpResponse, redirect
from app001 import models def user_list_func(request):
user_data = models.UserInfor.objects.filter()
return render(request, 'userListPage.html', {'user_data': user_data}) def user_add_func(request):
if request.method == 'POST':
name_infor = request.POST.get('name')
pwd_infor = request.POST.get('pwd')
if len(name_infor) == 0 or len(pwd_infor) == 0:
return HttpResponse('用户名或年龄不能为空')
user_infor = models.UserInfor.objects.filter(name=name_infor)
if user_infor:
return HttpResponse('用户名已存在')
models.UserInfor.objects.create(name=name_infor, pwd=pwd_infor)
return redirect('/user_list/')
return render(request, 'userAddPage.html') def user_edit_func(request, edit_id):
target_edit_id = edit_id
if request.method == 'POST':
name_infor = request.POST.get('name')
pwd_infor = request.POST.get('pwd')
if len(name_infor) == 0 or len(pwd_infor) == 0:
return HttpResponse('用户名或年龄不能为空')
models.UserInfor.objects.filter(pk=target_edit_id).update(name=name_infor, pwd=pwd_infor)
return redirect('/user_list/') target_edit_obj = models.UserInfor.objects.filter(pk=target_edit_id)[0]
print(target_edit_obj)
return render(request, 'userEditPage.html', {'target_edit_obj': target_edit_obj}) def user_delete_func(request, delete_id):
target_delete_id = delete_id
models.UserInfor.objects.filter(pk=target_delete_id).delete()
return redirect('/user_list/')

userListPage.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<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="{% url 'add_view' %}" class="btn btn-success">数据添加</a>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Pwd</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.pwd }}</td>
<td class="text-center">
<a href="{% url 'edit_view' edit_id=user_obj.pk %}" class="btn btn-primary btn-xs">编辑</a>
<a href="{% url 'delete_view' 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>add</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据添加页</h1>
<div class="col-md-6 col-md-offset-3">
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control">
</p>
<p>pwd:
<input type="text" name="pwd" class="form-control">
</p>
<input type="submit" value="添加用户" class="btn btn-warning btn-block">
</form>
</div>
</div>
</div> </body>
</html>

userEditPage.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>edit</title>
{% load static %}
<script src="{% static 'jquery-3.6.1.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 class="text-center">数据编辑页</h1>
<div>
<form action="" method="post">
<p>name:
<input type="text" name="name" class="form-control" value="{{ target_edit_obj.name }}">
</p>
<p>pwd:
<input type="text" name="pwd" class="form-control" value="{{ target_edit_obj.pwd }}">
</p>
<input type="submit" value="编辑用户" class="btn btn-primary btn-block">
</form>
</div> </div>
</div>
</body>
</html>

12月12日内容总结——Django之数据增删改查、Django请求生命周期流程图、Django路由层(路由匹配、转换器、正则匹配)、反向解析的更多相关文章

  1. Django ORM 数据库增删改查

    Django ORM 数据库增删改查 增 # 创建.增加数据(推荐) models.UserInfo.objects.create(username=') # 创建.增加数据 dic = {'} mo ...

  2. Django框架之第三篇(路由层)--有名/无名分组、反向解析、路由分发、名称空间、伪静态

    一.Django请求生命周期 二.路由层  urls.py url()方法 第一个参数其实就是一个正则表达式,一旦前面的正则匹配到了内容,就不会再往下继续匹配,而是直接执行对应的视图函数. djang ...

  3. Django数据库操作(增删改查)

    Django数据库操作(增删改查) 创建数据库中的一个表 class Business(models.Model): #自动创建ID列 caption = models.CharField(max_l ...

  4. Django中的增删改查

    1.model 假设我们的model如下: 某个JobType下有很多Job. class JobType(models.Model): name = models.CharField(max_len ...

  5. Django中ORM增删改查

    新建模型 class Author(models.Model): nid = models.AutoField(primary_key=True) name=models.CharField( max ...

  6. day 67 django 之ORM 增删改查基础

    一 操作基础前提准备 1. 新建django 项目 mysite  子项目app01 ,选择好做路径. 2  .2-1在app01 下面models 中引用 模块 from  django.db im ...

  7. Django models 的增删改查

    增 from app01.models import * #create方式一: Author.objects.create(name='Alvin') #create方式二: Author.obje ...

  8. django数据库的增删改查

    正常启动服务安装数据库cmd命令:python manage.py makemigrations 创建用户 在pxm里面会有一个py文件..这就是生成了表结构cmd命令:python manage.p ...

  9. 模拟django配置环境进行数据增删改查,测试的时候有用

    import os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE','day76.settings' ...

  10. django数据库基本操作-增删改查(tip)-基本

    补充:django外键保存 #外键保存 form_data = Form_Data() project, is_created = Project_Name.objects.get_or_create ...

随机推荐

  1. 论文笔记 - Active Learning by Acquiring Contrastive Examples

    Motivation 最常用来在 Active Learning 中作为样本检索的两个指标分别是: 基于不确定性(给模型上难度): 基于多样性(扩大模型的推理空间). 指标一可能会导致总是选到不提供有 ...

  2. java安全之CC1浅学(2)

    前言 上一篇了解了commons-collections中的Transformer,并且构造了一个简单的payload,接下来就需要将其改造为一个可利用的POC AnnotationInvocatio ...

  3. 2022春每日一题:Day 27

    题目:友好城市 分析一下可以转化为:选取最多的点对,使得点对之间连线没有交点,没有交点说明什么,假设选定第i组,则对于任意的j,一定满足a[i].l<a[j].l && a[i] ...

  4. 【云原生 · Kubernetes】Jenkins+Gitlab+Rancher+Docker 实现自动构建镜像的 CI 平台(一)

    1 准备 Jenkins+Gitlab 实验环境 1.1 准备实验环境:恢复到以一下快照:该环境已经配置好 jenkins+gitlab+sonar-配置通 主机角色: IP 地址 运行的服务 硬件配 ...

  5. 单例模式实现的多种方式、pickle序列化模块、选课系统需求分析等

    目录 单例模式实现的多种方式 方式一: 方式二: 方式三 方式四 pickle序列化模块 选课系统需求分析 功能提炼 选课系统架构设计 三层架构 选课系统目录搭建 选课系统功能搭建 单例模式实现的多种 ...

  6. 使用repo上传代码

    前言~ repo是一款安卓用于管理源码的工具,由python实现,基于git工具 本文介绍了repo的常用使用方式. 一,下载代码 1. repo init 初始化命令 此命令常用选项就那几个,此处取 ...

  7. python将列表中的数字合并成一个数字

    前言 今天,写算法题,其中需要进行这一步操作 输入: [1,2,3,4,5] 输出: 12345 解决办法 我首先想到用 join() 函数,但我发现使用join函数要求列表中的元素都是字符串,所以需 ...

  8. 关于linux mint更改资源管理器的快捷键

    前言 首先要知道 linux mint 的默认资源管理器是 nemo 我很不习惯 ctrl+d 在nemo里面是 收藏到侧边栏 我习惯 ctrl+d 在windows上是删除文件 所以下面我就修改这个 ...

  9. shell编写循环检查脚本

    背景:如下脚本实现当微服务重启后,检查微服务的启动端口正常,可通过轮询的方式来实现所需要用到配置文件config.properties信息如下: onlineService:8001 algorthS ...

  10. JavaEE Day01 基础加强

    今日内容 1.Junit单元测试(测试类) 2.反射 3.注解 一.Junit单元测试 1.概述 测试分类 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值 2.白盒测试:需要写代码 ...