Django 基于ORM的CURD、外键关联,请求的生命周期

news2024/11/16 15:36:40

文章目录

  • 基于ORM进行的CURD
  • ORM外键关联
  • Django请求的生命周期流程图

基于ORM进行的CURD

本质上就是通过面向对象的方式,对数据库的数据进行增、删、改、查。

这里将会将我们之前所有内容结合到一起,首先确保基于上序操作已经建立好了UserInfo表,那么我们还需要建立几个HTML文件,只需要关注与提交数据有关的标签

user_list:作为主页使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2" >

                <h1 class="text-center">用户列表展示</h1>
                <hr>
                <a href="/add/" class="btn btn-info" >添加</a>
                <table class="table table-striped table-bordered">
                    <thread>
                        <tr>
                            <th class="text-center">ID</th>
                            <th class="text-center">username</th>
                            <th class="text-center">password</th>
                            <th class="text-center">gender</th>
                            <th class="text-center">action</th>
                        </tr>
                    </thread>
                    <tbody>
                        {% for foo in user_obj %}
                        	<tr>
                            <td class="text-center" >{{ foo.id }}</td>
                            <td class="text-center" >{{ foo.username }}</td>
                            <td class="text-center" >{{ foo.password }}</td>
                            <td class="text-center" >{{ foo.gender }}</td>
                            <td>
                                <a href="/edit/?id={{ foo.id }}" class="btn btn-success" style="margin-left: 65px;">修改</a>&nbsp;&nbsp;
                                <a href="/delete/?id={{ foo.pk }}" class="btn btn-danger ">删除</a>
                            </td>
                        </tr>
                        {% endfor %}

                    </tbody>
                </table>

            </div>
        </div>
    </div>
</body>
</html>

主页已经建立好了,现在我们需要配置路由文件urls.py。根据点击主页的按钮跳转的页面来配置路由。
在这里插入图片描述

路由文件urls.py配置如下:
在这里插入图片描述

如果前后端不是同一个人开发的话,这些url必须要提前规定好。
针对主页的视图函数
在这里插入图片描述


add.html:用于新增用户的数据页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">添加用户</h1>
                <hr>
                <form action="" method="post">
                    <div class="form-group">
                        username: <input type="text" class="form-control" name="username" placeholder="请输入用户名">
                    </div>

                    <div class="form-group">
                        password: <input type="password" class="form-control" name="password" placeholder="请输入密码">
                    </div>

                    <div class="form-group">
                        gender: <input type="text" class="form-control" name="gender" placeholder="请输入性别">
                    </div>

                    <div class="form-group">
                        <input type="submit" class="btn btn-block btn-success" value="提交">
                    </div>

                </form>

            </div>
        </div>
    </div>
</body>
</html>

根据上面表单的action可以看出,数据是提交到原地提交post请求的。

add页面视图函数如下:

	def add(request):
    if request.method == 'POST':  # 接收用户增加数据发送的post请求
        username = request.POST.get('username')
        password = request.POST.get('password')
        gender = request.POST.get('gender')
		
		'数据库中添加数据的'
		'操作数据库添加数据'
        add_obj=models.UserInfo.objects.create(username=username, password=password, gender=gender)
        '返回的是当前记录的对象'
		# print(add_obj) # jack
		# print(add_obj.gender) # male
		
        return redirect('/user_list/')  # 重定向到主页

    return render(request, 'add.html', locals())

当原地提交post请求的数据会被我们当前视图函数接收到,然后再写入数据库内。

此时我们就可以从主页点击添加按钮,然后输入完毕后,来检验效果:
在这里插入图片描述
在这里插入图片描述


此时已经达到了数据同步到web页面的效果了,那么我们再来尝试修改。

edit.html:修改数据的页面

<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">修改页面</h1>
                <hr>
                <form action="" method="post">
                    <div class="form-group">
                        username: <input type="text" class="form-control" name="username" value="{{ edit_obj.username }}">
                    </div>
                    <div class="form-group">
                        password: <input type="password" class="form-control" name="password" value="{{ edit_obj.password }}">
                    </div>
                    <div class="form-group">
                        gender: <input type="text" class="form-control" name="gender" value="{{ edit_obj.gender }}">
                    </div>

                    <div class="form-group">
                        <input type="submit" class="btn btn-block btn-success" value="提交">
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
</html>

修改页面的套路基本和添加数据页面差不多,观察表单的提交地址是原地址,再根据input元素的name属性值在后端接收数据。

