web-dev-qa-db-fra.com

Django Admin: Relation OneToOne en ligne?

Je rassemble l'administrateur pour une application satchmo. Satchmo utilise les relations OneToOne pour étendre le modèle de base Product, et je voudrais tout modifier sur une seule page.

Il est possible d'avoir une relation OneToOne en tant que Inline? Sinon, quelle est la meilleure façon d'ajouter quelques champs à une page donnée de mon administrateur qui seront finalement enregistrés 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é cela pour mon administrateur mais cela 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 le faire est-elle Formulaire personnalisé ?

edit: Je viens d'essayer le code suivant pour ajouter directement les champs ... ne fonctionne pas non plus:

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

Il est parfaitement possible d'utiliser un inline pour une relation OneToOne. Cependant, le champ réel définissant la relation doit se trouver sur le modèle en ligne, pas sur le modèle parent - de la même manière que pour une ForeignKey. Basculez-le et cela fonctionnera.

Modifier après commentaire: vous dites que le modèle parent est déjà enregistré auprès de l'administrateur: puis désenregistrez-le et réenregistrez-vous.

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)
73
Daniel Roseman

En référence à la dernière question, quelle serait la meilleure solution pour plusieurs sous-types. Par exemple, classe Produit avec sous-type classe Livre et sous-type classe CD. Comme indiqué ici, vous devez modifier un produit, les éléments généraux plus les éléments de sous-type pour le livre ET les éléments de sous-type pour le CD. Ainsi, même si vous ne souhaitez ajouter qu'un livre, vous obtenez également les champs pour CD. Si vous ajoutez un sous-type, par exemple DVD, vous obtenez trois groupes de champs de sous-types, alors que vous ne voulez en fait qu'un seul groupe de sous-types, dans l'exemple mentionné: les livres.

6
Henri

Peut-être utiliser l'héritage à la place de la relation OneToOne

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

class MyProduct(Product):
    .....

Ou utilisez 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, votre produit sera en ligne.

6
Alexey

Vous pouvez également essayer de définir "parent_link = True" sur votre OneToOneField?

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

1
stephendwolff