Ограничить набор запросов полей автозаполнения в Django

У меня есть 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.

Как правильно ограничить набор запросов для поля автозаполнения?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
12
0
1 897
1

Ответы 1

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

Я использую это в модели, которая имеет несколько ForeignKey для одной и той же модели, где мне нужны разные варианты автозаполнения для каждого ForeignKey. Я не разбираюсь в javascript, но выяснил, что ac_field_name заполняется при загрузке страницы и содержит только одно значение, а не одно для каждого поля. Поэтому я вернулся к исходному autocomplete.js и просто добавил field_name: $element.attr('name') в функцию init return dict (не забудьте добавить запятую в предыдущей строке!). Я переопределил autocomplete.js для всего сайта, так как не смог загрузить js-класс Media в ModelAdmin после django-js.

jenniwren 19.01.2021 22:39

Другие вопросы по теме