[英]Django serialize child model from inheritance field
我正在使用 DRF,但我的模型似乎存在設計問題:
背景:我正在為財務管理做一個個人項目,所以我有SavingsAccount
、 CreditCard
、 Incomes
的模型(這確實很簡化,但我認為這足以看出問題所在)。
問題:在收入中,我應該能夠跟蹤我將錢添加到哪個賬戶,但這可能是儲蓄賬戶或信用卡,所以我制作了另一個 model ,兩者的共同屬性稱為Account
。
我正在使用InheritanceManager
使它更容易一些。
from model_utils.managers import InheritanceManager
class Account(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=120)
balance = models.DecimalField(decimal_places=4, max_digits=12)
objects = InheritanceManager()
def get_child(self):
return Account.objects.get_subclass(pk=self.pk)
class SavingsAccount(Account):
bank = models.CharField(max_length=120)
is_investment = models.BooleanField(default=0)
class CreditCard(Account):
cut = models.IntegerField()
pay = models.IntegerField()
bank = models.CharField(max_length=120)
credit = models.DecimalField(decimal_places=4, max_digits=12)
@property
def used(self):
return self.credit - self.balance
class Income(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
amount = models.DecimalField(decimal_places=4, max_digits=12)
account = models.ForeignKey(Account, on_delete=models.PROTECT, related_name="incomes")
description = models.TextField()
date = models.DateField()
有了這個,我可以與帳戶進行交互,例如: income = Income.objects.select_related("account").first()
然后income.account.get_child()
以檢索 SavingsAccount 或 CreditCard object,問題與序列化程序一起使用,因為我想發送子 object 而不是帳戶 object。
我當前(不完整)的解決方案:使用我得到的 rest-framework-generic-relations
class IncomeSerializer(serializers.ModelSerializer):
account = GenericRelatedField({
CreditCard: CreditCardSerializers(),
SavingsAccount: SavingsAccountSerializers(),
})
class Meta:
Model = Income
fields = ("id", "amount", "account", "description")
這失敗了,因為序列化程序獲取的帳戶 object 是Account
類型,如何獲取具有帳戶子類而不是默認子類的收入查詢集?
這是一個壞主意嗎? 我應該如何實現這樣的事情? 最好只發送帳戶 object 的 ID,然后再請求該 object?
提前非常感謝,我嘗試提供所有需要的信息,但如果我應該添加更多信息,請告訴我。
我一直避免使用 ContentType,因為我認為這里不需要它。
好吧,現在我這樣做了:
class AccountSerializer(serializers.ModelSerializer):
def to_representation(self, value):
child = value.get_child()
if isinstance(child, SavingsAccount):
serializer = SavingsAccountSerializer(child)
elif isinstance(child, Wallet):
serializer = WalletSerializer(child)
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
class Meta:
model = Account
class WalletSerializer(serializers.ModelSerializer):
class Meta:
model = Wallet
fields = ('__all__')
class SavingsAccountSerializer(serializers.ModelSerializer):
class Meta:
model = SavingsAccount
fields = ('__all__')
class IncomeSerializer(serializers.ModelSerializer):
account = AccountSerializer(read_only=True)
class Meta:
model = Income
fields = ("__all__")
我確信這不是最有效的方法,因為每個 object 中的get_child
方法使用的連接使用n
個查詢(其中 n 是收入中的對象數),我很確定你可以通過 2 個查詢(每個子班一個)來完成,但我只是在學習,希望更有經驗的人會發布更好的答案。
盡管如此,我還是讓這個以防萬一有助於像我一樣在一個小項目中工作的人。
注意:我只是用它來檢索信息,我沒有測試它來檢索信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.