编写管理器以过滤查询集结果

6 投票
2 回答
1564 浏览
提问于 2025-04-15 17:19

我有以下这段代码:

class GroupDepartmentManager(models.Manager):
  def get_query_set(self):
    return super(GroupDepartmentManager, self).get_query_set().filter(group='1')

class Department(models.Model):
 name = models.CharField(max_length=128)
 group = models.ForeignKey(Group)
 def __str__(self):
    return self.name
 objects = GroupDepartmentManager()

... 这段代码运行得很好。唯一的问题是,我需要把 group='1' 替换成 group=(由 group = models.ForeignKey(Group) 指定的组)。我在搞清楚这个外键应该传递到类里,还是传递到 get_query_set 函数里,或者其他地方时遇到了麻烦。我知道可以用 group.department_set.filter(group=desired group) 来实现这个功能,但我是在为管理网站写这个模型,所以我需要用一个变量,而不是在等号后面用一个常量。

2 个回答

2

如果你发现创建一个自定义管理器太复杂了,可能需要重新考虑一下组和部门之间的关系。管理器擅长简化常见查询,但在展示模型和模型实例之间复杂关系时就不太行了。

不过,我觉得这篇关于使用自定义管理器过滤模型对象的文章会给你一些启发。作者提出了一种技术,可以调用一个函数,这个函数返回一个自定义的管理器类,里面保存了你指定的过滤参数,这样这些参数就不会传递给实例了。试试看吧!

4

我觉得把默认的 Manager 替换掉,特别是在你打算使用管理后台的时候,可能不是个好主意……即使这样能帮你处理员工信息,但在处理部门时就没什么帮助了。你可以考虑增加一个属性,提供一个对部门的限制视图,和常规的 objects 一起使用?或者把标准的 Managerobjects 移到 _objects,然后把 from_same_group 改名为 objects,如果你真的更喜欢原来的方法的话。

class Department(models.Model):
    name = models.CharField(max_length=128)
    group = models.ForeignKey(Group)
    def __str__(self):
        return self.name
    objects = models.Manager()

    @property
    def from_same_group(self):
        return Department.objects.filter(group__exact=self.group)

另外,我知道你会设置管理后台来利用这个有趣的 Manager;如果你不太清楚(或者我误解了你的问题),可以留言,我会尽快跟进的。


编辑:好的,为了更清楚一点:如果你真的坚持要替换 objects,你可能想这样做:

class Department(models.Model):
    name = models.CharField(max_length=128)
    group = models.ForeignKey(Group)
    def __str__(self):
        return self.name

    _objects = models.Manager()

    @property
    def objects(self):
        # note the _objects in the next line
        return Department._objects.filter(group__exact=self.group)

撰写回答