'Django admin display many-to-many field as links

Trying to get my Django admin to display a list of related objects as hyperlinks to those objects. These objects are related through a many-to-many relationship.

Using a combination of this answer and this answer, I came up with:

class MyObject(models.Model):
    related = models.ManyToManyField(RelatedObject)

class RelatedObject(models.Model):
    name = models.CharField(max_length=191)

class MyAdmin(admin.ModelAdmin):
    list_display = ("rel")

    def rel(self, obj):
        return[self.link_to_object(related_object) for related_object in obj.related.all()]

    def link_to_object(self, obj):
        link = reverse("admin:<app>_relatedobject_change", args=[obj.id])
        return format_html(f"<a href={link}>{obj.name}</a>")

However, this gives me a list of hrefs, not a list of links.

If I instead change:

    def rel(self, obj):
        return self.link_to_object(obj.related.get(pk=1))

It returns a nice link (where that relationship exists), but I can't get this to replicate when multiple objects are retrieved.

Is there a way to get admin to return a list of hyperlinks?

I'll note that there's also this linkify method floating around, but it only works for a ForeignKey, not many-to-many, and I don't see how to adapt it.



Solution 1:[1]

I don't know any other right way, but I did it using the HTML list tag:

def rel(self, obj):
    return self.links_to_objects(obj.related.all())

@classmethod
def links_to_objects(cls, objects):
    rel_list = "<ol>"
    for obj in objects:
        link = reverse("admin:<your_app>_<your_rel_model_lower>_change", args=[obj.id])
        rel_list += "<li><a href='%s'>%s</a></li>" % (link, obj.name)
    rel_list += "</ol>"
    return format_html(rel_list)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Aa19