Django& GenericForeignKey来自抽象模型?

时间:2015-04-09 11:48:17

标签: python django django-models mezzanine

寻找一种方法,将相关的Django模型分配给抽象模型中声明的泛型关系,其他模型派生自。 Bellow是我尝试为cartridge.shop.models.Priced 抽象模型衍生的所有后代添加 ManyToOne 关系:

# cartridge.shop.models unit
# This is a 3rd party module I can't alter sources directly.
# Only monkeypatching or sublclassing are options.
from django.db import models

class Priced(models.Model):
    """
    Abstract model with unit and sale price fields. Inherited by
    ``Product`` and ``ProductVariation`` models.
    """

    unit_price = fields.MoneyField(_("Unit price"))

    class Meta:
        abstract = True

# Product derives from abstract Priced model
class Product(Priced, …):
    pass

# my_application.models module
from cartridge.shop.models import Priced, Product
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _

# Simple example of a django model I wish make ForeignKey
# relationship to from all descendants of Priced model
class VAT(models.Model):
    description = models.CharField(blank=False, null=False, max_length=36)
    rate = models.DecimalField(
            blank=False, null=False, decimal_places=2, max_digits=2+3)

    class Meta:
        verbose_name = _("Value Added Tax")
        verbose_name_plural = _("Value Added Taxes")

Priced.vat_contype = models.ForeignKey(ContentType)
Priced.vat_id = models.PositiveIntegerField()
Priced.vat = GenericForeignKey('vat_contype', 'vat_id')

Product.vat = VAT()  # Specify the concrete model here ? This way ?

我也不确定这是如何解决抽象模型后代的ForeignKey关系的正确方法。我是否做了不必要的过于复杂的事情?可以用一个ContentType来解决,而不是GenericForeignKey所有{{1}}其他方式?

我知道子类化和多表继承,但我真的希望避免创建额外的表,其中简单和更快的列添加至少也是如此。

1 个答案:

答案 0 :(得分:0)

我对你的目标有点不清楚。但是,如果您只想将所有Priced个后代连接到VAT,那么需要ContentTypes。我建议您继承Priced而不是猴子修补它,因为抽象模型不会创建数据库表。然后标记Priced子类摘要,并将ForeignKey添加到VAT,如下所示:

# models.py
class VAT(models.Model):
    ...

class PricedWithVAT(Priced):
    vat = models.ForeignKey('VAT')

    class Meta:
        abstract = True

# This class will have a foreign key to VAT
class Product(PricedWithVAT, …):
    pass

就是这样。

您可以查看有关如何将新对象或现有对象关联在一起的文档herehere

另一方面,如果您想要将所有Priced个后代通常连接到各种模型,那么执行确实想要使用ContentTypes。它并不复杂得多:

# models.py
class VAT(models.Model):
    ...

class PricedWithGenericRelation(Priced):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()

    class Meta:
        abstract = True

# This class can have a foreign key to ANY model, not just VAT
class Product(PricedWithGenericRelation, …):
    pass

ContentType API提供了各种方法来创建这些类型的对象之间的通用关系。