您现在的位置是: 网站首页 >Django Django
Django的F和Q查询使用方法
admin2018年11月15日 15:07 【Django 】 1159人已围观
## F查询-专门取对象中某列值的操作 > 对数据库中所有的商品,在原价格的基础上涨价10元,`F()`函数配合update可以优化效率,不再需要使用`get()`和`save()`方法 ```python from django.db.models import F from shop.models import Goods Goods.objects.update(price=F("price") + 10) # 对于Goods表中每个商品的价格都上涨10 ``` 如果没有F查询,首先要获取到原价格,然后进行计算,再更新数据。只能对对象中的某列值操作。 例如: ```python for goods in Goods.objects.all(): goods.price += 10 # 放到内存中,使用python计算,然后通过save方法保存 goods.save() ``` 或者F对单个对象操作 ```python from django.db.models import F from shop.models import Goods goods = Goods.objects.get(id=5) goods.price = F('price') + 10 goods.save() ``` 虽然看上去和上面的内存Python操作相似,但事实上这是一个描述数据库操作的sql概念 当django遇到`F()`实例,它覆盖了标准的Python运算符创建一个封装的SQL表达式。在这个例子中,`goods.price`就代表了一个指示数据库对该字段进行增量的命令。 无论`goods.price`的值是或曾是什么,Python一无所知--这完全是由数据库去处理的。所有的Python,通过Django的`F()` 类,只是去创建SQL语法参考字段和描述操作。 **`F()`函数优点:** - 直接通过数据库操作,而不是通过python操作 - 减少数据库查询次数 - 避免竞争 ### F()与聚合函数 ```pytohn class Category(models.Model): name = models.CharField(max_length=50) # ... class Article(models.Model): title = models.CharField(max_length=100) category = models.Foreignkey(Category, relate_name='articles') # ... ``` 查询某个文章非分类名称 ```python Article.objects.get(id=3).category.name # 获取到文章实例,查询到分类,再得到分类的name ``` #### Count() 查看每个分类对应下的文章数量 > 要聚合的类名.管理器名.annotate(自定义的python层面的实例字段名=聚合的方式(关联的小写模型类)) 自定义的python层面的实例字段名会作为实例的实例属性存在 ```python from django.db.models.aggregates import Count for category in Category.objects.annotate(article_num=Count('articles')): print('分类名:{},该文类文章数量{}'.format(category.name, category.article_num)) ``` #### 不同字段算术结合 用于通过将不同字段与算术相结合来在模型上创建动态字段,例如返回所有商品的价格变化 ```python all_goods = Goods.objects.annotate(diff_price=F('now_price') - F('old_price')) for goods in all_goods: print('价格变化:', goods.diff_price) ``` 但是需要注意的是如果你组合的字段是不同的类型,你需要告诉django返回什么类型的字段,django的`output_field`可以设置返回的字段类型,但是`F()`函数并不支持`output_field`字段,需要导入`ExpressionWrapper`类。下面返回值为将计算结果的浮点型改为字符串型。 ```python from django.db.models import CharField, ExpressionWrapper, F all_goods = Goods.objects.annotate(diff_price=ExpressionWrapper( F('now_price') - F('old_price'), output_field=CharField()) ) ``` ## Q查询-对对象的复杂查询 - Q查询可以组合使用 “&”, “|” 操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象, - Q对象可以用 “~” 操作符放在前面表示否定,也可允许否定与不否定形式的组合。 - Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。 ```python from django.db.models import Q from blog.models import Article Article.objects.filter(Q(id=1)) # 获取到id为1的查询集,这个查询出来是一个结果的查询集 Article.objects.filter(Q(id=1) | Q(title='python')) # id=1或title='python'的结果 Article.objects.filter(Q(click__gte=20) & Q(title__startswith='python')) # 点击数大于20,且标题以python开头的 Article.objects.filter(~Q(title='python') & Q(title__startswith='python')) # 标签不等于python,且以python开头的 Article.objects.filter(Q(title_startswith='python') | Q(title_startswith='django'), publish_time='2018-11-18')) # 以python或者django开头的标题,发布时间为2018-11-18的结果,Q对象与关键字一起使用,必须把不同关键字查询放在Q对象查询的后面 ``` ### Q的复杂查询 通过将Q对象实例化来然后增加各个条件之间的关系,而且这种写法用在你不知道用户到底会传入多少个参数的时候很方便 ```python from django.db.models import Q q1 = Q() q1.connector = 'AND' q1.children.append(('status', 'published')) q1.children.append(('author', 'admin')) # 上面等价于q1.children.append(('startus', 'published'), ('author', 'admin')) q2 = Q() q2.connector = 'AND' q2.children.append(('status', 'published')) q2.children.append(('author', 'user')) q3 = Q() q3.add(q1, 'OR') q3.add(q2, 'OR') queryset = Article.objects.filter(q3) # 查询status为published且author为admin 或者 status为published且author为user 的文章查询集 ``` ### 动态构建查询条件 ```python >>> import operator >>> q_list = [Q(text__contains = 'you'), Q(text__contains = 'who')] # OR >>> Question.objects.filter(reduce(operator.or_, q_list)) [<Question: what are you doing>, <Question: what is wrong with you>, <Question: who are you>, <Question: who am i>] # AND >>> Question.objects.filter(reduce(operator.and_, q_list)) [<Question: who are you>] ```
很赞哦! (0)
相关文章
文章交流
- emoji