如何从客户端输入筛选ModelAdmin自动完成_字段结果

2024-09-28 22:36:28 发布

您现在位置:Python中文网/ 问答频道 /正文

这是此线程的后续操作: How to filter ModelAdmin autocomplete_fields results with the context of limit_choices_to

Uberdude提出了一个解决方案,它可以根据触发请求的字段定制autoselect queryset,但我还需要根据客户端的输入进行过滤,最具体的是一个复选框,它不是一个模型字段,并且仅适用于此表单摘录中表单中的一些字段

Form

我通过覆盖AutocompleteSelect小部件将复选框应用于小部件,如下所示:

class AutocompleteSelectCb(AutocompleteSelect):
def render(self, name, value, attrs=None):
    s = super().render(name, value, attrs)
    return mark_safe('<div style="margin-bottom:10px;"><input type="checkbox" id="parent1"\
         name="parentx" value="1">Search among all kennels</div>' + s)

并且仅当字段出现在admin中的autocomplete_cb_fields属性中时才使用该小部件:

 autocomplete_fields = ['breed']
 autocomplete_cb_fields = ['father', 'mother']

但是,我不知道如何让我的AutocompleteSelectCb小部件发送复选框的状态,以便在get_search_results方法中处理它。我想用一些js,但是怎么做呢?有什么想法吗


Tags: tonamediv表单fieldsvalue部件render
1条回答
网友
1楼 · 发布于 2024-09-28 22:36:28

我最终能够通过使用thispost中介绍的方法解决这个问题,即向referer URL添加querystring键,因为select2在初始化后不接受对请求URL的修改。 我还添加了关于正在编辑的狗的其他信息,例如它的id和出生年份,以进一步过滤查询集(狗不能是自己的父母或父母比自己小,母亲只能是雌性…)

//this get passes to the select2:opening event listener
function expand_ajax_location_search($, fieldId) {
    if (!$) {
        $ = django.jQuery;
    }
    var pageURL = $(location).attr("href");
    var match = pageURL.match(/\/.*\/(\d+)\/change/);
    return `&birth_year=${$('#id_birth_year').val()}&dog_id=${match[1]}&father_cb=${$('#father-cb').prop( "checked" )}&mother_cb=${$('#mother-cb').prop( "checked" )}`
}

最后,在服务器端进行过滤是一项挑战,因为狗狗管理员通常由犬舍进行过滤,因此每个犬舍所有者只能编辑他们的狗,尽管复选框允许他们使用其他犬舍的狗作为父母。get_search_results方法中的挑战是在复选框时取消筛选queryset,这是无法完成的,因此在将它传递给super()之前创建一个新的。 此外,base get_search_results方法似乎可以遍历所有关系,即使它们不需要,也会导致100多个查询,因此在所有关系上使用select_related只生成一个查询

def get_search_results(self, request, queryset, search_term):
    if request.is_ajax and '/autocomplete/' in request.path and request.GET.get('model_name') == 'dog':
        url = urllib.parse.urlparse(request.headers['Referer'])
        referer = url.path
        # (parse_qs results are lists)
        qs = urllib.parse.parse_qs(url.query)
        if request.GET.get('field_name') == 'father':
            if qs.get('father_cb')[0] == 'true':
                # default is filetered by kennel so need new qs
                queryset = Dog.objects.select_related(
                    'kenn', 'img', 'father', 'mother', 'breeder').order_by('name')
            queryset, use_distinct = super().get_search_results(request, queryset, search_term)
            queryset = queryset.exclude(
                sex='F').exclude(id=qs.get('dog_id')[0])
        elif request.GET.get('field_name') == 'mother':
            if qs.get('mother_cb')[0] == 'true':
                # default is filetered by kennel so need new qs
                queryset = Dog.objects.select_related(
                    'kenn', 'img', 'father', 'mother', 'breeder').order_by('name')
            queryset, use_distinct = super().get_search_results(request, queryset, search_term)
            queryset = queryset.exclude(
                sex='M').exclude(id=qs.get('dog_id')[0])
        birth_year = qs.get('birth_year')[0]
        if birth_year:
            queryset = queryset.exclude(birth_year__gt=birth_year)
    else:
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
    return queryset, use_distinct

相关问题 更多 >