django-queryset的多态遗传
django-polymorphic-queryset的Python项目详细描述
django多态查询集
帮助实现依赖于模型类型的筛选逻辑。
不应混淆筛选和权限检查。如果您需要根据用户获取项目,您可能应该 使用django权限。
安装
pip install django-polymorphic-queryset
动机
例如,您的应用程序有两个模型:Product
并从中派生出来PerishableProduct
:
fromdjango.dbimportmodelsclassProduct(models.Model):name=models.CharField(max_length=120)classPerishableProduct(Product):is_perished=models.BooleanField(default=False)classBrokenProduct(Product):repaired=models.BooleanField(default=False)
如果要添加返回active产品(未损坏和修复的产品)的视图 这个层次结构可能以一个包含所有条件的函数结束:
fromdjango.dbimportmodelsclassProductQuerySet(models.QuerySet):defget_active_products(self):returnself.filter(perishableproduct__is_perished=False,brokenproduct__repaired=True)
在具有许多模型和条件的大型应用程序中,此函数可能变得复杂且难以维护。 此外,通过这个实现,queryset将知道派生模型的详细信息。
可在并行层次结构中分离queryset筛选器方法,以便派生的queryset将添加自定义逻辑 以方法为基础或覆盖它们:
# Not a real example, just the idea.fromdjango.dbimportmodelsclassProductQuerySet(models.QuerySet):defget_active_products(self):returnself.all()classPerishableProductQuerySet(ProductQuerySet):defget_active_products(self):returnself.filter(is_perished=False)classBrokenProductQuerySet(ProductQuerySet):defget_active_products(self):returnself.filter(repaired=True)
但是在这个实现中ProductQuerySet
将返回所有产品,包括保存的产品
当PerishableProduct
的is_perished
等于True
,而BrokenProduct
的repaired
等于False
。
溶液
这个库允许您创建考虑到queryset中所有条件的多态queryset。
层次结构(注意,查询函数属于类,而不是类实例,用作@classmethod
装饰器):
frompolymorphic_querysetimportQueryable,queryfromdjango.dbimportmodelsclassProductQuerySet(Queryable,models.QuerySet):model_name="Product"@query()defget_active_products(cls):returnquery.all()classPerishableProductQuerySet(ProductQuerySet):model_name="PerishableProduct"@query()defget_active_products(cls):returnmodels.Q(is_perished=False)classBrokenProductQuerySet(ProductQuerySet):model_name="BrokenProduct"@query()defget_active_products(cls):returnmodels.Q(repaired=True)
此实现基于指定的模型名在不同的查询集之间分离查询条件。
ProductQuerySet.get_active_products
将返回任何保存为Product
的产品,
如果is_perished
为false且BrokenProduct
为repaired
为true则保存为PerishableProduct
的产品。
queryset仍将返回Product
实例。
您可以使用django多态库来返回派生类的实例。
现在,您可以将这些查询集用作模型管理器:
fromdjango.dbimportmodelsclassProduct(models.Model):objects=ProductQuerySet.as_manager()classPerishableProduct(Product):objects=PerishableProductQuerySet.as_manager()classBrokenProduct(Product):objects=BrokenProductQuerySet.as_manager()active_products=Product.objects.get_active_products()
要在查询集中使用基类的条件,可以调用用query
修饰的方法的conditions
函数:
frompolymorphic_querysetimportQueryable,queryfromdjango.dbimportmodelsimportdatetimeclassProductQuerySet(Queryable,models.QuerySet):model_name="Product"@query()defget_new_products(cls):returnmodels.Q(date_created__gte=datetime.datetime.now()-datetime.timedelta(weeks=1))classPerishableProductQuerySet(ProductQuerySet):model_name="PerishableProduct"@query()defget_new_products(cls):returnsuper().get_new_products.conditions()&models.Q(date_perished__lt=datetime.datetime.now())
在本例中,get_new_products
将返回不到一周前创建的任何Product
,或者
PerishableProduct
如果它是一周前创建的,今天不会消亡。