Django模型实例方法的模式+等效的QuerySet过滤器?

时间:2015-04-08 20:29:38

标签: django django-models django-queryset

这是How to filter a queryset based on the result of a method on the model class that returns a boolean?的反转 - 我想基于QuerySet过滤器定义一个布尔实例方法,或者甚至更好地定义一个明显配对的QuerySet过滤器和布尔实例方法。

我已经编写了QuerySet / Manager子类,以根据文档为各种模型实现自定义过滤,例如。

class MyModelQuerySet(QuerySet):
    def visible_to_user(self, user):
        # Filter logic

class MyModelManager(Manager):
    def get_queryset(self):
        return MyModelQuerySet(self.model, using=self._db)
    def visible_to_user(self, user):
        return self.get_queryset().visible_to_user(user)

class MyModel(Model):
    objects = MyModelManager()

我需要的是我可以使用模型实例调用的东西。

目前,我正在创建一个仅包含实例的QuerySet,在其上运行过滤器,并查看是否还有任何内容:

class MyModel(Model):
    objects = MyModelManager()
    def visible_to_user(self, user):
        qs = self.__class__.objects.filter(pk=self.pk)
        if hasattr(qs, 'visible_to_user'):
            return qs.visible_to_user(user).exists()
        return False

这很好且通用(它实际上是在mixin中定义的,因此我可以在我的所有模型中使用它)但它效率不高 - 它每次从数据库重新检索实例在许多情况下,对于单个实例的情况,过滤器逻辑的优化程度很低。

简单地在模型上编写面向实例的布尔函数就足够了,我担心维护这个问题会非常棘手 - 基本上对一个版本所做的任何更改都必须反映在另一个版本中,这是更多当他们处于完全不同的阶级时很困难,两者之间没有明显的联系。

我考虑过的一个选项是将两个函数放在一个mixin中,然后每个组件使用适当的版本:

class VisibleToUserMixin(object):
    def _qs_visible_to_user(self, user):
        # QuerySet logic
    def _instance_visible_to_user(self, user):
        # Instance logic

class MyModelQuerySet(VisibleToUser, QuerySet):
    def visible_to_user(self, user):
        return self._qs_visible_to_user(user)

class MyModel(VisibleToUser, Model):
    def visible_to_user(self, user):
        return self._instance_visible_to_user(user)

这为QuerySet和Model子类添加了一些包袱,但至少它将所有逻辑保存在一个地方,维护人员很容易看到依赖。

有关最佳做法的建议吗?

0 个答案:

没有答案