18
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DjangoのAdmin(管理サイト)でManyToManyFieldを使いたいときの方法

Posted at

admin.pyのlist_displayにManyToManyFieldのカラムを指定すると、以下のようなエラーが出ました。

django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
<class 'proj.admin.ArticleAdmin'>: (admin.E109) The value of 'list_display[2]' must not be a ManyToManyField.

あるレコードに対して、ManyToManyFieldで紐付いた別テーブルのデータを管理サイトで一覧表示できると便利そうだと思ったのですが、エラーメッセージによると指定できない仕様のようです。

ただ、以下のようにしてやることで実現可能でしたので、やり方を記録しておきます。

やりたい事

はてなブックマークのように、ドキュメントに対してメタデータが付与される例を想定してください。

イメージ図

対応方法

Author(著者)、Article(記事)、Tag(メタデータ)の3つがあるとします。

Article.metaがManyToManyFieldになっており、リレーション先としてTagを指定しています。

models.py

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=30)

    def __unicode__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey('Author', blank=True, null=True)
    meta = models.ManyToManyField('Tag')

    def __unicode__(self):
        return self.title

class Tag(models.Model):
    name = models.CharField(max_length=30)

    def __unicode__(self):
        return self.name

admin.py

_metaのような任意の名前の関数を定義してやり、list_displayに該当の関数名を指定してやると、先で示した図のようにコンマ区切りで紐付いたデータを一覧表示することができました。

class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', '_meta')

    def	_meta(self, row):
        return ','.join([x.name for x in row.meta.all()])

admin.site.register(Article, ArticleAdmin)

参考資料

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?