gpt4 book ai didi

python - Django:具有完全相同角色的属性和查询集的 DRY 代码?

转载 作者:太空宇宙 更新时间:2023-11-03 11:37:57 24 4
gpt4 key购买 nike

在我的 Django 代码中,对于 OrderedArticle 对象,我需要计算一个 hist_price,它是 2 个字段的乘积:hist_unit_price * 数量

我做的第一种方法是一个简单的属性:

class OrderedArticle(Model):
@property
def hist_price(self):
return self.hist_unit_price * self.quantity

然后,我意识到当我需要对这些价格进行大量计算时,出于性能原因我不能使用此属性,而必须在数据库级别计算 hist_price。这就是我为此编写自定义查询集的原因:

class OrderOperationQuerySet(Queryset):

@staticmethod
def _hist_price(orderable_field): # can be an OrderedArticle or another object here
return ExpressionWrapper(
F(f'{orderable_field}__hist_unit_price') * F(f'{orderable_field}__quantity'),
output_field=DecimalField())

目前,我的代码中同时使用了 hist_price 属性和 _hist_price 查询集。

问题

这很好用,但是我很烦把相同的业务逻辑写两次。我有一种感觉,我没有在这里“以正确的方式”这样做。我想我应该在代码级别确保无论我使用属性还是查询集,它总是返回相同的结果。在这个特定案例中,业务逻辑是两个小数点之间的简单乘法,所以它应该没问题,但我的代码中还有其他情况会更复杂。

您是否找到改进我的代码的方法?谢谢。

最佳答案

这个想法类似于"hybrid attributes" from SQLAlchemy asked about before - 我对该线程链的任何答案都不是非常满意(比如将此计算值存储在表的额外字段中并始终确保保持更新)。

您可以拥有一些您的属性和 ExpressionWrapper 函数都使用的内部函数,只要重载所需的运算符以接受实际值或 F() 对象(例如基本数学运算符).

def multiplication(x, y):
return x * y # trivial here but it could be any mathematical expression really


def _hist_price(orderable_field):
return ExpressionWrapper(
multiplication(
F(f"{orderable_field}__hist_unit_price"),
F(f"{orderable_field}__quantity")
),
output_field=DecimalField()
)

@property
def hist_price(self):
return multiplication(self.hist_unit_price, self.quantity)

如果它变得比这些混合函数之一中的基本数值运算更复杂,并且您想避免重复的业务逻辑,则需要编写一个包装函数,它可以使用属性调用方的 python 函数解析为正确的输出,以及可以为查询集调用者操作 F 对象以维护运算符重载的函数。但这将导致代码反省参数以找出要做什么,这可能不直观,因此这实际上是一种权衡。

在粗略的伪代码中,这些自定义函数之一就像

def _hybrid_lower(value):
if isinstance(value, F): # maybe F would be sufficient or some other class higher in the hierarchy
# https://docs.djangoproject.com/en/2.2/ref/models/expressions/#func-expressions
return Func(value, function='LOWER')
else:
return value.lower()

然后您可以在属性和查询集都调用的函数中使用这个自定义函数。如果您确实开始需要数据库操作和 Python 等非常复杂的功能,那么一些重复代码可能并不是最糟糕的权衡。

关于python - Django:具有完全相同角色的属性和查询集的 DRY 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55687358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com