Django模型的声明性注释和预取
prepared-properties的Python项目详细描述
Django制备特性
Django模型的声明性注释和预取。在
我们经常会发现自己写了很多非常复杂的注释 预取。当这些在整个项目中使用时,定义它们的逻辑 在queryset方法中有点隐藏(如果注释 相互依赖)。如果有默认/原始实现作为属性, 这种逻辑完全不同。使用这些注释 要求您调用这些queryset方法中的每一个,这会很快变得有点 一团糟。在
这个包试图通过允许您定义注释和
预取为“prepared”属性,因此您可以通过
引用class属性。querysetprepare
方法解析
注释依赖项并为您构建正确的查询集。在
需要Python3.6和django 2.2。它可能适用于django3,但我没有 试过了(欢迎使用PRs<;3)
带注释的特性
要添加带注释的属性,只需传入
注释到AnnotatedProperty
类或annotated_property
装饰工。然后可以通过调用prepare(Model.propery_name)
来准备它
在queryset。在
避免在注释中循环引用模型(例如,通过引用 模型属性在注释中处于启用状态),也可以将注释传递为 lambda,将在注释queryset时对其求值。在
当您使用decorator时,将使用您装饰的方法体
当注释不存在时。使用它会发出警告,建议您
使用prepare
查询集方法。在
fromdjango.db.modelsimportModel,Sum,OuterRef,Managerfromprepared_propertiesimportannotated_property,AnnotatedProperty,PropertiedQuerySetclassBook(Model):page_number=models.PositiveIntegerField()classAuthor(Model):objects=Manager.from_queryset(PropertiedQuerySet)()pages_written=AnnotatedProperty(Subquery(Book.objects.filter(author=OuterRef("pk")).values("author").annotate(pages_written=Sum("page_number")).values("page_number")))# ... or with a default getter:@annotated_property(Subquery(Book.objects.filter(author=OuterRef("pk")).values("author").annotate(pages_written=Sum("page_number")).values("page_number")))defpages_written(self):# a warning is emitted before this is run.returnself.book_set.aggregate(pages_written=Sum("page_number"))["pages_written"]forauthorinAuthor.objects.prepare(Author.pages_written):print(author.pages_written)
相关注释属性
通常,注释可能依赖于其他注释的存在。如果你通过了 属性构造函数或修饰符中的属性名数组 当您准备 使用另一个属性:
^{pr2}$现在调用Book.objects.prepare(Author.twice_the_pages_written)
也将
注释Book.pages_written
。这允许您更改底层
在不更改queryset定义的情况下实现注释
到处都是。尼托。在
预取属性
对于预取,也可以执行类似的、但功能不完整的操作:
classAuthor(Model):objects=Manager.from_queryset(PropertiedQuerySet)()short_books=PrefetchedProperty("book_set",Book.objects.filter(page_number__lt=100))forauthorinAuthor.objects.prepare(Author.pages_written):print(author.short_books)
由于预取不能相互依赖,depends_on
kwarg不是
支持预取。目前也不支持默认的getter
(django在执行
预取,它将始终执行天真的getter。)
正如您所看到的,prepare方法并不关心传递它是预取还是 注释,因此属性可以从注释更改为预取,反之亦然 不需要更改queryset定义或模型接口!在
- 项目
标签: