我正在为 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',)
很遗憾,Django 管理器不支持使用内联形式直接编辑
OneToOne
关系。内联仅适用于
ForeignKey
关系,其中“子”对象对“父”对象具有外键。
但是,有几种方法可以在 Django 管理器中在一页上实现类似的结果:
1. 自定义表单和
ModelForm
:
这是最灵活的方法,可以让完全控制表单字段和保存逻辑。
```python from django import forms from django.contrib import admin from .models import Product, MyProduct
class MyProductForm(forms.ModelForm): name = forms.CharField(max_length=100)
class Meta:
model = MyProduct
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
self.fields['name'].initial = self.instance.product.name
def save(self, commit=True):
instance = super().save(commit=False)
if 'name' in self.changed_data:
instance.product.name = self.cleaned_data['name']
instance.product.save()
if commit:
instance.save()
return instance
class MyProductAdmin(admin.ModelAdmin): form = MyProductForm
admin.site.register(MyProduct, MyProductAdmin) ```
在这个例子中:
-
我们创建了一个自定义表单
MyProductForm
,它包含Product
模型的name
字段。 -
在表单的
__init__
方法中,如果正在编辑现有实例,我们将name
字段的初始值设置为相关Product
的名称。 -
在
save
方法中,我们更新相关Product
的name
字段。
2. 使用
inlines
,但反转关系:
虽然不能将
Product
内联到
MyProduct
中,但可以反过来做。在
Product
管理器中,可以使用内联来编辑相关的
MyProduct
对象。
```python from django.contrib import admin from .models import Product, MyProduct
class MyProductInline(admin.StackedInline): model = MyProduct
class ProductAdmin(admin.ModelAdmin): inlines = [MyProductInline]
admin.site.register(Product, ProductAdmin) ```
这种方法的缺点是将主要通过
Product
管理器界面管理
MyProduct
对象。
3. 使用自定义模板:
可以创建一个自定义 Django 管理器模板,该模板在一个页面上显示
Product
和
MyProduct
字段。这需要更多工作,但可以让完全控制管理界面的外观和行为。
选择哪种方法取决于的具体需求和偏好。
标签:python,python-3.x,django,django-admin,one-to-one From: 1744203