Django框架之ORM操作
一、选择数据库
1、默认数据库
- Django默认的数据库是sqlite3数据库
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
2、指定数据库
- 修改连接到MySQL数据库
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库名字 'NAME': "user_data", # 数据库用户名 "USER": "root", # 数据库密码 "PASSWORD": "111111", # 数据库 IP,本地默认是127.0.0.1/localhost "HOST": "127.0.0.1", # 数据库端口 "PORT": 3306, # 数据库编码 "CHARSET": "utf8mb4", } }
3、指定MySQL数据库报错
django 默认使用mysqldb模块链接mysql,但是该模块的兼容性不好,需要手动修改为pymysql链接
(1)解决办法一:猴子补丁
- 在项目下的
__init__
或者任意的应用名下的__init__
文件中书写一下代码
import pymysql pymysql.install_as_MySQLdb()
(2)解决办法二:下载第三方模块
- 直接安装
pip install mysqlclient
- 运气好不会报错,但是运气不好就会报错
- 报错的话下载whl文件
- https://pypi.org/project/mysqlclient/#files
- 下载对应的whl版本文件并安装
pip install pip mysqlclient-2.2.4-cp310-cp310-win_amd64.whl
二、连接数据库
首先如下图,点击Database
第二步,如下图
第三步,填写相关信息
第四步,不要着急确定,先点击Test Connection,看看是否能够连接成功
最后,点击OK连接数据库成功
三、ORM介绍
1、什么是ORM
ORM(Object-Relational Mapping)是一种编程技术,用于在关系型数据库和面向对象编程语言之间建立映射关系,从而实现数据的持久化和操作。ORM工具可以将数据库中的表和记录映射到编程语言中的对象和属性,使开发人员可以使用面向对象的方式来操作数据库,而无需直接编写SQL语句。
简单来说,就是
- 数据库中的表映射为Python中的类
- 数据库中的字段映射为Python中的属性
- 数据库中的记录映射为Python中的实例
2、使用Django ORM的好处
Django ORM(Object-Relational Mapping)是Django框架内置的ORM工具,用于简化与数据库的交互和操作。以下是使用Django ORM的一些优点:
-
简单易用:Django ORM提供了简单易用的API,使开发人员能够使用Python对象来表示数据库表和记录,从而减少了编写SQL语句的需要。
-
自动化数据库表创建:通过定义Django模型类,Django ORM可以自动创建对应的数据库表结构,无需手动编写SQL语句创建表。
-
数据关系管理:Django ORM支持定义数据之间的关系,如一对多、多对多等关系,开发人员可以轻松地处理复杂的数据关系。
-
查询表达式:Django ORM提供了丰富的查询表达式和方法,使开发人员能够轻松地执行各种复杂的数据库查询操作,如过滤、排序、分组等。
-
事务支持:Django ORM提供了事务管理的功能,确保数据库操作的原子性和一致性,避免数据不一致的情况发生。
-
性能优化:Django ORM提供了查询优化的功能,可以通过使用索引、延迟加载等技术来提高查询性能。
-
跨数据库支持:Django ORM支持多种数据库后端,开发人员可以在不同的数据库系统之间切换而无需修改大部分代码。
-
安全性:Django ORM可以防止SQL注入攻击,因为它会自动转义用户输入的数据,从而提高应用程序的安全性。
-
可扩展性:Django ORM支持自定义查询集、管理器和查询表达式,开发人员可以根据需要扩展其功能。
总的来说,Django ORM简化了与数据库的交互,提高了开发效率,同时提供了丰富的功能和性能优化选项,使开发人员能够更轻松地构建功能强大的Web应用程序。
四、ORM操作之建表
1、定义模型表
- 应用下面的models.py文件
- 数据库中的表映射为Python中的类
class User(models.Model): """ 数据库中的字段映射为Python中的属性 定义一个用户名 : 字符串类型 长度 MySQL中字符串类型的字段 : char varchar(32) CharField :字符串类型的字段 max_length :最大长度 verbose_name : 注释 help_text : 解释 """ # username varchar(32) username = models.CharField(max_length=32, verbose_name="用户名", help_text="这是一个用户名字段") password = models.CharField(max_length=32) # IntegerField : 相当于MySQL中的 int 字段 age = models.IntegerField() # FloatField : 相当于MySQL数据库中的 float 字段 salary = models.FloatField()
2、数据库迁移
(1)命令行输入,生成迁移文件
python manage.py makemigrations
(2)迁移记录生效,同步到数据库中
python manage.py migrate
(3)注意事项
只要你修改了models.py中跟数据库中相关的代码,就必须重新执行上述的两条命令。
由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段,所以ORM在当你不定义主键字段的时候,ORM会自动帮你创建一个名为id的主键字段,但是如果需要额外的叫法例如uid,aid等等,那么就需要自己手动去创建了
(4)补充
pycharm帮助我们偷懒的办法,直接点击下方按钮
然后直接输入makemigrations和migrate即可
最后我们在Database上就能看见各种表了
五、ORM操作之字段操作
1、字段的增加
要在 Django 模型表中增加新的字段,只需在相应的 Model 类中添加新字段及其类型和所需属性。
(1) 可以在终端内直接给出默认值 (2) 设置该字段可以为空 info = models.CharField(max_length=32,verbose_name='个人简介',null=True) (3) 直接给字段设置默认值 hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')
2、 字段的修改
直接修改代码然后执行数据库迁移的两条命令即可
python manage.py makemigrations python manage.py migrate
3、字段的删除
直接注释对应的字段然后执行数据库迁移的两条命令即可,但是执行完之后字段对应的数据也都没有了
所以在操作models.py的时候一定要注意:
千万不要轻易的注释一些字段,执行迁移命令之前最好先检查一下自己写的代码
六、ORM操作之数据操作
1、数据增加
(1)方式一
res = models.User.objects.create(username="张三",password=123456) # res 就是当前被创建的对象本身
(2)方式二
user_obj = models.User(username=username,password=password) user_obj.save() # 保存数据
2、数据查询
(1)获取全部数据的方式
模型表名.objects.all()
(2)获取特定数据的方式
filter括号内可以携带多个参数,参数与参数之间默认是and关系,可以把filter联想成where记忆
# 方式一 模型表名.objects.get(筛选字段名=筛选字段值) # 方式二 res = models.User.objects.filter(username="张三") print(res) # # <QuerySet [<User: User object (1)>]> [数据对象1,数据对象2,...] user_obj = res[0] """ 返回值可以先看成事列表套数据对象的格式。 它支持索引取值,切片操作,但是不支持负数索引;但是它不推荐你使用索引的方式取值 user_obj = models.User.objects.filter(username=username).first() """
(3)去除指定条件后的数据
模型表名.objects.exclude(筛选字段名=筛选字段值)
(4)示例
# 获取表中所有数据 all_records = MyModel.objects.all() # 根据特定条件筛选数据(方式一) filtered_records = MyModel.objects.get(name="张三") # 根据特定条件筛选数据(方式二) # 查询包含"张"的所有name filtered_records = MyModel.objects.filter(name__contains="张") # 去除满足指定条件的数据 # 过滤掉所有年龄小于18岁的记录 excluded_records = MyModel.objects.exclude(age__lt=18)
(5)补充
.filter() 过滤-->Queryset对象 .first() .last()-->获取用户对象 .get() 直接拿到的就是用户对象
3、数据修改
(1)先查询直接修改
- 推荐使用
模型表名.objects.filter(筛选字段名=筛选字段值).update(修改字段名=修改字段值)
(2)先查询后,再修改,最后保存
obj = 模型表名.objects.get(筛选字段名=筛选字段值) obj.修改字段名=修改字段值 obj.save()
(3)示例
# 点击编辑按钮朝后端发送编辑数据的请求 """ 如何告诉后端用户想要编辑哪条数据? 将编辑按钮所在的哪一行数据的主键值发送给后端 利用url问号后面携带参数的方式 """ def edit_user(request): # 获取url后面的参数 edit_id = request.GET.get('user_id') # 查询当前用户想要编辑的数据对象 edit_obj = models.User.objects.filter(id=edit_id).first() if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') # 去数据库中修改对应的数据内容 # 修改方式1 models.User.objects.filter(id=edit_id).update(username=username,password=password) """ 将filter查询出来的列表中所有的对象全部更新 批量更新操作 只修改被修改的字段,推荐使用 """ # 修改方式2 edit_obj.username = username edit_obj.password = password edit_obj.save() """ 上述方法当字段特别多的时候效率会非常的低 因为它是从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改 """ # 跳转到数据的展示页面 return redirect('/user_list/') # 将数据对象展示到页面上 return render(request,"05 edit_user.html",locals())
4、数据删除
(1)先查询直接删除
模型表名.objects.filter(筛选字段名=筛选字段值).delete()
(2)先查询再删除
instance_to_delete = MyModel.objects.get(筛选字段名=筛选字段值) instance_to_delete.delete()
(3)示例
# 删除满足特定条件的记录,通常先通过查询获取对象实例再调用 .delete() 方法 instance_to_delete = MyModel.objects.get(name="张三") instance_to_delete.delete() # 可以使用 .filter() 方法批量删除 MyModel.objects.filter(name="李四").delete() # 删除所有名字为"李四"的记录
(4)了解
删除数据内部其实并不是真正的删除,我们会给数据添加一个标识字段用来表示当前数据是否被删除了,如果数据被删了仅仅只是将字段修改了一个状态
七、Django ORM中如何创建表关系
1、表与表之间的关系
-
一对多
-
多对多
-
一对一
判断表关系的方法:换位思考
2、创建表关系
- 思路:先将基表创建出来,然后再添加外键字段
- 思考:ORM中如何定义三种关系?
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
其中ForeignKey、OneToOneField会自动在字段后面加_id后缀,还需要手动加上 on_delete=models.CASCADE 来标识级联更新和删除(Django1.x版本不需要手动添加)
from django.db import models class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) # 总共8位,小数点后面占2位 """ 图书和出版社是一对多,并且书是多的一方,所以外键字段放在书表里面 """ publish = models.ForeignKey(to='Publish') # to_field不写默认就是与出版社表的主键字段做外键关联 """ 如果字段对应的是ForeignKey,那么ORM会自动在字段的后面加_id 如果你自己加了_id,那么ORM还是会在后面继续加_id 因此后面在定义ForeignKey的时候就不要自己加_id """ """ 图书和作者是多对多的关系,外键字段建在任意一方均可,但是推荐你建在查询频率较高的一方 """ authors = models.ManyToManyField(to='Author') """ authors是一个虚拟字段,主要是用来告诉ORM,书籍表和作者表是多对多关系 让ORM自动帮你创建第三张关系表 """ class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() """ 作者与作者详情是一对一的关系,外键字段建在任意一方均可,但是推荐你建在查询频率较高的一方 """ author_detail = models.OneToOneField(to='AuthorDetail') """ OneToOneField也会自动给字段加_id后缀 """ class AuthorDetail(models.Model): phone = models.BigIntegerField() # 或者直接用字符类型 addr = models.CharField(max_length=32)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY