[Django]查询表达式

作者: alue | 来源:发表于2021-05-02 13:52 被阅读0次

    作为一个全栈开发工程师,我最喜欢Django框架中的ORM和Admin,很大程度上提升了开发效率。
    其中,ORM虽然很好上手,但想要高效的操作数据库,还是需要很多经验的。善于使用查询表达式(Query Expressions)就是很重要的一个技能。
    Django自带的查询表达式有

    # 1. F() 能够在数据库层面操作,减少读入内存的损耗
    from django.db.models import F
    
    reporter = Reporters.objects.get(name='Tintin')
    reporter.stories_filed = F('stories_filed') + 1
    reporter.save()
    
    
    # 2. Func() 能够使用数据库函数
    queryset.annotate(field_lower=Func(F('field'), function='LOWER'))
    
    # 3. Aggregate()是一些聚合函数的基础,标志着查询带有GROUP BY语句,例如Count(),Max()
    Aggregate()
    
    # 4. 最小表达单元. 将python数据转换为数据库表达式。当书写F('field') + 1时,Django会自动将1改为Value(1)
    Value()
    # 5. ExpressionWrapper()用于表达式的嵌套;下面是一个实战案例,加权求和的高效算法
    queryset.annotate(
                hours_x_number=ExpressionWrapper(
                    F("hours") * F("number"),
                    output_field=FloatField()
                )
            ).aggregate(
                total_hours_x_number=Sum('hours_x_number')
            )["total_hours_x_number"]
    
    # 6. Subquery()提供一种更清晰的表达式
    newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
    Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
    

    提供一个Value()表达式在实战中的应用

    打算将模型两个字段拼接成一个并输出,拼接规则是(字段1)字段2,即字段1需要先用括号括起来。

    常规的做法,先将数据库字段读到内存中,然后再用Python拼接,这样耗时较长。
    进阶的做法是利用查询表达式Value():

    queryset.annotate(
                    combined_fields=Concat(
                        Value(' ('),
                        'field1',
                        Value(')'),
                        "field2",
                        output_field=CharField()
                    )).
    

    这样,操作直接在数据库层面完成,效率大增。

    计算一个模型中两个字段乘积的总和

    常规做法,利用for循环,在python内存中累加。
    进阶做法,利用ExpressionWrapper和F,在数据库中完成.

    queryset.annotate(
                hours_x_number=ExpressionWrapper(
                    F("hours") * F("number"),
                    output_field=FloatField()
                )
            ).aggregate(
                total_hours_x_number=Sum('hours_x_number')
            )["total_hours_x_number"]
    

    相关文章

      网友评论

        本文标题:[Django]查询表达式

        本文链接:https://www.haomeiwen.com/subject/soefdltx.html