Django在filter()之后使用模型管理器方法

时间:2019-05-22 15:57:08

标签: django django-models django-views

我正在使用Django 2.2

我有一个视频模型,该模型具有在模型管理器中定义的自定义方法

class VideoManager(models.Manager):
    def completed(self):
        return self.get_queryset().filter(status=self.model.STATUS_POST_COMPLETE)


class Video(models.Model):
    STATUS_UPLOADED = 'uploaded'
    STATUS_POST_COMPLETE = 'post_complete'

    STATUSES = (
        (STATUS_UPLOADED, 'Uploaded'),
        (STATUS_POST_COMPLETE, 'Post Complete'),
    )

    campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE)
    title = models.CharField(max_length=250)
    video = models.FileField(upload_to=user_upload_directory_path)
    status = models.CharField(choices=STATUSES, default=STATUS_UPLOADED, blank=True, max_length=50)

    objects = VideoManager()

在查看文件中,我想获取完成视频的数量

class VideoListView(generic.ListView):
    template_name = 'videos/list.html'
    model = Video

    def get_queryset(self):
        return self.model.objects.filter(campaign__user=self.request.user)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        stats = {
            'total': self.get_queryset().count(),
            'completed': self.get_queryset().completed().count()
        }
        context['stats'] = stats

        return context

我正在使用self.get_queryset()进行用户过滤,然后使用模型管理器方法获取所有完整的视频。

我遵循这种方法来减少重复的变量。

但这会导致错误

AttributeError: 'QuerySet' object has no attribute 'completed'

1 个答案:

答案 0 :(得分:3)

因为completed()Manager方法,而不是QuerySet方法。您还需要实现自定义QuerySetManager方法不可链接。返回Manager后,您将无法再使用QuerySet方法。像(all()filter()annotate()exclude())之类的方法,都在Manager级别和QuerySet级别上实现。

请参阅此link

models.py

class VideoQuerySet(models.QuerySet):

    def completed(self):
        return self.filter(status=self.model.STATUS_POST_COMPLETE)

class VideoManager(models.Manager):

    def get_queryset(self):
        return VideoQuerySet(model=self.model, using=self._db)

    def completed(self):
        return self.get_queryset().completed()

class Video(models.Model):
    STATUS_UPLOADED = 'uploaded'
    STATUS_POST_COMPLETE = 'post_complete'

    STATUSES = (
        (STATUS_UPLOADED, 'Uploaded'),
        (STATUS_POST_COMPLETE, 'Post Complete'),
    )

    campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE)
    title = models.CharField(max_length=250)
    video = models.FileField(upload_to=user_upload_directory_path)
    status = models.CharField(choices=STATUSES, default=STATUS_UPLOADED, blank=True, max_length=50)

    objects = VideoManager()

video_qs = Video.objects.filter(**lookup_kwargs).completed()
# or
video_qs = Video.objects.completed()

根据需要。希望我没有记错。