我有两个模型:帐户和转账。 模型账户具有属性货币(欧元、美元、日元等(。 模型转移具有两个属性account_from和account_to。 我想添加一个约束,用于检查account_from是否使用与account_to相同的货币。
我正在考虑在转移模型上添加这样的约束:
class Meta:
constraints = [
CheckConstraint(check=Q(account_from__currency=F('account_to__currency')), name='same_currency'),
]
但由于错误,这不起作用
django.core.exceptions.FieldError: Joined field references are not permitted in this query
我该怎么做?不依赖 SQL。我知道如何在SQL中做到这一点,但我想使用ORM。还是不可能用姜戈ORM做到这一点?
以下是两种模型(简化以避免噪音(:
class Tranfer(AuditedModel):
"""
The action of moving money from one account to another
"""
account_from = models.ForeignKey(Account, related_name="outgoing", on_delete=models.CASCADE)
account_to = models.ForeignKey(Account, related_name="incoming", on_delete=models.CASCADE)
class Account(AuditedModel):
"""
Recipient for money
"""
currency = models.CharField('currency', max_length=3, choices=(('EUR', 'Euro'), ('USD', 'American Dollars'), ('JPY', 'Japan Yen')))
class Meta:
constraints = [
CheckConstraint(check=Q(account_from__currency=F('account_to__currency')), name='same_currency'),
]
按照以下步骤解决问题。
-
约束部分应位于转移模型中,而不是在帐户模型中。
-
必须避免对任何两个关系模型进行检查约束。
-
Meta 部分的约束数组中的 CheckConstraint(( 的替代方法使用函数 clean 进行验证而不是约束。
from django.db import models
from django.core.exceptions import ValidationError
class Account(models.AuditedModel):
"""
Recipient for money
"""
currency = models.CharField('currency', max_length=3, choices=(
('EUR', 'Euro'),
('USD', 'American Dollars'),
('JPY', 'Japan Yen')
))
class Transfer(models.AuditedModel):
"""
The action of moving money from one account to another
"""
account_from = models.ForeignKey(Account, related_name="outgoing", on_delete=models.CASCADE)
account_to = models.ForeignKey(Account, related_name="incoming", on_delete=models.CASCADE)
def clean(self):
if self.account_from.currency != self.account_to.currency:
raise ValidationError("Same currency required for transaction.")
return super().clean()