django数据库操作-查02-F和Q对象|8月更文挑战

198 阅读2分钟

F和Q对象

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

在本指南(以及参考资料)中,我们将参考以下模型,

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField()
    number_of_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __str__(self):
        return self.headline

1 F对象

Django 提供了 F 表达式 实现这种比较。 F() 的实例充当查询中的模型字段的引用。这些引用可在查询过滤器中用于在同一模型实例中比较两个不同的字段。(Django 支持对 F() 对象进行加、减、乘、除、求余和次方)

语法如下:

F(属性名)

查出所有评论数大于 pingbacks 的博客条目

>>> from django.db.models import F
>>> Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))

评论数两倍于 pingbacks 的博客条目

>>> Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)

要找出所有评分低于 pingback 和评论总数之和的条目,修改查询条件:

>>> Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))

你也能用双下划线在 F() 对象中通过关联关系查询。带有双下划线的 F() 对象将引入访问关联对象所需的任何连接。

检索出所有作者名与博客名相同的博客,这样修改查询条件:

>>> Entry.objects.filter(authors__name=F('blog__name'))

对于 date 和 date/time 字段,你可以加上或减去一个 timedelta对象。

返回所有发布 3 天后被修改的条目:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

F() 对象通过 .bitand(), .bitor(), .bitrightshift() 和 .bitleftshift() 支持位操作。例子:

>>> F('somefield').bitand(16)

2 Q对象

如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被义在django.db.models中。

语法如下:

Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。
Q对象前可以使用~操作符,表示非not。
Q(属性名__运算符=值)

例如,该 Q 对象压缩了一个 LIKE 查询:

from django.db.models import Q
Q(question__startswith='What')

Q 对象能通过 & 和 | 操作符连接起来。当操作符被用于两个 Q 对象之间时会生成一个新的 Q 对象。

例如,该语句生成一个 Q 对象,表示两个 "question_startswith" 查询语句之间的 "OR" 关系:

Q(question__startswith='Who') | Q(question__startswith='What')

你能通过 & 和 | 操作符和括号分组,组合任意复杂度的语句。当然, Q 对象也可通过 ~ 操作符反转,允许在组合查询中组合普通查询或反向 (NOT) 查询:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

每个接受关键字参数的查询函数 (例如 filter(), exclude(), get() 也同时接受一个或多个 Q 对象作为位置(未命名的)参数。若你为查询函数提供了多个 Q 对象参数,这些参数会通过 "AND" 连接。例子:

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)