Django Admin: отношение OneToOne как встроенный?
Я собираю admin для приложения satchmo. Satchmo использует отношения OneToOne для расширения базовой модели Product
, и я хотел бы отредактировать все это на одной странице.
Возможно ли иметь отношение OneToOne как Inline? Если нет, то каким образом можно добавить несколько полей на заданную страницу моего администратора, которые в конечном итоге будут сохранены в отношении 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',)
Ответы
Ответ 1
Вполне возможно использовать встроенную линию для отношения 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)
Ответ 2
Возможно использование наследования вместо отношения 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)
В этом варианте ваш продукт будет встроен.
Ответ 3
Ссылаясь на последний вопрос, что будет лучшим решением для нескольких подтипов. Например, класс Product с подтипом класса Book и подтип класса CD. Как показано здесь, вам нужно будет отредактировать продукт, а также элементы подтипа для книги и элементы подтипа для компакт-диска. Поэтому, даже если вы хотите добавить книгу, вы также получите поля для компакт-диска. Если вы добавите подтип, например. DVD, вы получаете три группы полей подтипа, в то время как на самом деле вам нужна только одна группа подтипов, в указанном примере: книги.
Ответ 4
Вы также можете попробовать установить 'parent_link = True' на свой OneToOneField?
https://docs.djangoproject.com/en/dev/topics/db/models/#specifying-the-parent-link-field