因为我们在user_list页面内定义了,点击修改按钮,URL地址中还会携带一个用户的id编号,那么我们需要接收这个编号,再根据它来修改用户信息。

	def edit(request):
    edit_id = request.GET.get('id')  # GET可以获取URL内,问号后面的数据

    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        gender = request.POST.get('gender')
	
	'''数据库中的修改字段语法update userinfo set username='', password='' where id=1;'''
	# 第一种方式
		models.UserInfo.objects.filter(pk=edit_id).update(username=username,password=password,gender=gender)
		使用update这种语句方法不需要save保存
	
	# 第二种方式
		edit_obj = models.UserInfo.objects.filter(id=edit_id).first()  # 获取这个用户对象
		edit_obj.username = username  # 修改这个用户的姓名
		edit_obj.password = password  # 修改这个用户的密码
		edit_obj.gender = gender   # 修改性别
		edit_obj.save()  # 将修改后的数据保存到数据库
		
        return redirect('/user_list/')
    return render(request, 'edit.html', locals())

在这里插入图片描述
在这里插入图片描述


删除自然就不需要什么页面了,在主页点击后就会跳转到一个URL执行一个视图函数,并且这个URL内携带用户的编号,那么基本操作套路就是一样了。

	def delete(request):
    del_id = request.GET.get('id')
    print(del_id)
    '''数据库中删除字段语法delete from userinfo where id = 1;'''
    models.UserInfo.objects.filter(pk=del_id).delete()  # 删除数据库内,和页面传递过来相同编号的用户

    return redirect('/user_list/')  # 重定向到主页,达到一个刷新的效果

在这里插入图片描述
已经达到了我们预期的效果,点击一下删除按钮整行数据。


那么来总结一下上序所操作所用到的内容。

	1.查
		models.User.objects.filter(name=username, pwd=password)
		如何获取对象 可以使用first()方法 如果没有值会返回None 我们if判断即可
		
		obj = User.object.get(id=edit_id) # 获取一个用户对象
		print(obj.name) # 查询这个用户的name值
		
	2.增
		方法一:
		models.User.objects.create(name='jack',password=123)
		# 向数据库写入一条记录,name字段值为jack,password字段值为123
		方法二:
		obj = models.User(username=username,password=password,gender=gender)
        obj.save()
		
	3.改
		方法一:
		models.User.objects.filter(id=1).update(name='tom')
		方法二:
		obj = models.User.objects.filter(id=1).first()
		obj.name = 'tom' # 修改这个用户的name属性值
		obj.age = 18 # 修改这个用户的age属性值
		obj.save() # 将修改后的属性值,同步到数据库
		
	4.删
		models.User.objects.filter(id=1).delete()  # 在数据库内删除这个用户

	5.获取所有用户对象
		obj_all = User.object.all()
		也可以用获取局部所有变量的方法locals()
		
	6.获取指定一个对象
		obj = User.object.filter('id').first()
		'filter类比数据库中where的使用'

至此已经完成了基本操作,可以通过面向对象的形式来操作数据库里面的数据,但前提是模型类是已经存在的数据库表,如果不存在则当我们执行迁移时,Django帮助我们自动创建。


那么如果要导入已经存在的表到我们的模型里面呢。那么我们来了解一下吧!

导入已存在的表

在Django内操作数据库是通过模型models.py里面的类,而我们目前只了解怎么通过它创建数据库表,而没有了解过如何使用它导入已经存在数据库内的表。

其方式有两种:

  • 在模型内,按照表的完整数据结构创建类名、类属性,整体代码如下:
	class Book(models.Model):
    name = models.CharField(max_length=30, blank=True, null=True)
    price = models.FloatField(blank=True, null=True)
    author = models.CharField(max_length=20, blank=True, null=True)

    class Meta:
        db_table = 'book'

会发现多出来一个Meta内部类,其作用我们目前不深究,知道此时它的作用即可:通过db_table属性,指定模型类对应的数据库表名。

  • 偷懒方式:通过Django自带的命令inspectdb将数据库内的表名,生成上面这种形式:
    在这里插入图片描述
    在这里插入图片描述

为什么不执行迁移操作?因为我们并没有向模型类执行:新增表、或者新增、修改字段等操作。


