限制Django中自动完成字段的查询集

时间:2018-11-15 14:59:06

标签: python django python-3.x

我在Django 2.1.3中有一个ModelAdmin,如下所示:

class BoxAdmin(admin.ModelAdmin):
    autocomplete_fields = ['testkit']

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'testkit':
            kwargs['queryset'] = Barcode.objects.exclude(testkit__in=Box.objects.all().values('testkit'))
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

formfield_for_foreignkey方法是为“传统”外键字段编写的。对于自动完成字段,它确保在选择查询集之外的测试包时显示错误。但是,它并不限制在自动完成字段中找到的结果。 documentation没有提到对自定义查询集的任何限制。 This answer是相关的,但仅涉及授权。

可以覆盖相关ModelAdmin的{​​{3}}方法。

class TestkitAdmin(admin.ModelAdmin):
    search_fields = ['number']

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        if 'autocomplete' in request.path:
            queryset = queryset.exclude(testkit__in=Box.objects.all().values('testkit'))
        return queryset, use_distinct

但是我找不到确定搜索请求来自哪个自动完成字段的方法。因此,我只能对其编程,以满足一个引用ModelAdmin的需求。

如何正确限制自动完成字段的查询集?

1 个答案:

答案 0 :(得分:0)

您可以在autocomplete.js中覆盖Django static/admin/js/autocomplete.js静态文件。 Django将始终喜欢您已覆盖的文件。

然后在覆盖的文件中修改djangoAdminSelect2()函数,如下所示:

$.fn.djangoAdminSelect2 = function(options) {
    var settings = $.extend({}, options);
    $.each(this, function(i, element) {
        var $element = $(element);

        $.extend(settings, {
            'ac_field_name': $element.parents().filter('.related-widget-wrapper').find('select').attr('name')
        });

        init($element, settings);
    });
    return this;
};

init()函数如下:

var init = function($element, options) {
    var settings = $.extend({
        ajax: {
            data: function(params) {
                return {
                    term: params.term,
                    page: params.page,
                    field_name: options.ac_field_name
                };
            }
        }
    }, options);
    $element.select2(settings);
};

然后在您的get_search_results()中,仅访问请求GET参数field_name并瞧瞧。

您当然可以使JS看起来更好,但原则上它是这样工作的。