116 votes

many-to-many dans l'affichage des listes django

class Product(models.Model):
    products = models.CharField(max_length=256)

    def __unicode__(self):
        return self.products

class PurchaseOrder(models.Model):
    product = models.ManyToManyField('Product')
    vendor = models.ForeignKey('VendorProfile')
    dollar_amount = models.FloatField(verbose_name='Price')

J'ai ce code. Malheureusement, l'erreur survient dans admin.py avec l'élément ManyToManyField

class PurchaseOrderAdmin(admin.ModelAdmin):
    fields = ['product', 'dollar_amount']
    list_display = ('product', 'vendor')

L'erreur dit :

'PurchaseOrderAdmin.list_display[0]', 'product' est un champ ManyToManyField qui n'est pas pris en charge.

Cependant, il compile lorsque je prends 'product' de list_display . Alors comment puis-je afficher 'product' sur list_display sans lui donner d'erreurs ?

modifier : Peut-être qu'une meilleure question serait de savoir comment afficher un ManyToManyField sur list_display ?

210voto

karthikr Points 36157

Vous ne pourrez peut-être pas le faire directement. D'après la documentation de list_display

Les champs ManyToManyField ne sont pas supportés, car cela impliquerait l'exécution d'une instruction SQL distincte pour chaque ligne de la table. Si vous voulez néanmoins le faire, donnez à votre modèle une méthode personnalisée et ajoutez le nom de cette méthode à list_display. (Voir ci-dessous pour en savoir plus sur les dans list_display).

Vous pouvez faire quelque chose comme ça :

class PurchaseOrderAdmin(admin.ModelAdmin):
    fields = ['product', 'dollar_amount']
    list_display = ('get_products', 'vendor')

    def get_products(self, obj):
        return "\n".join([p.products for p in obj.product.all()])

OU définir une méthode modèle, et l'utiliser

class PurchaseOrder(models.Model):
    product = models.ManyToManyField('Product')
    vendor = models.ForeignKey('VendorProfile')
    dollar_amount = models.FloatField(verbose_name='Price')

    def get_products(self):
        return "\n".join([p.products for p in self.product.all()])

et dans l'admin list_display

list_display = ('get_products', 'vendor')

24voto

JKV Points 241

Vous pouvez le faire de cette façon, en regardant le snippet suivant :

class Categories(models.Model):
    """ Base category model class """

    title       = models.CharField(max_length=100)
    description = models.TextField()
    parent      = models.ManyToManyField('self', default=None, blank=True)
    when        = models.DateTimeField('date created', auto_now_add=True)

    def get_parents(self):
        return ",".join([str(p) for p in self.parent.all()])

    def __unicode__(self):
        return "{0}".format(self.title)

Et dans votre module admin.py appelez la méthode comme suit :

class categories(admin.ModelAdmin):
    list_display    = ('title', 'get_parents', 'when')

8voto

Lucas B Points 699

Si vous voulez économiser des requêtes supplémentaires, vous pouvez utiliser relatif à la prélecture dans le get_queryset comme ci-dessous :

class PurchaseOrderAdmin(admin.ModelAdmin):
    fields = ['product', 'dollar_amount']
    list_display = ('get_products', 'vendor')

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.prefetch_related('product')

    def get_products(self, obj):
        return ",".join([p.products for p in obj.product.all()])

Según el Docs De cette façon, il n'y aurait qu'une seule requête supplémentaire à effectuer pour récupérer les données relatives à l'entreprise. Product articles de tous PurchaseOrder au lieu d'avoir besoin d'une requête par chaque PurchaseOrder instance.

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