python---django中orm的使用(2)
1.基于对象的正向查询和反向查询
在python---django中orm的使用(1)中也提到了正向和反向查找
表:一对多 书籍和出版社
class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,default=10) def __str__(self): return self.title
class Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名称") address = models.CharField("地址", max_length=50) city = models.CharField('城市',max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name = '出版商' verbose_name_plural = verbose_name def __str__(self): return self.name
正向查询:
from blog import models def data_oper(req): obj = models.Book.objects.filter(id=2)[0] print(obj.publisher.name) print(obj.publisher.city) #正向查询,正常查找
反向查询:
from blog import models def data_oper(req): obj = models.Publisher.objects.filter(id=6)[0] print(obj.book_set.all().values("title").distinct()) #_set是一个queryset集合 #反向查找,需要加上_set
上面正向反向都是基于对象的查询
2.双下划线(__)
双下划线(__)之单表条件查询
models.Book.objects.filter(id__lt=10,id_gt=1)获取id大于1,小于10的值 and models.Book.objects.filter(id__in=[11,12,13])获取id在11,12,13中的数据 models.Book.objects.exclude(id__in=[11,12,13]) not in models.Book.objects.exclude(title__contains="ven") #contains类似于like模糊查询 models.Book.objects.exclude(title__icontains="ven") #icontains大小写不敏感
models.Book.objects.exclude(title__startwith="p")
models.Book.objects.filter(id__range=[1,10])获取在1-10之间的数据 ......像:
字段名__isnull 判断字段是否为空
双下划线(__)之关联表条件查询
一对多,多对多没有区别
正向查询 models.Book.objects.filter(title="fsa").values("publish__name") models.Book.objects.filter(publish__name="ffa出版社").values("title") 反向查询 models.Publish.objects.filter(book__title="XX书",book__id=5).values("name").distinct()
....
关联查询,表之间需要有约束,外键,或者ManyToManyField。不能随便将无关表关联
3.聚合查询 aggregate(*args,**kwargs)和分组查询annotate(*args,**kwargs)(了解)
都属于聚合函数
聚合查询是在查询结果集上进行操作,只有一个结果
分组查询是根据条件对结果进行分组,然后对应每个分组,来进行操作,有多个结果
from django.db.models import Avg,Min,Sum,Max #导入聚合函数
聚合查询aggregate:
models.Book.objects.all().aggregate(Avg("price"),Min("price"),Max("price"))
分组查询annotate:分组条件放在values中
models.Book.objects.values("authors_name").annotate(Sum("price"))#对每个作者分组
4.F和Q查询(重点)
需求引入:
将所有商品价格增加20
models.Book.objects.all().update(price="price"+20)#错误,update不能对某列进行运算,可以直接赋值 解决方法,循环每个对象,单个修改,或者迭代,或者使用F
F查询:用来对某一列值进行操作
from django.db.models import F def data_oper(req): models.Book.objects.all().update(price=F("price")+20)
models.Book.objects.all().update(price=F("title")+'tt')
Q查询:
前面filter()条件过滤,要么是单字段,或者and
Q:可以封装关键字查询,多关键字查询
from django.db.models import Q def data_oper(req): models.Book.objects.filter(id=3)[0] print(obj) #打印对象的地址(若无__str__) models.Book.objects.filter(Q(id=3)|Q(title="php"))[0] #or print(obj) models.Book.objects.filter(Q(price_gt=50) & (Q(id=3)|Q(title="php")))[0] #and和or print(obj)
models.Book.objects.filter(Q(price_gt=50) & (Q(id=3)|Q(title="php")),color="yellow")[0]
可以把Q对象和关键字查询一起使用,但是一定要把Q对象放在关键字查询前面
结果是列表,包含所有结果
或者可以使用:
q =Q() q.connector = "OR" q.children.append(('id',3)) #注意这里是元组 q.children.append(('title','php'))
models.Book.objects.filter(q)