Ограничить набор запросов автозаполнения полей в Django - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть ModelAdmin в Django 2.1.3, например:

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 написан для "традиционных" полей внешнего ключа.Для поля автозаполнения он обеспечивает отображение ошибки при выборе тест-набора вне набора запросов.Однако это не ограничивает результаты, найденные в поле автозаполнения.Документация не содержит никаких ограничений для пользовательских наборов запросов. Этот ответ связан, но касается только авторизации.

Возможно переопределить get_search_result метод связанного ModelAdmin.

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 голосов
/ 05 мая 2019

Вы можете переопределить статический файл Django autocomplete.js в 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 выглядеть лучше, но в принципе это работает так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...