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