Django, имеющий Q объект фильтра по пользователям full_name - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть простое окно поиска, которое ищет сообщения (фильтрует сообщения) по названию, имени, фамилии, однако, как бы я ни старался, я не могу искать по пользователям полное имя

В моих моделях яиметь

User.full_name = property(lambda u: u"%s %s" % (u.first_name, u.last_name))

В моем терминале Django Shell я получаю следующие результаты

>>> user.first_name
'Blake'
>>> user.last_name
'Lively'
>>> user.full_name
'Blake Lively'

Теперь, когда я пытаюсь выполнить поиск с полным именем пользователя, я получаю следующую ошибку

Связанное поле получило недопустимый поиск: полное_имя

Q(user__full_name__icontains=query)

Ниже приведены мои представления

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q')
        if query:
            queryset = queryset.filter(
                Q(title__icontains=query) | #This works
                Q(user__username__iexact=query) | #This works
                Q(user__first_name__iexact=query) | #This works
                Q(user__last_name__iexact=query) | #This works
                Q(user__full_name__icontains=query) #This Fails what am I doing worng

                )
        return queryset

Пробовал это

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q')

        if ' ' in query:
            query = query.split()
            queryset = queryset.filter(
                chain(User.objects.filter(first_name__icontains=query[0], last_name__icontains=query[1]),
                      User.objects.filter(first_name__icontains=query[1], last_name__icontains=query[0])))

            return queryset
        else:
            queryset = queryset.filter(
                Q(title__icontains=query) |
                Q(user__username__iexact=query) |
                Q(user__first_name__iexact=query) |
                Q(user__last_name__iexact=query)

                )
        return queryset

Получение ошибки

Аргумент типа 'NoneType' не может быть повторен

if ' ' in query:

Ответы [ 2 ]

3 голосов
/ 02 апреля 2019

Использование filter() с таким свойством невозможно, чтобы фильтр работал, это должно быть поле модели.

Проверьте этот поток , чтобы увидеть некоторые возможные обходные пути с помощью менеджеров илианнотации.

Правка для новой ошибки:

Ваш query = self.request.GET.get('q') возвращает None, когда нет q, и вы не можете проверить что-либо в None.Измените эту строку на query = self.request.GET.get('q', ''), поэтому, если q отсутствует, по умолчанию используется пустая строка.

1 голос
/ 03 апреля 2019

Спасибо @gdef_ Приведенный ниже код сделал работу

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q', None)

        if query:
            queryset = queryset.annotate(
                full_name=Concat(
                    'user__first_name',
                    Value(' '),
                    'user__last_name',
                    output_field=CharField()
                )
            ).filter(
                Q(full_name__icontains=query) |
                Q(title__icontains=query) |
                Q(user__username__iexact=query) |
                Q(user__first_name__iexact=query) |
                Q(user__last_name__iexact=query)

                )
        return queryset
...