djangodjango-admindjango-listview

Filter urlencode with 2 Level reverse relationship


I have these models:

class Issuer(models.Model):
    name = models.CharField()

    @property
    def investor_count(self):
        return Investment.objects.filter(offering__issuer_id=self.pk).count() or 0

    def __str__(self):
        return self.name

class Offering(models.Model):
    issuer = models.ForeignKey(Issuer, on_delete=models.CASCADE)
    name = models.CharField()

    def __str__(self):
        return self.name

class Investment(models.Model):
    offering = models.ForeignKey(Offering, on_delete=models.CASCADE)
    name = models.CharField()

    def __str__(self):
        return self.name

And I want to display in the Issuer list view the number of investments it has. This is the function I'm currently using,

# link investments to page
def view_investments_link(self, obj):
    count = obj.investor_count
    url = (
        reverse("admin:crowdfunding_investment_changelist")
        + "?"
        + urlencode({"issuer__id": f"{obj.id}"})
    )
    return format_html('<a href="{}">{} Investment(s)</a>', url, count)

view_investments_link.short_description = "NUMBER OF INVESTMENTS"

And this is how it looks:

enter image description here

But the line + urlencode({"issuer__id": f"{obj.id}"}) does not work. It changes my url to http://localhost:8000/app/investment/?e=1. Is there a way to filter Investments using the issuer_id?


Solution

  • if you want to filter Investment by the issuer_id you can simply change the list_filter in ModelAdmin like this

    @admin.register(Investment)
    class Investment_Register(admin.ModelAdmin):
        list_filter = ["offering__issuer__id"]
    

    and then pass the id of issuer to URL like this http://localhost:8000/app/investment/?offering__issuer__id={id-issuer}

    note: if you give an error like this

    (admin.E116) The value of 'list_filter[0]' refers to 'offering__issuer__id', which does not refer to a Field.
    

    add field id minimally to your model