在Django-Admin中,您可以在模型的字段上定义list_filter。这适用于ManyToMany-Fields。
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的元素列表。
现在我的问题:是否可以按ModelA的多个对象进行过滤?
在ModelB的change_view中,我使用django-autocomplete-light来定义关系。我是否可以使用此小部件在change_list中进行过滤?
我想象这个过滤器的背景中的查询,如ModelB.objects.filter(model_a_relation__in=names)
,其中names是ModelA所选对象的列表。
谢谢,霍斯特
答案 0 :(得分:4)
我做了一个非常脏的尝试来解决我的问题。它有效,我想与你分享。
为了更好地理解,我在本例中使用了新模型:
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
。
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参数。
然后我的覆盖了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
- 过滤器,我可以激活多个选项。通过单击过滤器,会向查询添加新ID。再次单击已选择的选项将从查询中删除id。点击全部从网址中删除洞tags_in
- 参数。
答案 1 :(得分:0)
允许用户在更改列表视图中使用自动填充的另一个选项:
设置ModelAdmin.search_fields
以搜索自动填充所服务的字段,即。
class ModelBAdmin(ModelAdmin):
search_fields = ['model_a_relation__name']
override the changelist tomplate至spawn an autocomplete on the search input:
<script type="text/javascript">
$(document).ready(function() {
$('#searchbar').yourlabsAutocomplete({
url: '{% url 'autocomplete_light_autocomplete' 'YourAutocompleteName' %}',
choiceSelector: '[data-value]',
}).input.bind('selectChoice', function(e, choice, autocomplete) {
$(this).val(choice.text())
.parents('form').submit();
});
});
</script>
确保添加此脚本后没有JS错误!