使用RelatedManager的Django自定义管理器

时间:2009-10-27 22:23:29

标签: django

此处super(InviteManager, self).get_query_set()一定存在问题,但我不知道该使用什么。当我查看用户实例的RelatedManager时,

len(Invite.objects.by_email()) == len(user.invite_set.by_email())

即使用户没有任何邀请。但是,user.invite_set.all()正确返回所有键入User对象的Invite对象。

class InviteManager(models.Manager):
    """with this we can get the honed querysets like user.invite_set.rejected"""

    use_for_related_fields = True

    def by_email(self):
        return super(InviteManager, self).get_query_set().exclude(email='')

class Invite(models.Model):
    """an invitation from a user to an email address"""

    user = models.ForeignKey('auth.User', related_name='invite_set')
    email = models.TextField(blank=True)
    objects = InviteManager()

'''
u.invite_set.by_email() returns everything that Invite.objects.by_email() does
u.invite_set.all() properly filters Invites and returns only those where user=u
'''

4 个答案:

答案 0 :(得分:3)

您可能需要一个实现by_email过滤器的自定义QuerySet。请参阅Subclassing Django QuerySets上的示例。

class InviteQuerySet(models.query.QuerySet):
    def by_email(self):
       return self.exclude(email='')

class InviteManager(models.Manager):
    def get_query_set(self):
        model = models.get_model('invite', 'Invite')
        return InviteQuerySet(model)

答案 1 :(得分:2)

尝试:

def by_email(self):
    return super(InviteManager, self).exclude(email='')

如果不出意外,.get_query_set()是多余的。在这种情况下,它可能返回一个全新的查询集,而不是优化当前的查询集。

答案 2 :(得分:1)

当您替换相关集的默认管理器时,文档指定您should not filter the queryset使用get_query_set()。

  

请勿过滤掉此类经理子类中的任何结果

     

使用自动管理器的一个原因是访问与其他模型相关的对象。在这些情况下,Django必须能够查看它所获取的模型的所有对象,以便可以检索所引用的任何内容。

     

如果覆盖get_query_set()方法并过滤掉任何行,Django将返回不正确的结果。不要那样做。在get_query_set()中过滤结果的管理器不适合用作自动管理器。

答案 3 :(得分:0)

尝试使用.all()代替.get_query_set()。这似乎解决了我遇到的类似问题。

def by_email(self):
    return super(InviteManager, self).all().exclude(email='')