ORM外键关联

		关联类型主要分为三类 跟MySQL类型一样
		一对多
			外键字段建在多的一方
		多对多
			外键字段建在第三张关系表
		一对一
			外键字段建在查询频率较高的表中
		
		ORM
			一对多
		    	外键字段建在多的一方
		    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
		   	
		 	多对多
		    	外键字段可以直接写在某张表中 orm会自动帮你创建第三张表
		    authors = models.ManyToManyField(to='Authors')
		   	一对一
		    	外键字段建在查询频率较高的表中
		    detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
		'''Django1.x版本无需写级联删除级联更新,2.x需要,此处是以2.x展示'''
		class Book(models.Model):
	    title = models.CharField(max_length=32)
	    # 书与出版社是一对多 书是多
	    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)	
	    	''' 级联删除 注意主键不需要自己去添加ID ORM会自动添加 '''
	    # 书与作者是多对多
	    authors = models.ManyToManyField(to='Authors')
	
		class Publish(models.Model):
		    pub_name = models.CharField(max_length=32)
		
		class Authors(models.Model):
		    name = models.CharField(max_length=32)
		    detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
		
		class AuthorDetail(models.Model):
		    phone = models.BigIntegerField()

Django请求的生命周期流程图

	django的生命周期是从用户发送HTTP请求数据到网站响应的过程。
	整个过程的流程包括:
	
	浏览器发送HTTE请求(通过orm) MySI获取数据->wsgiref服务>视图层一>中间件->templates模板层
	->路由层urls->视图层渲染->视图层views-> 中间件smodels模型层->响应内容给浏览器一>
	
	1.首先,用户在浏览器中输入一个url,发送一个GET方法的reguest请求。
	2.在django中有一个封装了socket的方法模块wsgiref,监听端口接受request请求,初步封装传送到中间件。
	3.由中间件传输到路由系统中进行路由分发,匹配对应的视图函数。
	4.将request请求传输到views视图函数中进行逻辑处理。
	5.调用models中表对象,通过orm操作数据库拿到数据,同时去templates中相应的模板进行渲染
	6.用response响应传输到中间件,依次处理,响应给浏览器展示给用户

在这里插入图片描述
在这里插入图片描述

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。当然我们也可以称它为:WSGI协议

而wsgiref模块就是python基于WSGI协议开发的服务模块。其支持的并发量不高,但用于我们开发环境足够了,待程序的上线再使用其他的Web服务提高我们运行程序的服务器性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1201003.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Three.js——基于原生WebGL封装运行的三维引擎

文章目录 前言一、什么是WebGL&#xff1f;二、Three.js 特性 前言 Three.js中文官网 Three.js是基于原生WebGL封装运行的三维引擎&#xff0c;在所有WebGL引擎中&#xff0c;Three.js是国内文资料最多、使用最广泛的三维引擎。既然Threejs是一款WebGL三维引擎&#xff0c;那么…

Python 使用tkinter的Scrollbar方法创建Text水平和垂直滚动条

在Python的Tkinter中&#xff0c;可以使用Scrollbar来实现Text组件的上下或左右滑动。首先&#xff0c;需要创建一个Scrollbar对象并将其与Text组件绑定&#xff0c;然后将Scrollbar放置在Text组件的右侧或底侧&#xff0c;使其能够控制Text组件的上下或左右滑动。 运行结果&am…

隔离在高可用架构中的使用

写作目的 最近看到了河北王校长隔离的视频&#xff0c;结合自己在工作中的应用&#xff0c;分享常见的隔离落地方案。 隔离落地方案 服务环境隔离 因为我们的项目服务于整个国内的多条产品线&#xff0c;也服务于国外。为了低成本所以使用一套代码。在产品线之间隔离&#…

mysql讲解2 之事务 索引 以及权限等

系列文章目录 mysql 讲解一 博客链接 点击此处即可 文章目录 系列文章目录一、事务1.1 事务的四个原则1.2 脏读 不可重复读 幻读 二、索引三,数据库用户管理四、mysql备份 一、事务 1.1 事务的四个原则 什么是事务 事务就是将一组SQL语句放在同一批次内去执行 如果一个SQ…

深入研究SVN代码检查的关键工具:svnchecker vs. SonarQube

目录 一、SVN代码检查(整合svnchecker)1、创建SVN代码库2、下载安装包3、修改SVN配置4、新建代码检查配置文件(名称自定义)5、hooks目录添加配置文件6、设置只对Java文件进行检查7、测试 二、SonarQube代码检测1、什么是SonarQube2、MySQL数据库的安装3、SonarQube服务端软件安…

Linux系统编程——修改配置文件(应用)

该应用主要调用到strstr函数&#xff0c;我们只需调用该函数并传入相关文件和修改数值即可&#xff0c;下面就是对strstr函数的定义解读以及实现案例 1.调用strstr函数需要包含以下头文件 #include<string.h>2.函数定义格式 char *strstr(char *str1, const char *str…

springboot苍穹外卖实战:十、缓存菜品(手动用redisTemplate实现缓存逻辑)+缓存套餐(Spring cache实现)

