Django如何在另一模型字段中使用外键字段的关联属性
报错原因
你直接在FiatTransaction的模型类定义层级写currency = debit_account.currency是错误的。Django模型定义阶段,debit_account只是一个ForeignKey字段类的实例,不是具体的模型记录对象,没有关联到实际的Account数据,自然取不到currency属性,这就是报错的核心原因。
正确实现方案
根据你是否需要将currency存储到数据库,可以选择两种实现方式:
方案1:动态属性取值(无需冗余存储)
如果不需要用currency做数据库查询、过滤,直接将其设为动态属性即可:
class FiatTransaction(models.Model): debit_account = models.ForeignKey('company.Account', on_delete=models.CASCADE, related_name='debit_account') credit_account = models.ForeignKey('company.Account', on_delete=models.CASCADE, related_name='credit_account') executed_on = models.DateTimeField(auto_now_add=True) amount = models.FloatField() is_processed = models.BooleanField(default=False) fee = models.FloatField() memo = models.CharField(max_length=250) # 新增动态属性 @property def currency(self): return self.debit_account.currency def __str__(self): return F"Transferred {self.amount} from {self.debit_account} to {self.credit_account} at {self.executed_on}"
调用时直接访问实例的.currency属性就会自动从关联的借记账户取对应货币值,不需要额外存储到数据库。
方案2:数据库存储(适合需要用currency做查询的场景)
如果需要基于currency做过滤、统计、索引,就将其设为普通字段,重写save方法自动赋值:
class FiatTransaction(models.Model): debit_account = models.ForeignKey('company.Account', on_delete=models.CASCADE, related_name='debit_account') credit_account = models.ForeignKey('company.Account', on_delete=models.CASCADE, related_name='credit_account') executed_on = models.DateTimeField(auto_now_add=True) amount = models.FloatField() # 新增存储currency的字段,editable设为False禁止手动修改 currency = models.ForeignKey(FiatCurrency, on_delete=models.CASCADE, editable=False) is_processed = models.BooleanField(default=False) fee = models.FloatField() memo = models.CharField(max_length=250) def save(self, *args, **kwargs): # 保存前自动赋值 if not self.currency_id and self.debit_account_id: self.currency = self.debit_account.currency # 如果业务允许修改debit_account,可以加逻辑同步更新currency # if self.debit_account_id and self.currency != self.debit_account.currency: # self.currency = self.debit_account.currency super().save(*args, **kwargs) def __str__(self): return F"Transferred {self.amount} from {self.debit_account} to {self.credit_account} at {self.executed_on}"
使用该方案需要执行makemigrations和migrate命令,将新增的currency字段同步到数据库表中。
内容的提问来源于stack exchange,提问作者JSRB
相关产品推荐
相关产品推荐

