在 wagtail 管理中编辑 django 'through' 模型内联?

Edit django 'through' model inline in wagtail admin?

[编辑了更好的代码示例]

根据标题,我正在尝试允许在 Wagtail 中对一个非常简单的商店页面进行内联编辑(可能会将其放入一个简单的包中):

有以下型号:

class Product(ClusterableModel):
    page = ParentalKey(MiniShopPage, on_delete=models.CASCADE, related_name='shop_products')
    name = models.CharField(max_length=255)
    description = models.CharField(max_length=2500)
    downloadable = models.BooleanField()
    price = models.FloatField()
    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    # define the content_panels
    panels = [
        FieldPanel('name'),
        FieldPanel('description'),
        FieldPanel('downloadable'), 
        FieldPanel('price'), 
        ImageChooserPanel('image'),
    ]

class Order(TimeStampedModel, ClusterableModel):
    '''
    Example of use outside of the admin:
    p = Product.objects.first()
    order = Order.objects.create(client_email='someone@hotmail.com', gift_amount=0)
    quantities = ProductInOrderCount(product=p, order=order, quantity=2)
    quantities.save()

    for itm in order.productinordercount_set.all():                          
        print(itm.quantity)
    '''
    is_fulfilled = models.BooleanField(default=False)
    is_paid_for = models.BooleanField(default=False)
    client_email = models.EmailField(blank=False)
    gift_amount = models.PositiveIntegerField()
    # products = M2MTHROUGH
    # the through model stores the quantity
    products = models.ManyToManyField(Product, through='ProductInOrderCount')

    content_panels = [
        FieldPanel('is_fulfilled'),
        FieldPanel('is_paid_for'),
        FieldPanel('client_email'),
        FieldPanel('gift_amount'),
        InlinePanel('products'),
    ]

    class OrderModelAdmin(ModelAdmin):
        model = Order
        menu_label = 'Orders'
        ...

    modeladmin_register(OrderModelAdmin)

class ProductInOrderCount(Orderable):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()

棘手的事情是我收到错误 Cannot set values on a ManyToManyField which specifies an intermediary model. 或者我根本没有得到内联面板,而是 select。

我假设是这种情况,因为创建和添加方法不能通过模型​​工作,是这样吗?

如果可以,您能否建议我重写应用程序的方法,以便允许我在管理员和我的代码中创建包含产品的订单?

InlinePanel 仅适用于一对多 ParentalKey 关系,不适用于 ManyToManyField。这应该不是问题,因为 ParentalKey 非常适合这种情况:

  • 带有through模型的ManyToManyField实际上只是两个背对背的一对多关系;
  • ParentalKey 专为与父模型密切相关的关系而设计,因为它们始终作为一个单元进行编辑、验证和保存。 ProductInOrderCountOrder 之间的关系是这样(ProductInOrderCount 记录在概念上是 Order 的一部分),但 ProductInOrderCountProductProductInOrderCount 不是 Product 的一部分)。

这将为您提供如下模型定义:

class ProductInOrderCount(Orderable):
    order = ParentalKey(Order, on_delete=models.CASCADE, related_name='ordered_products')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()

您的 Order 模型可以有一个 InlinePanel('ordered_products'),并且可以省略 products 字段。