72 votes

Django Admin: OneToOne Relation comme un inline?

Je mets ensemble les admin pour un satchmo application. Satchmo utilise OneToOne relations d'étendre la base Product modèle, et j'aimerais le modifier tout sur une seule page.

Il est possible d'avoir une relation OneToOne en ligne? Si non, quel est le meilleur moyen d'ajouter un peu de champs à une page de mon admin qui finira par être mis en 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 admin, 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)

Qui génère cette erreur: <class 'satchmo.product.models.Product'> has no ForeignKey to <class 'my_app.models.MyProduct'>

Est la seule façon pour ce faire, un Formulaire Personnalisé?

edit: Juste essayé le code suivant pour ajouter les champs directement... ne fonctionne pas:

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

82voto

Daniel Roseman Points 199743

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, et non sur le parent, de la même manière que pour une clé étrangère. Basculez-le et cela fonctionnera.

Éditer après le commentaire : vous dites que le modèle parent est déjà enregistré auprès de l’administrateur: annulez-le puis 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)
 

9voto

Levon Points 289

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 intégré.

5voto

Henri Points 182

Se référant à la dernière question, quelle serait la meilleure solution pour plusieurs sous-types. E. g Produit de classe avec le sous-classe du type de Livre et de la sous-classe du type de CD. La façon illustrée ici que vous auriez à modifier un produit, le général articles, plus le sous-type des éléments du livre ET de la sous-éléments de type CD. Donc, même si vous ne voulez ajouter un livre, vous obtenez également les champs pour les CD. Si vous ajoutez un sous-type par exemple DVD, vous obtenez trois sous-champ type de groupes, alors qu'en fait vous voulez seulement un sous-type du groupe, dans l'exemple cité: livres.

2voto

stephendwolff Points 99

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X