目录
- ORM
- 常用字段
- 创建表
- 增删查改
- 表关系
- 聚合查询
- 分组查询
- F和Q
- 其他操作
ORM
ORM:对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
ORM在业务逻辑层和数据层之间充当了桥梁的作用
优点:提高了开发效率、不同数据库可以平滑切换
缺点:降低了执行效率
ORM对应关系表:
常用字段
models.AutoField(primary_key=True)
int自增列(主键id),
必须参数:primary_key=True,
当model中没有主键id时,会自动创建一个主键id
models.IntegerField()
整数字段,范围 -2147483648 to 2147483647
models.BigIntegerField()
大整数字段,范围 -9223372036854775808 ~ 9223372036854775807
models.DecimalField(max_digits, decimal_places)
小数字段,
必须参数:max_digits,表示整数部分长度,
必须参数:decimal_places,表示小数部分长度
models.CharField(max_length)
字符字段,
必须参数:max_length,表示字符串的长度
models.DateField(auto_now_add, auto_now)
日期字段,日期格式 Y-M-D,
可选参数:auto_now_add=True,自动将创建记录的时间更新到此字段,
可选参数:auto_now=True,自动将更新记录的时间更新到此字段
models.DateTimeField(auto_now_add, auto_now)
日期时间字段,格式 Y-M-D H:M[:S[.u]][TZ],
可选参数:auto_now_add=True,自动将创建记录的时间更新到此字段,
可选参数:auto_now=True,自动将更新记录的时间更新到此字段
models.BooleanField()
布尔值字段
models.TextField()
文本字段
models.EmailField()
邮箱字段
models.FileField(upload_to="文件路径", storage=None)
文件字段,
必选参数:upload_to参数指定存储文件的位置,存储的路径存到数据库里
可选参数:storage:存储组件,默认为django.core.files.storage.FileSystemStorage
models.ImageField(upload_to="文件路径", storage=None, width_field=None, height_field=None)
图片字段,upload_to参数指定存储文件的位置,存储的路径存到数据库里
可选参数:storage:存储组件,默认为django.core.files.storage.FileSystemStorage
可选参数:width_field:上传图片宽度保存的字段名
可选参数:height_field:上传图片高度保存的字段名
通用参数:
default:表示为该字段设置默认值
null:null=True,表示该字段可以为空
blank:blank=True,表示该字段可以为空,该字段与null不同,null纯粹与数据库相关,而blank与验证相关,允许表单输入空值
unique:unique=True,表示该字段必须唯一
db_index:db_index=True,表示该字段设置为索引
choices:用于指定一个二元组,组件将是一个选择框,限定选择给定的选项
verbose_name:字段的自述名
创建表
class Book(models.Model): # 创建图书表(必须是models.Model的子类)
id = models.AutoField(primary_key=True) # 创建主键id,bu
title = models.CharField(max_length=32) # 创建标题字段
price = models.DecimalField(max_digits=5, decimal_places=2) # 创建价格字段
publish = models.CharField(max_length=32) # 创建出版社字段
number = models.IntegerField() # 创建数量字段
pub_date = models.DateField(auto_now_add=True) # 创建出版日期字段
>>> python3 manage.py makemigrations app01 # 数据库迁移指令
>>> python3 manage.py migrate app01 # 数据库迁移指令
增加数据
方法一:实例化对象执行对象.save()
book_obj = models.Book(title='python', price=12.13, number=99, publish='publish_1')
book_obj.save()
方法二:objects.create()
book = models.Book.objects.create(title="django", price=1.11, number=9, publish="publish_2")
查询数据
13条表的操作方法
1、all():查询所有结果,返回一个QuerySet,类似对象列表
book_list = models.Book.objects.all()
2、filter(**kwargs):查询所有与筛选结果匹配的对象,返回一个QuerySet,类似对象列表
book_list = models.Book.objects.filter(id=1)
3、get(**kwargs):查询所有与筛选结果匹配的对象,得到的结果必须只有一个,多个或没有就好报错
book_obj = models.Book.objects.get(id=1)
4、exclude(**kwargs):查询所有与筛选条件不匹配的对象,返回一个QuerySet,类似对象列表
book_list = models.Book.objects.exclude(id=1)
5、values(*field):返回一个ValueQuerySet(特殊的QuerySet),返回的是一个可迭代的字典序列
price_list = models.Book.objects.values("price")
6、values_list(*field):与values类似,values返回的字典序列,values_list返回的是元祖序列
price_list = models.Book.objects.values_list("price")
7、order_by(*field):对查询结果排序
8、reverse(*field):将查询结果反转,只能在排过顺序后使用
9、distinct():对查询结果去重,一般和values或者values_list一起使用
10、count():返回匹配查询的对象数量
11、first():返回第一条记录
12、last():返回最后一条记录
13、exists():查询到数据就返回True,否则返回False
双下划线查询
__lt=num:小于某值
models.Book.objects.filter(id__lt=3) # 查询id小于3的值
__lte=num:小于等于某值
models.Book.objects.filter(id__lte=3) # 查询id小于等于3的值
__gt=num:大于某值
models.Book.objects.filter(id__gt=3) # 查询id大于3的值
__gte=num:大于等于某值
models.Book.objects.filter(id__gte=3) # 查询id大于等于3的值
__in=iter:在。。。里面的值
models.Book.objects.filter(id__in=[1, 2, 3]) # 查询id在list里的值
__contains=str:包含某值的值,区分大小写
models.Book.objects.filter(publish__contains='pub') # 查询含有'pub'的值,区分大小写
__icontains=str:包含某值的值,不区分大小写
models.Book.objects.filter(publish__icontains='Pub') # 查找含有'Pub'的值,不区分大小写
__range=[1, 3]:在某范围内的值
models.Book.objects.filter(id__range=[1,4]) # 查找id在1-4之间的值,顾头顾尾
__startswith=str:开头是某字符的值
models.Book.objects.filter(publish__startswith='pub') # 查询开头是'pub'的值
__endswith=str:结尾是某字符的值
models.Book.objects.filter(publish__endswith='pub') # 查询结尾是'pub'的值
__year=num:某年的值
models.Book.objects.filter(pub_date__year=2012) # 查询2012年的值
__month=num:某月的值
models.Book.objects.filter(pub_date__month=6) # 查询6月的值
__day=num:某天的值
models.Book.objects.filter(pub_date__day=12) # 查询12号的值
__week_day=num:某周的值
models.Book.objects.filter(pub_date__week_day=3) # 查询第三周的值
删除数据
方法一:对象.delete()
book = models.Book.objects.filter(pk=1).first().delete()
方法二:QuerySet.delete()
book = models.Book.objects.filter(pk=1).delete()
修改数据
方式一:对象.属性=属性值
book = models.Book.objects.filter(pk=1).first()
book.price = 200
book.save
方法二:QuerySet.update(字段名=数据)
book = models.Book.objects.filter(pk=1).update(price=200)
表关系
表与表之间的关系分为三种:一对一、一对多、多对多
外键字段
models.ForeignKey(to, to_field, on_delete, db_constraint)
外键字段,一对多,外键建在多的一方
to:设置关联的表,当参数为类名时,必须在模型类之后(惰性关系),当参数为字符串形式的类名时,则没有影响
to_field:设置关联的表的字段
on_delete:当删除关联表的数据,当前表与其关联行的行为
db_constraint:是否在数据库中创建外键约束,默认为True
models.OneToOneField(to)
外键字段,一对一,外键建在常用的一方
to:设置关联的表,,当参数为类名时,必须在模型类之后(惰性关系),当参数为字符串形式的类名时,则没有影响
models.ManyToManyField()
外键字段,多对多,外键建在常用的一方
to:设置关联的表,,当参数为类名时,必须在模型类之后(惰性关系),当参数为字符串形式的类名时,则没有影响
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField(auto_now_add=True)
publish = models.ForeignKey('Publish')
author = models.ManyToManyField('Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
phone = models.BigIntegerField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
gender_choices = ((1, 'male'), (2, 'female'), (3, 'other'))
gender = models.CharField(max_length=32, choices=gender_choices)
details = models.OneToOneField('AuthorDetails')
class AuthorDetails(models.Model):
msg = models.CharField(max_length=32)
查询数据
正向查询
对象查找:对象.外键字段.字段
book_obj = models.Book.objects.all().first()
book_obj.publish.name
字段查找:外键字段__字段
book = models.Book.objects.filter(publish__name='pub_1')
反向查询
对象查找:对象.表名_set
pub_obj = models.Publish.objects.all().first()
book_list = pub_obj.book_set.all()
titles = book_list.values_list("name")
字段查询:表名__字段
titles = models.Publish.objects.values("book__name")
操作数据
一对多
获得对象,将对象传给外键字段或将对象的主键id传给外键字段
models.Publish.objects.create(name='pub_1', addr='苏州', phone='134') # 先创建被关联表数据
pub_obj = models.Publish.objects.filter(pk=1).first() # 获得被关联表对象
book = models.Book.objects.create(name='Python', price=99.99, publish=pub_obj) # 将对象传给外键字段
多对多
create():创建一个关联对象,并自动写入数据库,且在第三张关联表中建立双方关系
models.Author.objects.first().book_set.create(name='P3', price=33.33, publish=pub_obj) # 先找到作者再为其创建图书并关联到第三张表内
add():把对象添加到第三张表内
author_list = models.Author.objects.filter(id__lt=3) # 先查询需要添加的对象
models.Book.objects.first().author.add(*author_list) # 再使用add添加关系到第三张表
set():更新某个对象在第三张表中的关联对象,不同于添加add,set相当于重置
book_obj = models.Book.objects.first().author.set(*[2, 3])
remove():从关联对象中移除指定的对象
book_obj = models.Book.objects.first().author.remove(3)
clear():从关联对象中移除一切对象
book_obj = models.Book.objects.first().author.clear()
ps:clear()和remove()只能在null=True时存在,所有方法都会马上更新数据库。
聚合查询
内置聚合函数:from django.db.models import Avg, Sum, Max, Min, Count
语法:aggregate(别名 = 聚合函数名("属性名称"))
聚合查询返回值是字典,返回的字典中:键的名称默认是(属性名称加上__聚合函数名),值是计算出来的聚合值,可以为其取别名。
res = models.Book.objects.aggregate(Avg("price"))
分组查询
分组查询一般都会用到聚合函数
语法:annotate(别名 = 聚合函数名("属性名称"))
values或values_list在分组函数前面,表示声明以什么字段分组
values或values_list在分组函数后面,表示以当前pk分组,values和values_list表示查询某些字段
res = models.Book.objects.values('name').annotate(Min('price'))
res = models.Book.objects.annotate(Count("name")).values("author__name")
F和Q
F 可以查询引用字段,比较同一个model实例两个不同字段的值
Q 可以用于条件判断,一般用于复杂的判断语句
引用:from django.db.models import F, Q
语法:F(“字段名称”)
语法:Q(条件判断)
逻辑符号 &:与,|:或,~:非,优先级从高到低:~ & |
from django.db.models import F, Q
res = models.Book.objects.filter(price__gt=F('number'))
res = models.Book.objects.filter(Q(price__gt=10)|Q(number__lt=10))
其他操作
执行原生SQL
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
开启事务
from django.db import transaction
with transaction.atomic():
事务内容
优化查询数据库
select_related:表之间进行join连表操作,一次性获取关联数据
主要针对一对多和一对一关系优化
使用sql的join语句进行优化,通过减少sql查询的次数来进行优化、提高性能
prefetch_related:使其执行多次sql查询在python代码中实现连表操作
主要针对多对多和一对多关系优化
分别查询每个表,然后用python处理他们的关系
批量插入
bulk_create(obj_list)
models.Book.objects.bulk_create(obj_list)