请参考下面的代码
交易模型
class Transaction(models.Model)
current_product_code = models.CharField(....)
previous_product_code = models.CharField(....)
@property
def status(self):
c_price = Product.objects.get(code=self.current_product_code).price
p_price = Product.objects.get(code=self.previous_product_code).price
if c_price == p_price:
return "Due"
elif c_price > p_price:
return "Upgrade"
else:
return "Downgrade"
产品型号
class Product(models.Model):
code = models.CharField(....)
price = models.DecimalField(....)
我的问题:我如何获取/过滤具有升级/降级/到期状态的交易。我正在尝试创建一个自定义管理员过滤器,该过滤器根据其状态过滤事务,但是我无法放入.filter()里面的内容,请检查下面的方法
def queryset(self, request, queryset):
value = self.value()
if value == 'Upgrade':
return queryset.filter(***** HERE *****)
elif value == 'Downgrade':
return queryset.filter(***** HERE *****)
elif value == 'Unknown':
return queryset.filter(***** HERE *****)
return queryset
答案 0 :(得分:2)
您确实应该在ForeignKey
和Product
之间使用Transaction
(对于current_product_code
和previous_product_code
两者)。这将使您可以轻松地在查询集中使用这些关系。
我建议的模型结构如下:
class Product(models.Model):
code = models.CharField(....)
price = models.DecimalField(....)
class Transaction(models.Model)
# You have to define related_name for at least one of relations below.
# Without that, automatically generated ones will clash.
# Also don't foget to change `on_delete` to suit your needs.
current_product = models.ForeignKey(Product, related_name="current_transactions", on_delete=models.CASCADE)
previous_product = models.ForeignKey(Product, related_name="previous_transactions", on_delete=models.CASCADE)
@property
def status(self):
# also, no need to do additional queries here manually. You can improve
# it further by using `select_related` when querying for transactions.
c_price = self.current_product.price
p_price = self.previous_product.price
if c_price == p_price:
return "Due"
elif c_price > p_price:
return "Upgrade"
else:
return "Downgrade"
使用该模型结构,查找特定类型的交易将更加容易:
upgrade_transactions = Transaction.objects.filter(current_product__price__gt=F('previous_product__price'))
downgrade_transactions = Transaction.objects.filter(current_product__price__lt=F('previous_product__price'))
due_transactions = Transaction.objects.filter(current_product__price=F('previous_product__price'))
答案 1 :(得分:1)
我认为您可以尝试使用Subquery
, OuterRef
和.annotate()
:
if value == 'Upgrade':
return queryset.annotate(
previous_price=Subquery(
Product.objects.filter(
code=OuterRef("previous_product_code")
)[:1]
),
current_price=Subquery(
Product.objects.filter(
code=OuterRef("current_product_code")
)[:1]
),
).filter(current_price__gt=F("previous_price"))
...
答案 2 :(得分:0)
请记住,最后,filter()操作是一个SQL操作,我们应该注意性能问题。
因此,我的建议是:如果您需要按状态进行过滤,则每次保存交易时都要更新产品模型上的状态。您的应用程序将更快并且代码更简洁。