72

我正在为一个 satchmo 应用程序组合管理员。Satchmo 使用 OneToOne 关系来扩展基本Product模型,我想在一页上对其进行编辑。

可以将 OneToOne 关系作为内联吗?如果没有,将一些字段添加到我的管理员的给定页面最终将保存到 OneToOne 关系中的最佳方法是什么?

例如:

class Product(models.Model):
    name = models.CharField(max_length=100)
    ...

class MyProduct(models.Model):
    product = models.OneToOne(Product)
    ...

我为我的管理员尝试了这个,但它不起作用,并且似乎需要一个外键:

class ProductInline(admin.StackedInline):
    model = Product
    fields = ('name',)

class MyProductAdmin(admin.ModelAdmin):
    inlines = (AlbumProductInline,)

admin.site.register(MyProduct, MyProductAdmin)

引发此错误:<class 'satchmo.product.models.Product'> has no ForeignKey to <class 'my_app.models.MyProduct'>

这样做的唯一方法是自定义表单吗?

编辑:刚刚尝试以下代码直接添加字段......也不起作用:

class AlbumAdmin(admin.ModelAdmin):
    fields = ('product__name',)
4

4 回答 4

82

完全可以将内联用于 OneToOne 关系。但是,定义关系的实际字段必须位于内联模型上,而不是父模型上 - 与 ForeignKey 的方式相同。切换它,它会工作。

评论后编辑:您说父模型已经向管理员注册:然后取消注册并重新注册。

from original.satchmo.admin import ProductAdmin

class MyProductInline(admin.StackedInline):
    model = MyProduct

class ExtendedProductAdmin(ProductAdmin):
    inlines = ProductAdmin.inlines + (MyProductInline,)

admin.site.unregister(Product)
admin.site.register(Product, ExtendedProductAdmin)

2020 年更新(Django 3.1.1)

此方法仍然有效,但新Django版本中的某些类型已更改,因为现在应该将inlinesin添加为列表而不是元组,如下所示:ExtendedProductAdmin

class ExtendedProductAdmin(ProductAdmin):
    inlines = ProductAdmin.inlines + [MyProductInline]

或者你会得到这个错误:

    inlines = ProductAdmin.inlines + (MyProductInline,)
TypeError: can only concatenate list (not "tuple") to list
于 2009-11-16T19:49:49.570 回答
9

也许使用继承而不是 OneToOne 关系

class Product(models.Model):
    name = models.CharField(max_length=100)
    ...

class MyProduct(Product):
    .....

或者使用代理类

class ProductProxy(Product)
    class Meta:
        proxy = True

在 admin.py

class MyProductInlines(admin.StackedInline):
    model = MyProduct

class MyProductAdmin(admin.ModelAdmin):
    inlines = [MyProductInlines]

    def queryset(self, request):
        qs = super(MyProductAdmin, self).queryset(request)
        qs = qs.exclude(relatedNameForYourProduct__isnone=True)
        return qs

admin.site.register(ProductProxy, MyProductAdmin)

在此变体中,您的产品将内联。

于 2012-09-28T12:42:57.390 回答
5

关于最后一个问题,对于多个子类型,最佳解决方案是什么。例如,具有子类型类 Book 和子类型类 CD 的类 Product。此处显示的方式必须编辑产品的一般项目加上书籍的子类型项目和 CD 的子类型项目。因此,即使您只想添加一本书,您也可以获得 CD 字段。如果您添加一个子类型,例如 DVD,您将获得三个子类型字段组,而实际上您只需要一个子类型组,在上述示例中:书籍。

于 2010-03-14T00:24:43.000 回答
2

您也可以尝试在 OneToOneField 上设置“parent_link=True”?

https://docs.djangoproject.com/en/dev/topics/db/models/#specifying-the-parent-link-field

于 2012-12-14T10:57:55.273 回答