Django之ORM操作
目录
- 双下划线查询
- 数据准备
- 具体操作
- orm创建外键关系
- 外键字段的增删改查
- 正反向的概念
- 正向
- 反向
- 多表查询
- 基于对象的跨表查询
- 基于双下划线的跨表查询
- 双下线查询扩展
- 如何查看SQL语句
- 方式1:句点符加query查看
- 方式2:配置文件固定配置
双下划线查询
数据准备
class Staff(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
salary = models.DecimalField(max_digits=8, decimal_places=2)
recruit_time = models.DateField(auto_now=True)
def __str__(self):
return "%s-对象" % self.name
models.Staff.objects.create(name='linda', age=22, salary=25000.00)
models.Staff.objects.create(name='rose', age=24, salary=15000.00)
models.Staff.objects.create(name='frank', age=32, salary=35000.00)
models.Staff.objects.create(name='laurence', age=24, salary=25000.00)
models.Staff.objects.create(name='steve', age=42, salary=15000.00)
models.Staff.objects.create(name='july', age=32, salary=35000.00)
models.Staff.objects.create(name='sam', age=27, salary=42000.00)
models.Staff.objects.create(name='tom', age=33, salary=28000.00)
models.Staff.objects.create(name='Simon', age=43, salary=45000.00)
具体操作
# 一、查询年龄小于等于27的员工
staff_obj = models.Staff.objects.filter(age__lte=27)
print(staff_obj)
"""
__gt 大于
__lt 小于
__gte 大于等于
__lte 小于等于
"""
# 二、查询年龄是24、32、42的员工
staff_obj = models.Staff.objects.filter(age__in=[14, 32, 42])
print(staff_obj
"""
__in 成员运算
"""
# 三、查询年龄在25到30之间的员工
staff_obj = models.Staff.objects.filter(age__range=[25, 30])
print(staff_obj)
"""
__range 范围查询
"""
# 四、查询姓名中包含字母s的员工
staff_obj = models.Staff.objects.filter(name__contains='s')
print(staff_obj) # , , ]>
staff_obj = models.Staff.objects.filter(name__icontains='s')
print(staff_obj) # , , , ]>
"""
__contains 区分大小写
__icontains 忽略大小写
"""
# 五、查询姓名中首字母为j的员工
staff_obj = models.Staff.objects.filter(name__startswith='j')
print(staff_obj) # ]>
# 六、查询姓名中尾字母为e的员工
staff_obj = models.Staff.objects.filter(name__endswith='e')
print(staff_obj) #
# 七、查询姓名中s开头m结尾的员工
staff_obj = models.Staff.objects.filter(name__regex='^s.*m$')
print(staff_obj) # ]>
# 八、查询招聘月份是5月的员工
staff_obj = models.Staff.objects.filter(recruit_time__month=5)
print(staff_obj) # , , ]>
# 九、查询招聘年份是2020年的员工
staff_obj = models.Staff.objects.filter(recruit_time__year=2020)
print(staff_obj) # , , ]>
orm创建外键关系
class Staff(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
salary = models.DecimalField(max_digits=8, decimal_places=2)
recruit_time = models.DateField(auto_now=True)
def __str__(self):
return "%s-对象" % self.name
# 图书表
class Book(models.Model):
book_title = models.CharField(max_length=64, verbose_name='图书名')
book_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='图书价格')
publish_time = models.DateField(auto_now=True, verbose_name='出版日期')
publish = models.ForeignKey(to='Press')
authors = models.ManyToManyField(to='Author')
def __str__(self):
return "%s-图书对象" % self.book_title
# 出版社表
class Press(models.Model):
press_name = models.CharField(max_length=64, verbose_name='出版社名称')
press_addr = models.CharField(max_length=64, verbose_name='出版社地址')
def __str__(self):
return "%s-出版社对象" % self.press_name
# 作者表
class Author(models.Model):
author_name = models.CharField(max_length=64, verbose_name='作者姓名')
author_age = models.IntegerField(verbose_name='作者年龄')
author_details = models.OneToOneField(to='AuthorDetail')
def __str__(self):
return "%s-作者对象" % self.author_name
# 作者详情表
class AuthorDetail(models.Model):
author_addr = models.CharField(max_length=64, verbose_name='作者地址')
author_phone = models.BigIntegerField(verbose_name='作者联系方式')
def __str__(self):
return "%s-作者详情对象" % self.author_addr
外键字段的增删改查
# 一对多、一对一外键字段操作
增
models.Book.objects.create(book_title='初中地理', book_price=29, publish_id=1)
publish_obj = models.Press.objects.filter(pk=3).first()
models.Book.objects.create(book_title='初中生物', book_price=36, publish=publish_obj)
改
res = models.Book.objects.filter(pk=5).update(publish_id=1)
print(res)
publish_obj = models.Press.objects.filter(pk=2).first()
res = models.Book.objects.filter(pk=6).update(publish_id=publish_obj)
print(res)
# 多对多字段操作
一、第三张关系表创建数据
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.add(3, 4)
book_obj = models.Book.objects.filter(pk=3).first()
author_obj = models.Author.objects.filter(pk=5).first()
book_obj.authors.add(author_obj)
注意:括号内可以放主键值也可以放数据对象,并且都支持多个
二、第三张关系表修改数据
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set([5])
注意:括号内必须是一个可迭代对象,元素同样支持主键值或者数据对象
三、第三张关系表删除数据
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(5)
注意:括号内可以放主键值也可以放数据对象并且都支持多个
四、第三张关系表清空指定数据
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.clear()
注意:括号内无需传值,直接清空当前表在第三张关系表中的绑定记录
正反向的概念
核心在于当前数据对象是否含有外键字段:有则是正向,没有则是反向
正向
eg:
由书籍查询出版社,外键字段在书籍表中,那么书查出版社就是'正向'
由书籍查询作者,外键字段在书籍表中,那么书查作者就是'正向'
由作者查询作者详情,外键字段在作者表中,那么也是'正向'
反向
eg:
由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
多表查询
基于对象的跨表查询
基于对象的跨表查询本质就是子查询即分步操作即可
# 查询初中生物书籍对应的出版社
# book_obj = models.Book.objects.filter(book_title='初中生物').first()
# res = book_obj.publish
# print(res) # 西南师范大学出版社-出版社对象
# 查询小学英语对应的作者
# book_obj = models.Book.objects.filter(book_title='小学英语').first()
# res = book_obj.authors.all()
# print(res) # , ]>
# 查询作者david的详情信息
# author_obj = models.Author.objects.filter(author_name='david').first()
# res = author_obj.author_details
# print(res) # 北京-作者详情对象
# 查询四川大学出版社出版的书籍
# publish_obj = models.Press.objects.filter(press_name='四川大学出版社').first()
# res = publish_obj.book_set.all()
# print(res) # , , ]>
# 查询朱巍编写的书籍
# author_obj = models.Author.objects.filter(author_name='朱巍').first()
# res = author_obj.book_set.all()
# print(res) # , ]>
# 查询地址在杭州的作者
# author_detail_obj = models.AuthorDetail.objects.filter(author_addr='杭州').first()
# res = author_detail_obj.author
# print(res) # 李华-作者对象
基于双下划线的跨表查询
基于双下划线的跨表查询本质就是联表操作
# 查询科学世界书籍对应的出版社名称
# res = models.Press.objects.filter(book__book_title='科学世界')
# print(res) # ]>
# res = models.Press.objects.filter(book__book_title='科学世界').values('press_name')
# print(res) #
# 查询地理探索对应的作者姓名和年龄
# res = models.Author.objects.filter(book__book_title='地理探索').values('author_name', 'author_age')
# print(res) #
# 查询作者david的联系方式和地址
# res = models.AuthorDetail.objects.filter(author__author_name='david').values('author_phone', 'author_addr')
# print(res) #
# 查询西南师范大学出版社出版的书籍名称和价格
# res = models.Book.objects.filter(publish__press_name='西南师范大学出版社').values('book_title', 'book_price')
# print(res) #
# 查询王涛编写的书籍名称和日期
# res = models.Book.objects.filter(authors__author_name='王涛').values('book_title', 'publish_time')
# print(res) #
# 查询地址在北京的作者的姓名和年龄
# res = models.Author.objects.filter(author_details__author_addr='北京').values('author_name', 'author_age')
# print(res) #
双下线查询扩展
基于双下划线的跨表查询的结果也可以是完整的数据对象
# 查询科学世界书籍对应的出版社名称
# res = models.Press.objects.filter(book__book_title='科学世界').first()
# print(res) # 四川大学出版社-出版社对象
# 查询地理探索对应的作者姓名和年龄
# res = models.Author.objects.filter(book__book_title='地理探索').values('author_name', 'author_age')
# print(res) #
# 查询作者david的联系方式和地址
# res = models.AuthorDetail.objects.filter(author__author_name='david').values('author_phone', 'author_addr')
# print(res) #
# 查询西南师范大学出版社出版的书籍名称和价格
res = models.Book.objects.filter(publish__press_name='西南师范大学出版社').values('book_title', 'book_price')
print(res) #
# 查询王涛编写的书籍名称和日期
# res = models.Book.objects.filter(authors__author_name='王涛').values('book_title', 'publish_time')
# print(res) #
# 查询地址在北京的作者的姓名和年龄
# res = models.Author.objects.filter(author_details__author_addr='北京').values('author_name', 'author_age')
# print(res) #
# 连续跨表操作
# 查询小学英语对应的作者的地址
res = models.AuthorDetail.objects.filter(author__book__book_title='小学英语').values('author_addr')
print(res) #
# 获取多张表里面的字段数据
# 查询初中数学对应的作者的地址和出版社名称
res = models.AuthorDetail.objects.filter(author__book__book_title='初中数学').values('author_addr', 'author__book__publish__press_name')
print(res) #
如何查看SQL语句
方式1:句点符加query查看
如果结果集对象是queryset可以点query查看
方式2:配置文件固定配置
只要执行了orm操作都会打印内部SQL语句
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}
}