Django admin:直接内联到二级关系

时间:2017-06-10 19:27:24

标签: python django admin relationship inline-formset

我有一个三级Invoice模型,我想在Django的管理区域中显示...在" 特殊"方式。

请允许我提供一些背景信息:

每个Invoice符合多个SubInvoice(s),每个SubInvoice符合几个InvoiceItem(s),其中包含Products的细分{1}}由客户购买。

从逻辑上讲,它是这样的(希望ascii艺术作品)

+---------- Invoice id=3 -----------+
|       Full total: $100.00         |
|                                   |
|  +----- Sub Invoice id=1 -----+   |
|  |      Subtotal $70          |   |
|  |                            |   |
|  |    Item 1 in SubInv.1      |   |
|  |    Item 2 in SubInv.1      |   |
|  |    Item 3 in SubInv.1      |   |
|  |____________________________|   |
|                                   |
|  +----- Sub Invoice id=2 -----+   |
|  |      Subtotal $30          |   |
|  |                            |   |
|  |    Item 1 in SubInv.2      |   |
|  |    Item 2 in SubInv.2      |   |
|  |____________________________|   |
|                                   |
|___________________________________|

模型看起来或多或少(他们已经针对这个问题进行了简化),例如:

class Invoice(models.Model):
    full_total = DecimalField(...)
    # has a .sub_invoices RelatedManager through a backref from SubInvoice

class SubInvoice(models.Model):
    sub_total = DecimalField(...)
    invoice = ForeignKey('server.Invoice', related_name='sub_invoices')
    # has an .items RelatedManager through a backref from InvoiceItem

class InvoiceItem(models.Model):
    sub_invoice = ForeignKey('server.SubInvoice', related_name='items')
    product = ForeignKey('server.Product', related_name='+')
    quantity = PositiveIntegerField(...)
    price = DecimalField(...)

现在,我知道在Django Admin中嵌套两个级别的关系非常复杂,我并没有尝试将InvoiceItem嵌套到SubInvoice中并将其嵌入到Invoice中。 Invoice。这很棒,但由于嵌套内联的困难,我已经准备好了。 否:我要做的是显示inline,并Items显示Invoice.sub_invoices__items&#34 ;跳过" SubInvoice。我对Invoice(s)中显示的信息并不十分关心,但我确实关注InvoiceItemsInvoice中的信息。

我的意思是,基本上,如果+---------- Invoice id=3 -----------+ | Full total: $100.00 | | | | +----------------------------+ | | | | | | | Item 1 in SubInv.1 | | | | Item 2 in SubInv.1 | | | | Item 3 in SubInv.1 | | | | Item 1 in SubInv.2 | | | | Item 2 in SubInv.2 | | | |____________________________| | | | |___________________________________| 管理员视图如下所示,我希望(或"我可以和" 相处) :

InvoiceItems

Invoice 作为 SubInvoices 的内联,但未显示有关 admin.py的任何信息在其中)

我在class InvoiceItemInline(admin.StackedInline): fk_name = 'sub_invoice__invoice' model = InvoiceItem class InvoiceAdmin(admin.ModelAdmin): inlines = (InvoiceItemInline,) 中尝试了以下内容:

<class 'server.admin.invoices.InvoiceItemInline'>: (admin.E202) 'server.InvoiceItem' has no field named 'sub_invoice__invoice'.

但这给了我一个错误:

class InvoiceItemInline(admin.StackedInline): model = InvoiceItem class InvoiceAdmin(admin.ModelAdmin): inlines = (InvoiceItemInline,)

我也直接尝试过:

<class 'server.admin.invoices.InvoiceItemInline'>: (admin.E202) 'server.InvoiceItem' has no ForeignKey to 'server.Invoice'.

然后(我期待的这个)产生了这个错误:

Invoice

有没有办法实现这个目标?提前谢谢。

PS:

截至目前,我已经修补了#34;解决方案似乎是规范的方式:

  • 注册SubInvoice模型。
  • Invoice注册一个admin.ModelAdmin 内联(此内联将在&#34;内联&#34;进入SubInvoice&#39; s的ModelAdmin)。
  • 同时在管理员中注册InvoiceItems,以便我们计算其管理员视图的链接。
  • SubInvoice内嵌视图添加到上述SubInvoice视图中。
  • 添加指向Invoice
  • Invoice的管理视图的链接

几乎所有其他S.O. answer中描述的内容。

但这种方法的问题在于它不会让我一眼就看到InvoiceItems及其+---------- Invoice id=3 -----------+ | Full total: $100.00 | | | | +----- Sub Invoice id=1 -----+ | +--- Sub Invoice id=1 ---+ | | Subtotal $70 | | | Item 1 in SubInv.1 | | | | | | Item 2 in SubInv.1 | | | <a>Click for items ==============> | Item 3 in SubInv.1 | | |____________________________| | |________________________| | | | +----- Sub Invoice id=2 -----+ | | | Subtotal $30 | | +--- Sub Invoice id=2 ---+ | | | | | Item 1 in SubInv.2 | | | <a>Click for items ==============> | Item 2 in SubInv.2 | | |____________________________| | |________________________| | | |___________________________________| (我看到发票,其中包含sub_invoices,然后是sub_invoices内联,有一个指向InvoiceItems的链接,我必须点击它以查看项目)。如果我能摆脱对该链接的需求,那就太棒了。

这就是我现在所拥有的,基本上:

reader.readAsText(file);

1 个答案:

答案 0 :(得分:2)

我认为您的问题可以使用ManyToManyField + through来解决。 (这是一个例子)

#models.py
class Invoice(models.Model):
    full_total = DecimalField(...)
    # has a .sub_invoices RelatedManager through a backref from SubInvoice

class SubInvoice(models.Model):
    sub_total = DecimalField(...)
    invoice = ManyToManyField(
        'server.Invoice',
        through='server.InvoiceItem',
        through_fields=('sub_invoice', 'invoice'))
    # has an .items RelatedManager through a backref from InvoiceItem

class InvoiceItem(models.Model):
    sub_invoice = ForeignKey('server.SubInvoice')
    invoice = ForeignKey('server.Invoice')
    product = ForeignKey('server.Product', related_name='+')
    quantity = PositiveIntegerField(...)
    price = DecimalField(...)

#admin.py
from django.contrib import admin
from .models import InvoiceItem, Invoice, SubInvoice


class InvoiceItemInline(admin.TabularInline):
    model = InvoiceItem
    extra = 1


class InvoiceAdmin(admin.ModelAdmin):
    inlines = (InvoiceItemInline,)


admin.site.register(Invoice, InvoiceAdmin)
admin.site.register(SubInvoice, InvoiceAdmin)

我建议您在views.py中使用此类的课程,并在inlineformset_factory中使用forms.py。 在你的前端使用jquery-formset库,因为它看起来非常整洁。

注意: 您也可以在外键上的on_delete=models.CASCADE中使用InvoiceItem,因此如果其中一个项目被删除,那么InvoiceItem也会被删除,或者models.SET_NULL,无论您喜欢哪个

希望这可以帮助你。