Django管理员change_list过滤多个ManyToMany [英] Django Admin change_list filtering multiple ManyToMany

查看:96
本文介绍了Django管理员change_list过滤多个ManyToMany的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Django-Admin中,您可以在模型的字段上定义list_filter.这也适用于ManyToMany-Fields.

In the Django-Admin you have the possibility to define list_filter on fields of the model. This is working for ManyToMany-Fields as well.

class ModelA(models.Model):
    name = models.CharField(max_length=100, verbose_name="Name")

class ModelB(models.Model):
    model_a_relation = models.ManyToManyField(ModelA)

class ModelBAdmin(ModelAdmin):
    list_filter = [model_a_relation, ]

admin.site.register(ModelB, ModelBAdmin)

现在,我可以在ModelB的admin object_list中通过与ModelA的关系来过滤我的ModelB元素列表.

Now, I can filter my list of elements of ModelB by relation to ModelA in the Admin object_list of ModelB.

现在我的问题是:是否可以按ModelA的多个对象进行过滤?

Now my question: Is it possible to filter by multiple objects of ModelA?

在ModelB的change_view中,我使用django-autocomplete-light定义关系.我也可以使用此小部件来过滤change_list吗?

In the change_view of ModelB I use django-autocomplete-light to define relations. Can I use this widget to filter in change_list, too?

我想像像ModelB.objects.filter(model_a_relation__in=names)这样的过滤器背景中的查询,其中名称是ModelA所选对象的列表.

I imagine the query in the background of this filter like ModelB.objects.filter(model_a_relation__in=names), where names is a list of the chosen objects of ModelA.

谢谢,霍斯特

推荐答案

我真的很努力地尝试解决我的问题.它有效,我想与您分享.

I made a really dirty try to solve my issue. It works and I want to share it with you.

为了更好地理解,我在此示例中使用了新模型:

For better understanding I use new Models in this example:

class Tag(models.Model):
    name = models.CharField(max_length=100, verbose_name="Name")

class Book(models.Model):
    tags = models.ManyToManyField(Tag)
    read = models.BooleanField()

class BookAdmin(ModelAdmin):
    list_filter = ['read', ]

admin.site.register(Book, BookAdmin)

起初,我改写了BookAdmin的changelist_view.

At first, I overwrote the changelist_view of the BookAdmin.

def changelist_view(self, request, extra_context=None):

    extra_context = extra_context if extra_context else {}

    q = request.GET.copy()

    tags = Tag.objects.all().values('id', 'name')

    current_tags = q.get('tags__id__in', [])
    tag_query = request.GET.copy()
    if current_tags:
        tag_query.pop('tags__id__in')
        current_tags = current_tags.split(',')
        all_tag = False
    else:
        all_tag = True
    for tag in tags:
        if str(tag['id']) in current_tags:
            tag['selected'] = True
            temp_list = list(current_tags)
            temp_list.remove(str(tag['id']))
            tag['tag_ids'] = ','.join(temp_list)
        else:
            tag['selected'] = False
            tag['tag_ids'] = ','.join(current_tags)

    extra_context['tag_query'] = '?' if len(tag_query.urlencode()) == 0 else '?' + tag_query.urlencode() + '&'
    extra_context['all_tag'] = all_tag
    extra_context['tags'] = tags

    return super(BookAdmin, self).changelist_view(request, extra_context=extra_context)

如您所见,我在GET中查看是否选择了一些标签.然后,我为每个可能的标记构建新的GET-Parameter.

As you can see, I look in GET, whether there some Tags are chosen or not. Then I build new GET-Parameter for each possible Tag.

然后是我覆盖的change_list.html

And then there is my overwriten change_list.html

{% extends "admin/change_list.html" %}

{% block content %}
    {{ block.super }}

    <h3 id="custom_tag_h3"> Fancy Tag filter</h3>
    <ul id="custom_tag_ul">

        <li{% if all_tag %} class="selected"{% endif %}>
            <a href="{{ tag_query }}">All</a>
        </li>

        {% for tag in tags %}
            <li{% if tag.selected %} class="selected"{% endif %}>
                <a href="{{ tag_query }}tags__id__in={{ tag.tag_ids }}{% if not tag.selected %}{% if tag.tag_ids %},{% endif %}{{ tag.id }}{% endif %}">{{ tag.name }}</a>
            </li>
        {% endfor %}

    </ul>

    <script type="text/javascript">
        $('#changelist-filter').append($('#custom_tag_h3'));
        $('#custom_tag_h3').after($('#custom_tag_ul'));
    </script>

{% endblock content %}

这样,我得到了一个类似于布尔值read -filter的过滤器,在其中可以激活多个选项.通过单击过滤器,新的ID将添加到查询中.再次单击已选择的选项将从查询中删除ID.单击全部,从URL中删除孔tags_in-参数.

This way I have a filter looking like the boolean read-filter where I can activate more than one option. By clicking on the filter, a new id is added to the query. Another click on already selected option removes id from query. Click on All removes the hole tags_in-parameter from URL.

这篇关于Django管理员change_list过滤多个ManyToMany的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