ORM简介
- MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
创建表
在项目下的models.py中创建模型:
class Seat(models.Model):
name = models.CharField(max_length=10)
class Meta:
db_table = "stat" # 指定表名
ordering = ['id'] # 设置排序方式
class Grand(models.Model):
names = models.CharField(max_length=10)
class Meta:
db_table = "grand" # 指定表
ordering = ['id'] #设置排序方式
class Uid(models.Model):
uid = models.IntegerField()
# 一对一关系
stu = models.OneToOneField(to="Student",on_delete=models.CASCADE)
#完整写法
stu =models.OneToOneField(to="Student",to_field="id",on_delete=models.CASCADE)
# to="sex" 指定表名
# to_field="id" 指定列名
# on_delete=models.CASCADE 设置级联删除
sex = ((1,男),(2,女))
class Student(models.Model):
name = models.CharField(max_length=10)
sex = models.IntegerField(choices=sex)
# 页面展示可以使用{{ foo.get_sex_display }}
sex = models.OneToOneField("Sex", on_delete=models.CASCADE)
# 一对多关系
grand = models.ForeignKey(to="Grand", on_delete=models.CASCADE)
# 多对多关系
# 多对多关系会生成第三张表
seat = models.ManyToManyField("Seat")
class Meta:
db_table = "student" # 指定表名
ordering = ['id'] #设置排序方式
表关系:
- OneToOneField:一对一关系
- ForeignKey:多对一关系(一对多)
- ManyToManyField:多对多关系
常见字段
-
CharField
字符串字段,必须要有一个参数maxlenght,用于指定该字段最大长度
-
IntegerField
保存一个整数
-
DecimalField
浮点数,必须提供两个参数,max_digits(总位数)和decimal_place(小数位数),总位数要大于小数位数
-
AutoField
类似于IntegerField,在添加记录时会自动增长,如果没有手动指定主键,系统会自动添加一个主键
-
TextField
容量很大的文本字段
-
EmailField
一个可以检测Email是否合法的CharField
-
DateField
日期字段
-
DateTimeField
日期时间字段
-
ImgeField
文件字段,检验上传对象是否是一个合法图片,当指定heigth_field和width_field时这个图片会按照提供的宽高进行保存
-
FileField
文件上传字段
orm字段与数据库实际字段的关系表
orm字段 | 数据库实际字段 |
---|---|
AutoField | integer AUTO_INCREMENT |
BigAutoField | bigint AUTO_INCREMENT |
BinaryField | longblob |
BooleanField | bool |
CharField | varchar(%(max_length)s) |
CommaSeparatedIntegerField | varchar(%(max_length)s) |
DateField | date |
DateTimeField | datetime |
DecimalField | numeric(%(max_digits)s, %(decimal_places)s) |
DurationField | bigint |
FileField | varchar(%(max_length)s) |
FilePathField | varchar(%(max_length)s) |
FloatField | double precision |
IntegerField | integer |
BigIntegerField | bigint |
IPAddressField | char(15) |
GenericIPAddressField | char(39) |
NullBooleanField | bool |
OneToOneField | integer |
PositiveIntegerField | integer UNSIGNED |
PositiveSmallIntegerField | smallint UNSIGNED |
SlugField | varchar(%(max_length)s) |
SmallIntegerField | smallint |
TextField | longtext |
TimeField | time |
UUIDField | char(32) |
参数补充
-
null
默认为False,设置为True时,将用Null在数据库中存储空值
-
blank
默认为False,设置为True时,该字段允许不填
-
default
默认值
-
primary_key
设置为True时,就是将这个字段设置为主键。如果未设置主键Django会自动添加一个主键
-
unique
设置为True时,表示该字段是唯一的
-
db_index
设置为True时,表示为该字段设置数据库索引
-
级联删除
on_delete=models.CASCADE
表记录的增删改查
增加
单表增加
方式一:
from app1 import models
def index(request):
obj = models.UserInfo(id = 1,name="张三",sex=1,birthday="2000-11-12")
obj.save() # 翻译成sql语句,然后由pymysql发送到服务端
return HttpResponse("123")
方式二:
from app1 import models
def index(request):
ret = models.UserInfo.object.creat(id = 1,name="张三",sex=1,birthday="2000-11-12")
print(ret) # 得到一个model对象
print(ret.name)
return HttpResponse("123")
批量添加
book_list = []
for i in range(10):
bk_obj = models.Book(name='张%s'%i,addr='北京%s'%i)
book_list.append(bk_obj)
models.Book.objects.bulk_create(book_list) #批量插入,速度快
多表添加
一对一关系
sea = models.Seat.objects.filter(name="座位2").first() # 查询座位2对应的对象
obj = models.Student.objects.create(
grade_id=1, # 第一种方式,通过表字段名直接设置值
seat=sea # 第二种方式,通过模型内变量名赋值一个对象
)
多对多关系
obj = models.Student.objects.get(pk=1)
# 方式一:通过给定值方式添加
obj.teacher.add(*[1,1])
obj.teacher.add(1,1)
# 方式二:通过给定对象方式添加
obj.teacher.add(对象1,对象2)
obj.teacher.add(*[对象1,对象2])
删除
单表删除
models.UserInfo.objects.filter(id=1).delete() # 由queryset对象调用delete
models.UserInfo.objects.filter(id=1)[0].delete() # 由model对象调用delete
多表删除
一对一关系
models.Seat.objects.filter(name="座位1").delete()
一对多关系
models.Grade.objects.filter(name="座位2").delete()
多对多关系
# models无法控制多对多关系生成的第三张表,需要通过使用含有关系列的对象进行调用
obj = models.Student.objects.get(id=1)
obj.teacher.remove(1) # 删除关系表中学生id为1,教师id为1的数据不影响其他表,
obj.teacher.clear() # 清空所有学生id为1的数据
obj.teacher.set([1,2]) # 先清空再加入
修改
单表修改
models.UserInfo.objects.filter(id=1).update(id = 2, name = "李四",sex = "女")
# model对象不能调用update方法通过返回的对象进行修改
ret = models.UserInfo.objects.filter(id=1)[0]
ret.name = "李四"
ret.sex = "女"
多表修改
models.Student.objects.filter(pk=3).update(
name = "李四",
grade_id = 2,
seat_id = 1)
# 修改多对多关系生成第三张表时可以借用多表删除中的set方法
查找
单表查找
models.UserInfo.objects.all()
常见查找方法:
-
all
查找全部,结果为queryset类型models.UserInfo.objects.all() # 结果: <QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>, <Student: Student]>
-
filter
条件查询,如果查找不到数据时不会报错,返回一个空的queryset,<QuerySet []>,如果没有查询条件会查询全部数据,queryset类型数据可以继续调用filter
models.Student.objects.filter(sex=1,name="张1")
-
get
get可以得到且只能得到一个model对象,当查不到数据时会报错,查询结果多余一个时也会报错
models.Student.objects.get(name="张三")
-
exclude
排除匹配的项object和quereyset类型数据都能进行调用
models.Student.objects.exclude(name="张三") models.Student.objects.all().exclude(name="张三")
-
order_by
排序
models.Student.objects.all().order_by("id") # 正序 models.Student.objects.all().order_by("-id") # 倒序 models.Student.objects.all().order_by("-id","price") # 先按id排序如果id相同再按price排序 models.Student.objects.all().order_by("id").reverse() # 反转排序结果,需要先排序
-
count
计数,返回结果的数量
models.Student.objects.all().count()
-
first
获取查询结果中的第一条数据,得到一个model对象
models.Student.objects.all().first()
-
last
获取查询结果中的最后一条条数据,得到一个model对象
models.Student.objects.all().last()
-
exists
判断返回结果有无数据,得到布尔类型
models.Student.objects.filter(id="999").exists()
-
values
返回queryset类型,其中数据是字典类型
models.Student.objects.all().values() '''结果 <QuerySet [{'id': 1, 'name': '张三', 'sex': 1, 'grand': 1, 'seat': 1}, {'id': 2, 'name': '张1', 'sex': 1, 'grand': 1, 'seat': 1}] '''
-
values_list
返回queryset类型,其中数据是数组类型
models.Student.objects.all().values_list() '''结果 <QuerySet [(1, '张三', 1, 1, 1), (2, '张1', 1, 1, 1)] '''
-
distinct
去重,需要配合values或values_list使用
models.Student.objects.all().values("sex")
filter双下划线查询:
-
gt
大于
models.Student.objects.filter(id__gt=4)
-
gte
大于等于
models.Student.objects.filter(id__gte=4)
-
lt
小于
models.Student.objects.filter(id__lt=4)
-
lte
小于等于
models.Student.objects.filter(id__lte=4)
-
range
区间,大于第一个值小于第二个值
models.Student.objects.filter(id__range=[3,6])
-
contains
模糊查询,匹配所有指定列包含指定值的数据
models.Student.objects.filter(name__contains="张")
-
icontains
不区分大小写查找
models.Student.objects.filter(name__icontains="ab")
-
startswitch
匹配以什么开头
models.Student.objects.filter(name__startswith="张")
-
date
匹配日期
models.Student.objects.filter(publish_date="2000-01-01")
匹配指定年、月、日
models.Book.objects.filter(publish_date__year='2019',publish_date__month='8',publish_date__day='1')
-
isnull
匹配指定字段为空的数据
models.Book.objects.filter(hoby__isnull=True)
跨表查找
obj = models.Student.objects.filter(id=3)[0]
print(obj.seat.name) # 正向查询
obj = models.Seat.objects.filter(name="座位4")[0]
print(obj.student.name) # 逆向查询
obj = models.Grade.objects.filter(id=2)[0]
print(obj.student_set.all()) # 值为多个时使用_set标注
基于双下划线的跨表查询
一对多关系
# 正向查询 按字段:press
obj = models.Book.objects.filter(press__name="黄山书社").values("name")
# 反向查询 按表名:book
obj = models.Press.objects.filter(name="黄山书社").values("book__name")
多对多关系
# 正向查询
obj = models.Book.objects.filter(name="论语").values("writer__name")
# 逆向查询
obj = models.Writer.objects.filter(book__name="论语").values("name")
一对一关系
# 正向查询
ret=Author.objects.filter(name="王五").values("authordetail__telephone")
# 反向查询
ret=AuthorDetail.objects.filter(author__name="yuan").values("telephone")
聚合查询
from django.db.models import Avg, Sum, Max, Min, Count
obj = models.Book.objects.all().aggregate(a=Max("price"),m=Min("price"))
分组查询
obj = models.Book.objects.values("press_id").annotate(a=Avg("price")) # 通过book表的press_id查询
obj = models.Book.objects.values("press__id").annotate(a=Avg("price")) # 通过press表的id查询
obj = models.Press.objects.annotate(a=Avg("book__price")).values("name","a") # 反向查询
F查询
from django.db.models import F
# 查询评论数大于喜欢数的书
obj = models.Book.objects.filter(comment__gt=F("like"))
for i in obj:
print(i.name)
# 每本书价格加100
obj = models.Book.objects.all().update(
price=F("price")+100
)
Q查询
obj = models.Book.objects.filter(Q(like__gt=10)&Q(comment__lt=900)).values("name") # 与
obj = models.Book.objects.filter(Q(like__gt=10)|Q(comment__lt=900)).values("name") # 或
obj = models.Book.objects.filter(~Q(like__gt=10)).values("name") # 非
动态q查询条件
q = Q()
for product_model_id in product_model_ids:
q.add(Q(product_model_id=product_model_id), Q.OR)
business_visit = models.BusinessDaily.objects.filter(q)
执行原生sql
models.Book.object.raw('select * from Book')
锁
models.Book.objects.select_for_update().filter(id=1)