0

让我们看看我是否可以解释自己,我有这个模型:

class BillHeader(models.Model):
    number = models.CharField(_('Bill number'), max_length=10, unique=True, \
    default=__number)
    client = models.ForeignKey(ClienteYProveedor, verbose_name=_('Client'))
    date = models.DateTimeField(_('Date'), default=datetime.now)

    def __unicode__(self):
        return str(self.number)

    class Meta:
        abstract = True

class BillFooter(models.Model):           
    base_import = models.DecimalField(_('Base import'), max_digits=12, \
    decimal_places=2)

    class Meta:
        abstract = True

class BillBody(models.Model):        
    description = models.CharField(_('Description'), max_length=200)
    amount = models.DecimalField(_('Amount'), max_digits=6, decimal_places=2)
    discount = models.DecimalField(_('Discount'), max_digits=4, \
    decimal_places=2)
    price = models.DecimalField(_('Price'), max_digits=12, decimal_places=2)
    unitaryprice = models.DecimalField(_('Unitary Price'), max_digits=12, \
    decimal_places=2)

    def __unicode__(self):
        return self.description
    class Meta:
        abstract = True

class EmittedBill(BillHeader, BillBody, BillFooter):
    pass

class ReceivedBill(BillHeader, BillBody, BillFooter):
    pass

当用户添加 Emmited 或 Received 账单时,我需要显示BillHeader为普通字段集,但BillBody需要BillFooterTabularInline.

如果我将它们作为 TabularInline 放在 admin.py 中,则会出现一个错误,指出它们需要ForeignKey相关模型。当然,我不能放那些外键,因为它们是在底部声明的。我认为你们称之为“向后外键”。

我的问题是:我怎样才能在管理员中显示 TabularInlines 而不会弄得一团糟?我可以在没有抽象基类的情况下做到这一点,但是另一个问题来了,它在 TabularInline 中显示了另一个 ForeignKey(如果你在 EmmitedBills 上,它会在 TabularInline 中显示 FK 到 ReceivedBills,反之亦然),我无法排除他们。

对不起,如果这是一个愚蠢的问题,但我不是程序员(这只是一种爱好),我真的让自己对数据模型一团糟。


我会更好地解释:

我有两种类型的账单,Emitted并且Received它们都显示在管理主页上(这就是为什么我没有使用 aBooleanField来标记它们)。两种类型都有相同的字段,除了一个是帐单编号,Emmitted它将自动生成。每个账单包含 1 个带有编号、客户和日期的标题,1 个或多个带有描述、金额、价格等的正文内联条目和 1 个内联页脚,显示不含税的总价格、应用的税等。


更新

我已经做了所有事情,但是我有一个问题,在我的新模型中 BillBody 有两个 FK(EmmitedBill 和 ReceivedBill),它们显示在 TabularInline 中。如何隐藏它们?field.exclude() 给出错误。

4

1 回答 1

2

我不完全理解你的问题,但你可以使用

ForeignKey('ModelName')

代替

ForeignKey(ModelName)

如果ModelName模型尚未声明。也许这可以解决您的问题。

内联管理员(如TabularInline)仅在您具有一对多关系时使用,该关系由ForeignKey多方创建。如果您没有这样的外键,则不能使用内联管理员。继承绝对不同于a ForeignKey

但是,我认为您的数据模型是错误的。看来您确实想存储账单。有两种类型的票据,emittedreceived票据。emittedreceivedbills 都具有相同的字段。此外,您希望每张账单都包含一个带有数字、客户和日期的标题、1 个或多个正文条目,其中每个条目存储您存储的信息BillBody和 1 个或多个小数base_number


对您来说可能更好的数据模型

class Bill(models.Model):
    number = models.CharField(_('Bill number'), max_length=10, unique=True, default=__number)
    client = models.ForeignKey(ClienteYProveedor, verbose_name=_('Client'))
    date = models.DateTimeField(_('Date'), default=datetime.now)

    def get_total_price(self):
        return sum([entry.price for entry in self.entries])

class BillEntry(models.Model):
    bill = models.ForeignKey(Bill, related_name='entries')

    description = models.CharField(_('Description'), max_length=200)
    amount = models.DecimalField(_('Amount'), max_digits=6, decimal_places=2)
    discount = models.DecimalField(_('Discount'), max_digits=4, decimal_places=2)
    price = models.DecimalField(_('Price'), max_digits=12, decimal_places=2)
    unitaryprice = models.DecimalField(_('Unitary Price'), max_digits=12, decimal_places=2)

我省略了__unicode__方法。

现在你有一个外键 from BillEntrytoBill并且你可以使用表格内联。我不明白你的用法,base_import所以我把它省略了。

价格计算

如果你price应该总是等于amount*unitaryprice - discount或者amount*(unitaryprice-discount)你不应该把它放在一个字段中,而是在需要时计算它,无论是在 Python 中还是在数据库中。如果您想在 Python 中执行此操作,可以使用类似于get_total_price. 如果你想在查询数据库时计算它们,那么让它与 Django 一起工作会有点困难。

在最后一种情况下,你可以看看 SQL 视图,但我认为这对于初学者来说有点太难了。另一种选择是使用自定义 SQL 表达式:

BillEntry.objects.extra(select={'price': 'amount*unitaryprice-discount'})

这将在选择期间计算所有条目的价格。

更新

如果您为发出和接收的账单添加两个子类并使用多表继承,那么您可以使用一个外键 from BillEntryto Bill

class EmittedBill(Bill):
    pass

class ReceivedBill(Bill):
    pass

您可能还必须考虑 Django 生成的数据库模型。通常,您只想将基本数据存储在数据库中,而不是计算数据(就像您想在页脚中做的那样)。因此,如果使用某个公式和使用 等计算价格,则unitaryprice不应amount存储此公式的结果,而是在必要时重新计算(并最终缓存以避免重新计算)。如果您不这样做,您可能会在某个时刻更新某些内容(例如)amount并忘记更新计算值(price一个好的数据库确实有约束,因此不可能在不破坏至少一个约束的情况下存储不一致的数据库。

我也不明白为什么要为每张账单单独设置页眉和页脚。模型不是真正的帐单,它存储帐单的信息。如果你想有一个可见的页眉和页脚,那么你应该在你的视图层(模板)而不是模型本身中这样做。

于 2010-06-30T14:42:40.560 回答