您可以按模型过滤用户的查询集吗?

时间:2019-05-28 20:59:26

标签: django django-models django-views

我认为按用户筛选对象的正确方法是在视图中完成的,因为您可以轻松地要求登录并且可以访问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 个答案:

答案 0 :(得分:1)

是的,尽管您的过滤功能有些不完善,但您只需设置.filter(user=user)

class LeadManager(models.Manager):

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

user=user参数名称​​不是引用函数的user参数。 Django ORM将查找具有该名称的字段,然后我们将其传递给参数调用的user

在您看来,您可以通过以下方式调用它:

def leads_by_city(request):
    # Invoke Lead classmethod to get the data
    data = Lead.objects.get_leads_per_city(request.user)
    return JsonResponse(data, safe=False)

话虽如此,您在这里使用Django的QuerySet机制生成字典。通常是可取的。您可能要使用Serializer, as is offered by the Django REST Framework [drf-doc]

此外,将列表作为JSON响应传递也不是一个好主意。有了JSON exploits,您最好将其包装在字典中。

由于您需要登录的用户,因此最好在此处添加@login_required decorator [Django-doc],如果用户尚未登录,这将返回HTTP重定向响应:

from django.contrib.auth.decorators import login_required

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