python-django框架ORM研究继续
ORM回顾
1,ORM常用的字段和属性,
AutoField(primary_key=True)
CharField(max_length=20)
intgerField()
DateField()
DateTimeField()
auto_now_add,----每次新增的时候添加时间为当前时间,
auto_add----每次修改的时候更改时间,
2,关系字段
ForeignKey(to=‘表名’,ralated_name='xx')------一对多,通常设置在多的那一边,
ManyToMany(to=‘表名’) ---多对多,通常是放在正向查询多的那一边,比如书和作者,把多对多放到了书的这边,因为根据书查作者比较多,
3,ORM一般操作
必知必会13条,
返回queryset对象的:
all()
filter()
values()返回一个字典
values_list()返回一个元组
exclude() 不包含
order_by()
reserve() 反转
distinct()
返回具体对象的
get()
first()
last()
----------
exist() 返回布尔
count()返回数量
4,单表查询下划线问题,
5,外键的跨表查询
正向查找,
基于对象
book_obj=models.Book.objects.get(id=1)
book_obj.publisher.name
基于下划线的,
book_obj=models.Book.objdects.filter(id=1).values("publisher__name")
反向查找
基于对象
publisher_obj=models.Publisher.objects.get(id=1)
publisher_obj.book_set.all()
如果在外键中设置了related_name=books
publisher_obj.books.all()
基于下划线的,
models.Publisher.objects.filter(id=1).values('book_title')
如果在外键中设置了related_name=books
models.Publisher.objects.filter(id=1).values("books_title")
6,分组和聚合,
聚合
models.Book.objects.all().aggregate(price_avg=Avg('price'))
分组:
models.Book.objects.all.annotate(author_num=Count('author'))
根据书分组,然后计算每一本书的作者的数量,
5,F和Q
F查询,字段和字段需要比较的时候需要用到F查询,
models.Book.objects.filter(inventory_num__gt=F('sales_num'))
Q查询
查询条件或的时候,使用Q查询,因为默认的filter都是且的关系,
6,事务,原子操作,
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup()
import datetime
from app01 import models
try:
from django.db import transaction #导入一个transaction
with transaction.atomic(): #atomic原子,下面的语句要么都成功,要么都不成功,这样就可以了,这就是事务,
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
except Exception as e:
print(str(e))
7,执行原生的sql语句,
#执行原生的sql
ret = models.Book.objects.raw('select * from app01_book')
for i in ret:
print(i)
####################################################
orm一对一
detail=models.OneToOneField(to='AuthorDetail')
#一个作者对应一个作者详情,
#为什么这么做,因为作者表用的非常的频繁,每一次查的时候都要全表查,数据量大,但是用到的字段不多,
#所以把常用的字段抽离出来,
#比如列表页和详情页,这些都是需要分离的,为了更快的查询,
# orm多对多的三种方式
#多对多的方式
# 1,orm自动帮我创建第三张表,书和作者之间的第三张表就是自动创建的,
# 2,自己创建第三张表,利用外键分别关联作者和书,查询比较麻烦
# 3,自己创建第三张表,使用orm的manyTomanyField,制定一下,
# book=models.ManyToManyField(to='book',through='Author2Book',through_fields=("author","book"))
#第三种的查询方式和第一种的查询方式一样的,因为已经做了关联了,
# 我们使用第几种,
# 我们使用第几种,
#如果第三张表没有额外的字段,就使用第一种方法,
#如果第三张表有额外的字段,这种可以使用第三种方法和第一种方法,
# 比如相亲网站,一个男的可以联系多个女的,一个女的也可以联系多个男的,这就是多对多的,
#约会记录,多对多,这个表的结构,
#id boy_id girl_id date 约会时间,
#这种add() remove() 就没有了,
# 举例:
# 从作者关联的书里面移除id是1的书
# 之前使用第一种方法的时候是:
# models.Author.objects.get(id=1).book.remove(1)
# 现在自己建第三张表,就不能使用这种方式了,
# models.Author2Book.objects.get(author_id=1,book_id=1).delete()
#在app01里面查询id=1的作者关联的书,
# author_obj=models.Author.objects.get(id=4)
# ret=author_obj.book.all()
# print(ret)
#在app02里面查询id=1的作者关联的书,
# author_obj=models.Author.objects.get(id=4)
# ret=author_obj.book.all()
# print(ret)
#如果是你自己创建的第三张表,就不能使用这种方法了,因为里面没有book这个属性啊,
#怎么拿?
#先拿到作者为1的数据,在关联表
ret=models.Author2Book.objects.filter(author_id=4).values_list('book_id')
print(ret)#<QuerySet [(4,), (5,)]>
ret=[i[0] for i in ret] #看来列表推导式还是需要研究一下
ret=models.Book.objects.filter(id__in=ret)
print(ret)
#所以这种自己建立第三张表是比较麻烦的,