Django admin:直接进入二级关系

Bor*_*jaX 9 python django admin relationship inline-formset

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

请允许我提供一些背景知识:

每个Invoice都符合几个SubInvoice(s),每个SubInvoice都符合几个InvoiceItem(s),其中包含Products客户购买的故障.

从逻辑上讲,它是这样的(希望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      |   |
|  |____________________________|   |
|                                   |
|___________________________________|
Run Code Online (Sandbox Code Playgroud)

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

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(...)
Run Code Online (Sandbox Code Playgroud)

现在,我知道在Django Admin中嵌套两个级别的关系是非常复杂的,我并不是试图嵌入到嵌套中InvoiceItem并将其SubInvoice嵌套到Invoice.这很好,但由于嵌套内联的困难,我准备放弃它.编号:我希望做的是显示了什么Invoice,并作为inlineItems,"跳"Invoice.sub_invoices__items.我对SubInvoice(s)中显示的信息并不是那么关心,但我确实关心Invoice和中的信息InvoiceItems.

我的意思是,基本上,如果管理员视图如下所示,我希望(或者"我可以和我一起生活")Invoice:

+---------- 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      |   |
|  |____________________________|   |
|                                   |
|___________________________________|
Run Code Online (Sandbox Code Playgroud)

(InvoiceItems作为Invoice(s)的内联而未显示其中的任何信息SubInvoices)

我在以下方面尝试了以下内容admin.py:

class InvoiceItemInline(admin.StackedInline):
    fk_name = 'sub_invoice__invoice'
    model = InvoiceItem

class InvoiceAdmin(admin.ModelAdmin):
    inlines = (InvoiceItemInline,)
Run Code Online (Sandbox Code Playgroud)

但这给了我一个错误:

<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,)
Run Code Online (Sandbox Code Playgroud)

但那时(我期待的这个)产生了这个错误:

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

有没有办法实现这个目标?先感谢您.

PS:

截至目前,我有一个"修补"的解决方案似乎是规范的方式:

  • 注册Invoice模型.
  • 注册一个内嵌的(这个在线将"内联"到的的ModelAdmin).admin.ModelAdmin SubInvoiceInvoice
  • 同时SubInvoice在admin中注册,这样我们就可以计算出其管理视图的链接.
  • 添加内嵌的观点InvoiceItems上述SubInvoice的观点.
  • 添加指向SubInvoice(s)的管理视图的链接Invoice

几乎在其他SO答案中描述了什么.

但这种方法的问题在于它不会让我一眼就看到InvoiceInvoiceItems(我看到发票,其中包含sub_invoices,然后在sub_invoices内联中,有一个指向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   |
|  |____________________________|   |       |________________________|
|                                   |
|___________________________________|
Run Code Online (Sandbox Code Playgroud)

Kin*_*oad 3

我认为你的问题可以使用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)
Run Code Online (Sandbox Code Playgroud)

我建议您在您的课程中使用该课程,并在您的课程中views.py使用它。在前端也使用库,因为这看起来非常整洁。inlineformset_factoryforms.pyjquery-formset

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

希望这可以帮助你。