作为一个全栈开发工程师,我最喜欢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"]
网友评论