[Django]-Django admin list_filter ForeignKey with large related table

1๐Ÿ‘

โœ…

I just found https://github.com/lincolnloop/django-salmonella looks like this will provide a raw id filter for any FK.

# pip install django-salmonella

from salmonella.admin import SalmonellaMixin
from salmonella.filters import SalmonellaFilter

class UserProfileAdmin(SalmonellaMixin, admin.ModelAdmin):
   list_filter = (
       ('salmonella_fk', SalmonellaFilter),
   )

You can also clean up the styling for grapelli https://www.abidibo.net/blog/2015/02/06/pretty-raw_id_fields-django-salmonella-and-django-grappelli/

in app/templates/salmonella/admin/widgets/salmonella_field.html

{{ hidden_input }}
<a onclick="return showRelatedObjectLookupPopup(this);" id="lookup_id_{{ name }}" data-name="{{ name }}" data-app="{{ app_name }}" data-model="{{ model_name }}" class="related-lookup" href="{{ related_url }}{{ url }}"><img width="16" height="16" alt="Consultazione" src="/static/admin/img/selector-search.gif"></a>
<a data-name="developers" data-app="{{ app_name }}" data-model="{{ model_name }}" class="salmonella-clear-field"></a>
<span class="salmonella_label" id="{{ name }}_salmonella_label"></span>

and app/templates/salmonella/multi_label.html

{% for object in objects %}
    <a href="{{ object.1 }}" >{{ object.0 }}</a>{% if not forloop.last %} {% endif %}
{% endfor %}

AND a style sheet:

.salmonella-clear-field {
    background-image: url("/static/grappelli/images/icons/related-remove.png");
    background-repeat: no-repeat;
    background-position: center center;
    display: inline-block;
    position: relative;
    top: 5px;
    margin: 0 5px 0 10px;
    height: 15px;
    width: 15px;
    cursor: pointer;
}
.salmonella_label {
    position: inline-block;
    position: relative;
    top: 2px;
}
.salmonella_label a {
    background: #fff;
    padding: 2px 5px;
}

2๐Ÿ‘

The best solution I was able to figure out is customize Filter with raw_id_field widget.

Create template user_filter.html:

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<script type="text/javascript">var go_from_select = function(opt) { window.location = window.location.pathname + opt };</script>
<h3>{{ title }}</h3>
<div class="admin-filter-user" style="margin-left:15px">
    <input type="text" style="display:inline-block;" name="{{title}}" value="{{ request.GET.user__id__exact }}" id="id_{{title}}" class="vForeignKeyRawIdAdminField"/>
    <a href="{% url 'admin:users_user_changelist' %}" class="related-lookup" style="display:inline-block;" id="lookup_id_{{title}}" title="Lookup"></a>
    <input type="button" onclick="go_from_select('?user__id__exact='+id_user.value)" value="Filter" />
    <a href="#" style="display:inline-block; margin-left:7px" onclick="go_from_select('')">clear</a>
</div>

Create new Filter class and override default template:

class UserFilter(admin.RelatedFieldListFilter):
    """Raw_id_filter for user field"""
    template = 'admin/user_filter.html'

Set UserFilter as filter class for user field in ModelAdmin:

class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'user']
    list_filter = [('user', UserFilter)]

This will set raw_id_field widget for user filter and increase page rendering performance.

Leave a comment