[英]Django Admin: OneToOne Relation as an Inline?
我正在为一个 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',)
完全可以将内联用于 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版本中的某些类型已更改,因为现在应该将ExtendedProductAdmin
中的内inlines
添加为列表而不是元组,如下所示:
class ExtendedProductAdmin(ProductAdmin):
inlines = ProductAdmin.inlines + [MyProductInline]
或者你会得到这个错误:
inlines = ProductAdmin.inlines + (MyProductInline,)
TypeError: can only concatenate list (not "tuple") to list
也许使用继承而不是 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)
在此变体中,您的产品将内联。
关于最后一个问题,对于多个子类型,最佳解决方案是什么。 例如,具有子类型类 Book 和子类型类 CD 的类 Product。 此处显示的方式您必须编辑产品的一般项目加上书籍的子类型项目和 CD 的子类型项目。 因此,即使您只想添加一本书,您也可以获得 CD 字段。 如果您添加一个子类型,例如 DVD,您将获得三个子类型字段组,而实际上您只需要一个子类型组,在上述示例中:书籍。
您也可以尝试在 OneToOneField 上设置“parent_link=True”?
https://docs.djangoproject.com/en/dev/topics/db/models/#specifying-the-parent-link-field
是的,一对一关系可以内联。
例如,如下所示,如果“MyProduct”类有“models.OneToOneField()”引用“Product”类,这意味着“MyProduct”类有ForeignKey引用“Product”类:
# "models.py"
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
class MyProduct(models.Model):
name = models.CharField(max_length=100)
product = models.OneToOneField( # Here
Product,
on_delete=models.CASCADE,
primary_key=True
)
然后,您可以在“Product”类下内联“MyProduct”类,如下所示:
# "admin.py"
from django.contrib import admin
from .models import Product, MyProduct
class MyProductInline(admin.TabularInline):
model = MyProduct
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
inlines = (MyProductInline, )
相反,如下图所示,如果“Product”类有“models.OneToOneField()”引用“MyProduct”类,这意味着“Product”类有ForeignKey引用“MyProduct”类:
# "models.py"
from django.db import models
class MyProduct(models.Model):
name = models.CharField(max_length=100)
class Product(models.Model):
name = models.CharField(max_length=100)
my_product = models.OneToOneField( # Here
MyProduct,
on_delete=models.CASCADE,
primary_key=True
)
然后,您可以在“MyProduct”类下内联“Product”类,如下所示:
# "admin.py"
from django.contrib import admin
from .models import Product, MyProduct
class ProductInline(admin.TabularInline):
model = Product
@admin.register(MyProduct)
class MyProductAdmin(admin.ModelAdmin):
inlines = (ProductInline, )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.