Ulfric Storm
Ulfric Storm

Reputation: 129

Get all ManyToManyField-Entries of an object in models.py

I want to have a tag list in the admin panel of my simple blog app. ManyToManyFields aren't allowed as input for list_display so i want to create a method for getting the tags and put this method in the list.

My problem is that i don't know how i can access in my model the other class.

My models.py

class Tag(models.Model):
    tag = models.CharField(max_length=25)

    def __unicode__(self):
        return self.tag


class Post(models.Model):
    author = models.ForeignKey(User)

    publication = models.DateTimeField()

    title = models.CharField(max_length=100)
    summary = models.TextField(max_length=150)
    content = models.TextField(max_length=9999)

    tag = models.ManyToManyField(Tag)

    commentsAllowed = models.BooleanField()

    def getTags(self):
        return Post.tag.all()    <-----------------------------------

    def __unicode__(self):
        return self.title

My admin.py

class PostAdmin(admin.ModelAdmin):
    date_hierarchy = 'publication'
    list_display = ('author', 'title', 'publication', 'getTags')

This returns me <django.db.models.fields.related.ReverseManyRelatedObjectsDescriptor object at 0xb8e24fcc>, but i want the tag names.

Upvotes: 0

Views: 1301

Answers (2)

Michał Bielawski
Michał Bielawski

Reputation: 76

list_display expects its items to be either object (instance) or admin class methods. In both cases they should return something that can be casted to unicode.

I would rather put this in admin class like this:

class PostAdmin(admin.ModelAdmin):
    list_display = ('tags',)

    def tags(self, obj):
        return u", ".join(obj.tag.all())

    def get_queryset(self, request):
        return super(PostAdmin, self).get_queryset(request).prefetch_related('tag')

I added a get_queryset method to modify the queryset in such a way that the tags are now prefetched using a single query. Thanks to this, there are not x queries for x rows displayed in admin.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599778

You want self.tags.all(), as it is the instance that has the relationship, not the class.

Upvotes: 3

Related Questions