zoukankan      html  css  js  c++  java
  • django的F和Q对象

    F表达式和Q表达式:

      # 示例模型如下
      class Book(models.Model):
        """图书模型"""
        name = models.CharField(max_length=300)
        pages = models.IntegerField()
        price = models.FloatField()
        rating = models.FloatField()
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
        publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

        class Meta:
          db_table = 'book'

      class Author(models.Model):
        """作者模型"""
        name = models.CharField(max_length=100)
        age = models.IntegerField()
        email = models.EmailField()

        class Meta:
          db_table = 'author'

    F表达式:
      F表达式是用来优化django的orm操作数据库的,使用F表达式时,F表达式就像是一个标记,F表达式不会立刻去提取数据库的值,他会在查询数据库的时候动态的获取F表达式中字段的值,这样的操作很明显会提高orm操作的效率,F表达式可以提取连表中的数据,此时所使用的字段形式和查询连表中的字段形式相同,会使用XXX__字段的方式。

      现在有一个需求,把图书的售价在原来的基础上增加10元,如果我们不用F表达式,那么操作应该是先从数据库中提取所有的图书售价到Python内存中,然后使用Python代码在图书售价的基础之上增加10元,最后再保存到数据库中,示例代码如下:


      books = Book.objects.all()
      for book in books:
        book.price += 10
        book.save()

      

      上面这种操作,在效率上显然不是很高,现在我们使用F表达式进行操作,示例代码如下:


      from django.db.models import F

      Book.objects.update(price=F('price')+10)
      print(connection.queries[-1]['sql'])

      原生SQL:UPDATE `book` SET `price` = (`book`.`price` + 10)


      由上面的操作,很明显的可以看出F表达式相对与常规操作的简便和高效,其实从上面的操作可以看出F表达式在执行的时候类似for循环的逐条执行,只不过这里的SQL更简单,为了说明逐条执行的特点,我们再提出一个需求,就是查询出Author模型中,name与email相同的所有作者,常规操作如下:


      authors = Author.objects.all()
      for author in authors:
      if author.name == author.email:
        print(author)

      使用F表达式操作如下:


      authors = Author.objects.filter(name=F('email')) # 注意name和email两个字段只需要在一个上使用F表达式
      for author in authors:
        print(author)

      原生SQL:SELECT `author`.`id`, `author`.`name`, `author`.`age`, `author`.`email` FROM `author` WHERE `author`.`name` = (`author`.`email`) LIMIT 21

     

      有的时候,我们需要对特定的字段做一些批量的拼接处理,例如在所有图书名称后面加上'(售)'这样的字符串,这种拼接,django的F表达式也是可以帮我们完成的,这时候需要使用Concat连接,例如在所有的图书名称后面加上'(售)'这样的字符,这样的需求我们既可以使用Concat来完成,示例代码如下:
      from django.db.models.functions inport Concat
      from django.db.models import Value

     

      Book.objects.update(name=Concat(F('name'),Value('('),Value('售'),Value(')')))
      原生SQL:UPDATE `book` SET `name` = CONCAT_WS('', `book`.`name`, CONCAT_WS('', '(', CONCAT_WS('', '售', ')')))

       注:这里使用F表达式动态的逐条获取'name'字段,然后使用Concat连接动态取出的name与其他字符串

    Q表达式:

      Q表达式通过传递字段的过滤条件,以及多个Q表达式连接使用,以实现复杂的查询操作,同时也弥补了在使用多个字段作为查询条件时无法使用或的方式。这些条件在之前博客https://www.cnblogs.com/limaomao/p/9302331.html中有具体的介绍,这里就不一一赘述了。Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    Q表达式之间可以使用 与(&)、或(|)、非(~)进行查询条件的组合,Q表达式中的非(~)弥补了过滤条件中没有不等与(没有__ne)或者不包含(没有__nc)的缺陷,Q 表达式当然也可以单独作为条件使用:

     

      1、查找出name中包含'传'字的所有图书:
      books = Book.objects.filter(Q(name__contains='传'))
      原生SQL:SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id` FROM `book` WHERE `book`.`name` LIKE BINARY '%传%' LIMIT 21

      2、查找出定价低于100并且评分低于4.5分的所有图书
      books = Book.objects.filter(Q(price__lt=100) & Q(rating__lt=4.5))

      3、查找出定价低于100或者评分低于4.5分的所有图书
      books = Book.objects.filter(Q(price__lt=100) | Q(rating__lt=4.5))

      4、获取所有name不包含'记'的图书
      books = Book.objects.filter(~Q(name__icontains='记'))

      5、获取书名包含“记”,但是id不等于3的图书
      books = Book.objects.filter(Q(name__icontains='记') & ~Q(id=3))

      6、Q对象可以与关键字参数查询一起使用,必须把普通关键字查询放到Q对象查询的后面
      Book.objects.filter(Q(price=70)|Q(title="Python"), publication_date="2017-09-26")

  • 相关阅读:
    吃透空洞卷积(Dilated Convolutions)
    CondInst:性能和速度均超越Mask RCNN的实例分割模型
    图像处理基础:颜色空间及其OpenCV实现
    caffe模型转rknn模型的方法
    探索 YOLO v3 源码
    探索 YOLO v3 源码
    事件
    组合,模板,bolck块
    WXSS学习
    其他组件
  • 原文地址:https://www.cnblogs.com/limaomao/p/9328489.html
Copyright © 2011-2022 走看看