Можете ли вы фильтровать наборы запросов по пользователю в моделях? - PullRequest
1 голос
/ 28 мая 2019

Я полагаю, что правильный способ фильтрации объектов по пользователям выполняется в представлениях, поскольку вам может быть просто необходим логин и у вас есть доступ к request.user.Но у меня есть представление, которое вызывает метод класса объекта, который не может быть объединен с фильтром, потому что он преобразует набор запросов в объект списка - так что я думаю, если есть способ отфильтровать набор запросов пользователем непосредственно в моделях, тогдакогда я вызываю метод класса в представлениях, объекты уже будут отфильтрованы.

Вот мой взгляд:

def leads_by_city(request):
    # Invoke Lead classmethod to get the data
    data = Lead.objects.get_leads_per_city()

    return JsonResponse(data, safe=False)

Модель с настраиваемым менеджером:

class Lead(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
    source = models.ForeignKey(LeadSource, on_delete=models.CASCADE)
    city = models.CharField(max_length=100)
    objects = LeadManager()


class LeadManager(models.Manager):

    def get_leads_per_city(self):
        queryset = self.values('city').annotate(Count('id')).order_by('city')
        data = list(queryset.values('city', 'id__count'))

        return data

Есть ли способ фильтрации по пользователю в методе класса?Может быть, как:

class LeadManager(models.Manager):

    def get_leads_per_city(self,user):
        queryset = self.filter(user=Lead.user).values('city').annotate(Count('id')).order_by('city')
        data = list(queryset.values('city', 'id__count'))

        return data

1 Ответ

1 голос
/ 29 мая 2019

Да, хотя ваша фильтрация немного отключена, вы можете просто установить .filter(user=user):

class LeadManager(models.Manager):

    def get_leads_per_city(self, user):
        queryset = self.filter(
            <b>user=user</b>
        ).values('city').annotate(Count('id')).order_by('city')
        return list(queryset.values('city', 'id__count'))

Имя параметра <b>user=</b>user действительно не относится к userпараметр функции.ORM Django будет искать поле с этим именем, и мы передаем ему user вызова параметра.

По вашему мнению, вы можете вызвать это с помощью:

def leads_by_city(request):
    # Invoke Lead classmethod to get the data
    data = Lead.objects.get_leads_per_city(<b>request.user</b>)
    return JsonResponse(data, safe=False)
* 1014Как говорится, вы используете механизм Django QuerySet для создания словарей.Это обычно , а не рекомендуется.Возможно, вы захотите использовать Serializer, как это предлагается в Django REST Framework [drf-doc] .

. Кроме того, не рекомендуется передавать список в видеJSON ответ. JSON эксплуатирует с этим, вам лучше обернуть это в словарь.

Поскольку вам требуется вошедший в систему пользователь, также может быть лучше добавить @login_required decorator [Django-doc] здесь, который будет возвращать ответ HTTP перенаправления, если пользователь не вошел в систему:

from django.contrib.auth.decorators import <b>login_required</b>

<b>@login_required</b>
def leads_by_city(request):
    # Invoke Lead classmethod to get the data
    data = Lead.objects.get_leads_per_city(request.user)
    return JsonResponse(<b>{'data'</b>: data<b>}</b>)
...