django 查询、反向查询和谓词中的 DRY
让我感到沮丧的是,在 Django 中,我经常不得不在自定义管理器上编写方法:
class EntryManager(Manager):
def filter_beatle(self, beatle):
return self.filter(headline__contains=beatle)
... 并在不同的管理器中重复几乎相同的方法进行反向查询:
class BlogManager(Manager):
def filter_beatle(self, beatle):
return self.filter(entry__headline__contains=beatle)
... 以及 Entry 上的谓词:
def headline_contains(self, beatle):
return self.headline.find(beatle) != -1
[注意Entry 上的谓词将适用于尚未保存的 Entry 对象。]
这感觉像是违反了 DRY。有没有什么方法可以表达一次并在所有三个地方使用它?
我想要做的是写一些类似的东西:
q = Q(headline__contains="Lennon")
lennon_entries = Entry.objects.filter(q)
lennon_blogs = Blog.objects.filter(q.reverse(Entry))
is_lennon = entry.would_filter(q)
... 其中 'headline__contains="Lennon"' 恰好表达了一次“关于“Lennon”的条目”的含义,这可以用来构造反向查询和谓词。
I am frustrated that in Django I often end up having to write methods on a custom Manager:
class EntryManager(Manager):
def filter_beatle(self, beatle):
return self.filter(headline__contains=beatle)
... and repeat pretty much the same method in a different Manager for a reverse query:
class BlogManager(Manager):
def filter_beatle(self, beatle):
return self.filter(entry__headline__contains=beatle)
... and a predicate on Entry:
def headline_contains(self, beatle):
return self.headline.find(beatle) != -1
[Note that the predicate on Entry will work on Entry objects that haven't even been saved yet.]
This feels like a violation of DRY. Is there some way to express this once and use it in all three places?
What I would like to be able to do is write something like:
q = Q(headline__contains="Lennon")
lennon_entries = Entry.objects.filter(q)
lennon_blogs = Blog.objects.filter(q.reverse(Entry))
is_lennon = entry.would_filter(q)
... where 'headline__contains="Lennon"' expresses exactly once what it means to be 'an Entry about "Lennon"', and this can be used to construct reverse queries and a predicate.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
最好的地方是自定义管理器。根据 django 的指南,管理器类是影响类中多个对象的代码的最佳位置。
The best place for this is a custom manager. According to django's guidelines a manager class is the best place for code that is affecting more than one object of a class.
您应该
永远很少需要执行以下操作:因为过滤器应该负责将结果集限制为您感兴趣的实例。
如果您要多次使用相同的过滤器,您可以创建一个 自定义管理器 或一个简单的类方法。
但实际上,DRYness 已经包含在 Queryset API 中。您真正需要将字符串“Lennon”硬编码到查询中的频率是多少?通常,搜索参数将从 GET 或 POST 传递到视图中。完美干燥。
那么,真正的问题是什么?除了探索查询集 API 之外,您是否曾经需要在多个查询(如您的问题)中对查找值进行硬编码?
You should
neverrarely have to do the following:because the filter should take care of restricting the result set to the instances you're interested in.
If you're going to be using the same filter multiple times, you can create a custom manager or a simple class method.
But really, the DRYness has already been contained within the Queryset API. How often are you really going to be hard coding the string 'Lennon' into a query? Usually, the search parameter will be passed into a view from a GET or POST. Perfectly DRY.
So, what is the actual problem? Other than exploring the queryset API, have you ever had to hard code lookup values in multiple queries like your question?
对于“反向过滤器”情况,您可以使用子查询:
重用或生成谓词是不可能的(通常),因为有些谓词无法表示为查询,而查询则无法表示为没有数据库访问的谓词。
For the "reverse filter" case you can use a subquery:
Reusing or generating predicates is not possible (in general) as there are predicates that cannot be expressed as queries and queries that cannot be expressed as predicates without db access.
我对谓词最常见的用法似乎是在断言中。通常是这样的:
我想确保没有其他代码在不需要被敲击的状态下调用 whack() 。虽然它会影响数据库,但它确实有效。
My most common use for the predicate seems to be in asserts. Often something like:
I want to make sure that no other code is calling whack() in state where it doesn't need to be whacked. It costs a database hit, but it works.