Django admin search: как переопределить обработчик по умолчанию?
Я хочу настроить способ поиска поисковых запросов по полям поиска.
Есть ли способ сделать это, не взломав глубоко в код Django или создав абсолютно независимый вид?
Например, я хотел бы вернуть объединение запросов для каждого из элементов querystring.split(). Таким образом, поиск "яблочной панели" будет возвращать результаты с помощью Яблока ИЛИ bar, в отличие от поиска по умолчанию, который применяет оператор И.
Ответы
Ответ 1
Это очень легко сделать в django 1.6
ModelAdmin.get_search_results (запрос, запрос, search_term) Новое в Django 1.6.
from django.db.models import Q
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'age')
search_fields = ('name',)
def get_search_results(self, request, queryset, search_term):
# search_term is what you input in admin site
# queryset is search results
queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
search_term_list = search_term.split(' ')#['apple','bar']
# you can also use `self.search_fields` instead of following `search_columns`
search_columns = ('name','age','address')
#convert to Q(name='apple') | Q(name='bar') | Q(age='apple') | ...
query_condition = ' | '.join(['Q(%s="%s")'%(x,y) for x in search_term_list for y in search_columns])
queryset = self.model.objects.filter(eval(query_condition))
return queryset, use_distinct
Ответ 2
вы можете добавить метод ModelAdmin
:
def queryset(self, request):
qs = super(MyModelAdmin, self).queryset(request)
# modify queryset here, eg. only user-assigned tasks
qs.filter(assigned__exact=request.user)
return qs
у вас есть запрос здесь, поэтому большая часть материала может быть зависимой от просмотра, включая параметры URL-адреса, файлы cookie, сеансы и т.д.
Ответ 3
Итак, я использовал код из ответа WeizhongTu и нашел в нем не столь очевидную ошибку. Когда мы пытаемся использовать как фильтрацию, так и поиск с помощью этого кода, фильтрация затеняется этой строкой:
queryset = self.model.objects.filter(eval(query_condition))
Важно использовать ТОЛЬКО предыдущие результаты. Поэтому вы никогда не должны использовать self.model.objects
для получения набора запросов, но только для фильтрации самого запроса. Вот так:
def get_search_results(self, request, queryset, search_term):
# search_term is what you input in admin site
# queryset is the list of objects passed to you
# by the previous functions, e. g. filtering
search_term_list = search_term.split(' ') #['apple','bar']
search_columns = ('name','age','address')
# convert to Q(name='apple') | Q(name='bar') | Q(age='apple') | ...
query_condition = ' | '.join(['Q(%s="%s")'%(x,y) for x in search_term_list for y in search_columns])
appended_queryset = queryset.filter(eval(query_condition))
# queryset is search results
queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
queryset |= appended_queryset
return queryset, use_distinct