【问题标题】:Django admin list_filter ForeignKey with large related table具有大型相关表的 Django 管理员 list_filter ForeignKey
【发布时间】:2018-02-19 22:24:06
【问题描述】:

我有这个模型:

class Post(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField()
    user = models.ForeignKey('users.User')

还有这个 ModelAdmin:

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

过滤效果很好,但我遇到了这样的问题。在我的情况下,users.User 表非常大,所以当 Django 渲染PostAdmin 页面时,渲染所有用户需要太多时间。

所以我想知道是否可以在不渲染所有相关对象的情况下将 Django Admin 过滤器与 ForeignKey 一起使用,例如用于过滤器的 raw_id_fields 小部件?

【问题讨论】:

  • 您正在寻找limit_choices_to。
  • @BurhanKhalid 感谢您的回复。但我需要有机会在过滤器中选择我想要的任何用户,没有限制,所以limit_choices_to 不是我的解决方案。

标签: django django-admin


【解决方案1】:

我能想到的最佳解决方案是使用 raw_id_field 小部件自定义过滤器。

创建模板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>

创建新的过滤器类并覆盖默认模板:

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

将UserFilter设置为ModelAdmin中用户字段的过滤器类:

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

这将为user 过滤器设置 raw_id_field 小部件并提高页面呈现性能。

【讨论】:

    【解决方案2】:

    我刚刚发现 https://github.com/lincolnloop/django-salmonella 看起来这将为任何 FK 提供原始 id 过滤器。

    # pip install django-salmonella

    from salmonella.admin import SalmonellaMixin
    from salmonella.filters import SalmonellaFilter
    
    class UserProfileAdmin(SalmonellaMixin, admin.ModelAdmin):
       list_filter = (
           ('salmonella_fk', SalmonellaFilter),
       )
    

    您还可以清理 grapelli https://www.abidibo.net/blog/2015/02/06/pretty-raw_id_fields-django-salmonella-and-django-grappelli/ 的样式

    在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>
    

    和app/templates/salmonella/multi_label.html

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

    和一个样式表:

    .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;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-09
      • 2011-10-08
      • 2019-03-12
      • 1970-01-01
      • 2019-05-10
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 2019-02-03
      相关资源
      最近更新 更多