缓存菜品 缺点 缓存和数据库的数据一致性通常解决方案&#xff1a;延时双删、异步更新缓存、分布式锁。 该项目对于缓存菜品的处理较为简单&#xff0c;实际可以用管道技术提高redis的操作效率、同时cache自身有注解提供使用。 功能设计与缓存设计 建议这部分去看下原视频&…

吃透 Spring 系列—MVC部分

目录 ◆ SpringMVC简介 - SpringMVC概述 - SpringMVC快速入门 - Controller中访问容器中的Bean - SpringMVC关键组件浅析 ◆ SpringMVC的请求处理 - 请求映射路径的配置 - 请求数据的接收 - Javaweb常用对象获取 - 请求静态资源 - 注解驱动 标签 ◆ SpringMV…

【JUC】二、线程间的通信(虚假唤醒)

文章目录 0、多线程编程的步骤1、wait和notify2、synchronized下实现线程的通信&#xff08;唤醒&#xff09;3、虚假唤醒4、Lock下实现线程的通信&#xff08;唤醒&#xff09;5、线程间的定制化通信 0、多线程编程的步骤 步骤一&#xff1a;创建&#xff08;将来被共享的&am…

FD-Align论文阅读

FD-Align: Feature Discrimination Alignment for Fine-tuning Pre-Trained Models in Few-Shot Learning&#xff08;NeurIPS 2023&#xff09; 主要工作是针对微调的和之前的prompt tuining&#xff0c;adapter系列对比 Motivation&#xff1a; 通过模型对虚假关联性的鲁棒…

联想小新Pro14默认设置的问题

联想小新Pro14 锐龙版&#xff0c;Win11真的挺多不习惯的&#xff0c;默认配置都不符合一般使用习惯。 1、默认人走过自动开机。人机互动太强了&#xff1b; 2、默认短超时息屏但不锁屏&#xff0c;这体验很容易觉得卡机然后唤起&#xff0c;却又不用密码打开&#xff1b; 3…

(头哥)多表查询与子查询

目录 第1关&#xff1a;查询每个学生的选修的课程信息 第2关&#xff1a;查询选修了“数据结构”课程的学生名单 第3关&#xff1a;查询“数据结构”课程的学生成绩单 第4关&#xff1a;查询每门课程的选课人数 第5关&#xff1a;查询没有选课的学生信息 第6关&#xff1a…

Linux下C++调用python脚本实现LDAP协议通过TNLM认证连接到AD服务器

1.前言 首先要实现这个功能&#xff0c;必须先搞懂如何通过C调用python脚本文件最为关键&#xff0c;因为两者的环境不同。本质上是在 c 中启动了一个 python 解释器&#xff0c;由解释器对 python 相关的代码进行执行&#xff0c;执行完毕后释放资源。 2 模块功能 2.1python…

设计模式1

![在这里插入图片描述](https://img-blog.csdnimg.cn/c9fbecf1ae89436095885722380ea460.png)一、设计模式分类&#xff1a; 1、创建型模式&#xff1a;创建与使用分离&#xff0c;单例、原型、工厂、抽象、建造者。 2、结构型模式&#xff1a;用于描述如何将对象按某种更大的…

01-Spring中的工厂模式

工厂模式 工厂模式的三种形态: 工厂模式是解决对象创建问题的属于创建型设计模式,Spring框架底层使用了大量的工厂模式 第一种&#xff1a;简单工厂模式是工厂方法模式的一种特殊实现,简单工厂模式又叫静态工厂方法模式不属于23种设计模式之一第二种&#xff1a;工厂方法模式…

Leetcode—234.回文链表【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—234.回文链表 直接法实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ bool isPalindrome(struct ListNode* head) {if(head NULL) {return t…

【mysql】CommunicationsException: Communications link failure

CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 通信异常&#xff1a;通信链路故障 最后一个成功发送到服务器的数据包是0毫秒前…

华为ensp:ospf末梢stub完全末梢totally Stub

现在宣告都宣告完了&#xff0c;现在要给area1做完全末梢 末梢区域 进入r2系统视图模式 ospf 1area 1 stub quit进入r1系统视图 ospf 1 area 1 stub quit 现在去r1上查看 末梢成功 完全末梢 进入r2系统视图 ospf 1 area 1stub no-summary 现在就成为完全末梢了&…

YOLOv8-Seg改进: 分割小目标系列篇 | 小目标分割到大目标分割一网打尽的GFPN

🚀🚀🚀本文改进:一种新的路径融合GFPN,包含跳层与跨尺度连接,助力YOLOv8-seg Neck,实现创新 🚀🚀🚀GFPN在不同分割场景均有涨点的表现,尤其适合存在不同大小分割尺寸的场景 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,…

计算机毕业设计选题推荐-校园交流平台微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…