簡體   English   中英

Django 從 inheritance 字段序列化子 model

[英]Django serialize child model from inheritance field

我正在使用 DRF,但我的模型似乎存在設計問題:

背景:我正在為財務管理做一個個人項目,所以我有SavingsAccountCreditCardIncomes的模型(這確實很簡化,但我認為這足以看出問題所在)。

問題:在收入中,我應該能夠跟蹤我將錢添加到哪個賬戶,但這可能是儲蓄賬戶或信用卡,所以我制作了另一個 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM