多対多のリスト表示django


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


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

   def __unicode__(self):
       return self.products

私はそのコードを持っています。残念ながら、エラーはadmin.pyにありますManyToManyField

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

エラーは次のように述べています。

'PurchaseOrderAdmin.list_display [0]'、 'product'はサポートされていないManyToManyFieldです。

ただし、を取り出すとコンパイル'product'されlist_displayます。では、エラー'product'list_display出さずに表示するにはどうすればよいですか?

編集:たぶん、より良い質問は、あなたが表示されない方法だろうManyToManyFieldlist_display

回答:


171

直接できない場合があります。のドキュメントからlist_display

ManyToManyFieldフィールドはサポートされていません。これは、テーブルの行ごとに個別のSQLステートメントを実行する必要があるためです。それでもこれを実行する場合は、モデルにカスタムメソッドを指定し、そのメソッドの名前をlist_displayに追加します。(list_displayのカスタムメソッドの詳細については、以下を参照してください。)

あなたはこのようなことをすることができます:

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()])

またはモデルメソッドを定義し、それを使用します

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()])

と管理者で list_display

list_display = ('get_products', 'vendor')

これは本当に良い解決策のように見えます。ありがとうございました。ただし、「列「product_id」のnull値が非null制約に違反している」というエラーが表示されます。これが何を意味するのかわかりますか?
mdjon26 2013

3
これによりデータベースがひざまずくので、パフォーマンスを向上させるためにselect_related()またはprefetch_related()をどのように使用しますか?
クラウド職人2017年

3
念のために最適化問題は、私はまだ、興味深い同じ問題を抱えていたし、あなたは、単に最適化実装できることが判明しているget_queryset()あなたのための方法をModelAdmin、参照stackoverflow.com/questions/12354099/...
ゲッツ

1
@SebastiánVansteenkiste良い考え、多分cached_property助けになるでしょう。しかし、おそらくそうではないと思います。最適化されたを使用する場合get_queryset、たとえば、DjangoではなくSQLで製品の連結を行うように、そこでデータに注釈を付けたり前処理したり、カスタムデータをクエリセットに保存したりできます。次に、プロパティにアクセスするときにすべての行に対してではなく、SQLでそのロジックを1回だけ実行する必要があります。
ゲッツ

1
いい視点ね。私は自分が最適化されたことになりますget_queryset、私は完全なドキュメントを読んだ程度だ(でも、私がやるべきことの簡単な例は十分あります)していない
セバスティアンVansteenkiste

16

このようにして、次のスニペットをチェックアウトしてください。

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)

そして、admin.pyモジュールで次のようにメソッドを呼び出します。

class categories(admin.ModelAdmin):
    list_display    = ('title', 'get_parents', 'when')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.