Django администраторско търсене: как да замените манипулатора по подразбиране?

Искам да персонализирам начина, по който заявките за търсене в search_fields.

Има ли начин да го направите, без да хакнете дълбоко кода на Django или да създадете напълно независим изглед?

Например, бих искал да върна обединението на наборите от заявки за всеки от елементите на querystring.split(). Така че търсенето на "apple bar" ще върне резултати с ИЛИ ябълка ИЛИ лента, за разлика от търсенето по подразбиране, което прилага оператор AND.


person GJ.    schedule 21.08.2010    source източник
comment
Моля, опишете какво точно поведение искате да постигнете. В идеалния случай дайте пример.   -  person Ihor Kaharlichenko    schedule 22.08.2010
comment
Актуализирах отговора си, можете да го прочетете и редактирате, след което опитайте   -  person WeizhongTu    schedule 10.04.2014


Отговори (3)


Много е лесно да направите това в django 1.6

ModelAdmin.get_search_results(заявка, набор от заявки, search_term) Ново в Django 1.6.

import operator
# from django.utils.six.moves import reduce  # if Python 3
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 = reduce(operator.or_, [Q(**{c:v}) for c in search_columns for v in search_term_list])

        queryset = self.model.objects.filter(query_condition)
        # NOTICE, if you want to use the query before
        # queryset = queryset.filter(query_condition)
        return queryset, use_distinct
person WeizhongTu    schedule 18.02.2014
comment
Това има уязвимост при отдалечено изпълнение на код. Няма нужда да използвате eval за изграждане на Q обекти. - person Gavin Wahl; 04.10.2018
comment
@GavinWahl eval беше премахнат чрез operator.or_ и reduce, наздраве - person WeizhongTu; 11.10.2018

Така че използвах кода от отговора на 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
person Dmitry Orlov    schedule 02.11.2017

можете да добавите 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 параметри, бисквитки, сесии и т.н.

person Jerzyk    schedule 25.03.2011