F查询和Q查询                       

                              F查询                           

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢?

Django提供了F() 来做这样的比较.F()的示例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值.

示例1:

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F("keep_num"))

Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作.

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F('price')+30)

引申:

如果要修改char字段咋办?

如: 把所有书名后面加上(第一版)

from django.db.models.funtions import Concat
from django.db.models import Value
models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))

 

 

                                  Q查询                                 

filter()等方法中的关键字参数查询都是一起进行'AND'的,如果你需要执行更复杂的查询,你可以使用Q对象.

示例1:

查询作者名是小仙女或者小魔女的

models.Book.object.filter(Q(authors__name='小仙女')|Q(authors__name='小魔女'))

你可以组合 & 和 | 操作符号以及使用括号进行分组来编写任意复杂的Q对象.同时,Q对象可以使用符 ~ 操作符取反,着允许组合正常的查询和取反(NOT)查询.

示例: 查询作者名字是小仙女并且不是2018年出版的书的书名

models.Book.object.filter(Q(author__name='小仙女') & ~Q(publish_date__year=2018)).values_list('title')

查询函数可以混合使用Q对象和关键字参数.所有提供给查询函数的参数(关键字参数或Q对象)都将"AND"在一起,但是,如果出现Q对象,它必须位于所有关键字参数的前面.

例如:查询出版年份是2017或2018,书名中带物语的所有书.

models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date_year=2017),title__icontains='物语')

                         事务                         

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
        with transaction.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))