Django模型实例方法的模式+;等效QuerySet过滤器?
这与-,我想定义一个基于QuerySet过滤器的布尔实例方法,或者更好地定义一个明显成对的QuerySet过滤器和布尔实例方法 我已经编写了QuerySet/Manager子类来实现基于文档的各种模型的自定义过滤,例如Django模型实例方法的模式+;等效QuerySet过滤器?,django,django-models,django-queryset,Django,Django Models,Django Queryset,这与-,我想定义一个基于QuerySet过滤器的布尔实例方法,或者更好地定义一个明显成对的QuerySet过滤器和布尔实例方法 我已经编写了QuerySet/Manager子类来实现基于文档的各种模型的自定义过滤,例如 class MyModelQuerySet(QuerySet): def visible_to_user(self, user): # Filter logic class MyModelManager(Manager): def get_que
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子类增加了一些麻烦,但至少它将所有逻辑保持在一个地方,这样维护人员就可以很容易地看到依赖关系
这里有关于最佳实践的建议吗?请注意,由于Django 1.7,您不需要定义单独的管理器和queryset-只需定义queryset,并将管理器设置为
MyModelQuerySet.as_manager()
-请参见。谢谢,当我们最终更新到1.7时,这非常有用(我们一直使用Python 2.6,因此Django 1.6)你的过滤器有多复杂?如果它们只是字段/值的东西,那么您可以编写一些东西,在一个方法中将它们转换为一组filter
参数,然后再编写一些东西,根据模型实例检查相同的字段期望值。在某些情况下,过滤器相当复杂,但我喜欢使用一些通用表示法的想法,这些表示法可以定义一次并在两种方法中适当应用。