Django Admin: OneToOne Relation comme Inline?
-
20-09-2019 - |
Question
Je suis en train ensemble l'administrateur pour une application Satchmo. Satchmo utilise les relations ONEtoONE pour étendre le modèle Product
de base, et je voudrais le modifier sur une seule page.
Il est possible d'avoir une relation OneToOne comme Inline? Sinon, quelle est la meilleure façon d'ajouter quelques champs à une page donnée de mon administration qui finira par être sauvé dans la relation OneToOne?
par exemple:
class Product(models.Model):
name = models.CharField(max_length=100)
...
class MyProduct(models.Model):
product = models.OneToOne(Product)
...
J'ai essayé pour mon administration, mais il ne fonctionne pas, et semble attendre à une clé étrangère:
class ProductInline(admin.StackedInline):
model = Product
fields = ('name',)
class MyProductAdmin(admin.ModelAdmin):
inlines = (AlbumProductInline,)
admin.site.register(MyProduct, MyProductAdmin)
Ce qui jette cette erreur: <class 'satchmo.product.models.Product'> has no ForeignKey to <class 'my_app.models.MyProduct'>
La seule façon de faire un formulaire personnalisé ?
modifier Juste essayé le code suivant pour ajouter les champs directement ... ne fonctionne pas non plus:
class AlbumAdmin(admin.ModelAdmin):
fields = ('product__name',)
La solution
Il est parfaitement possible d'utiliser une ligne pour une relation OneToOne. Cependant, le champ réel définissant la relation doit être sur le modèle en ligne, pas le parent un - exactement de la même manière que pour un ForeignKey. Mettez-le et il fonctionnera.
Modifier après commentaire : vous dites le modèle parent est déjà inscrit à l'administrateur. Désinscrivez et réinscrire
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)
Autres conseils
En se référant à la dernière question, quelle serait la meilleure solution pour plusieurs sous-types. Classe de produit avec par exemple du livre de classe sous-type et sous-type de classe CD. La manière indiquée ici que vous auriez à modifier un produit les éléments généraux ainsi que les éléments du sous-type pour les livres et les éléments sous-type pour les CD. Donc, même si vous voulez seulement ajouter un livre que vous pouvez également obtenir les champs pour CD. Si vous ajoutez un sous-type par exemple DVD, vous obtenez trois groupes de champs sous-types, alors que vous voulez en fait qu'un seul groupe sous-type dans l'exemple mentionné:. Livres
Peut-être utiliser l'héritage au lieu OneToOne relation
class Product(models.Model):
name = models.CharField(max_length=100)
...
class MyProduct(Product):
.....
Ou utiliser des classes proxy
class ProductProxy(Product)
class Meta:
proxy = True
dans 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)
Dans cette variante de votre produit sera en ligne.
Vous pouvez également essayer de régler 'parent_link = True' sur votre OneToOneField?