我怎样才能模仿“select_lated”使用 google-appengine 和 django-nonrel?
django nonrel 的 文档 指出:“您必须手动编写代码来合并多个查询的结果(JOIN、select_lated() 等)”。
有人可以向我指出手动添加相关数据的任何片段吗? @nickjohnson 有一篇 优秀帖子 展示了如何执行此操作使用直接的 AppEngine 模型,但我使用的是 django-nonrel。
对于我的特殊用途,我试图获取 UserProfiles 及其相关的用户模型。这应该只是两个简单的查询,然后匹配数据。
但是,使用 django-nonrel,将为查询集中的每个结果触发一个新查询。如何以“select_相关”方式访问相关项目?
我已经尝试过这个,但它似乎没有像我预期的那样工作。查看 rpc 统计信息,它似乎仍在对显示的每个项目触发查询。
all_profiles = UserProfile.objects.all()
user_pks = set()
for profile in all_profiles:
user_pks.add(profile.user_id) # a way to access the pk without triggering the query
users = User.objects.filter(pk__in=user_pks)
for profile in all_profiles:
profile.user = get_matching_model(profile.user_id, users)
def get_matching_model(key, queryset):
"""Generator expression to get the next match for a given key"""
try:
return (model for model in queryset if model.pk == key).next()
except StopIteration:
return None
更新: 哎呀...我明白了我的问题是什么。
我试图提高 django 管理中的changelist_view 的效率。当外键位于我的“display_list”中时,上面的 select_lated 逻辑似乎仍在为结果集中的每一行生成额外的查询。然而,我追踪到了不同的东西。上面的逻辑不会产生多个查询(但是如果你更仔细地模仿 Nick Johnson 的方式,它看起来会更漂亮)。
问题是在 django.contrib.admin.views.main 的 ChangeList 方法内第 117 行有以下代码:result_list = self.query_set._clone()
。因此,即使我正确地覆盖了管理中的查询集并选择了相关的内容,此方法也会触发查询集的克隆,该克隆不会保留我为“选择相关”添加的模型上的属性,从而导致页面加载效率比我开始时还要低。
还不知道该怎么办,但是选择相关内容的代码就很好。
django nonrel's documentation states: "you have to manually write code for merging the results of multiple queries (JOINs, select_related(), etc.)".
Can someone point me to any snippets that manually add the related data? @nickjohnson has an excellent post showing how to do this with the straight AppEngine models, but I'm using django-nonrel.
For my particular use I'm trying to get the UserProfiles with their related User models. This should be just two simple queries, then match the data.
However, using django-nonrel, a new query gets fired off for each result in the queryset. How can I get access to the related items in a 'select_related' sort of way?
I've tried this, but it doesn't seem to work as I'd expect. Looking at the rpc stats, it still seems to be firing a query for each item displayed.
all_profiles = UserProfile.objects.all()
user_pks = set()
for profile in all_profiles:
user_pks.add(profile.user_id) # a way to access the pk without triggering the query
users = User.objects.filter(pk__in=user_pks)
for profile in all_profiles:
profile.user = get_matching_model(profile.user_id, users)
def get_matching_model(key, queryset):
"""Generator expression to get the next match for a given key"""
try:
return (model for model in queryset if model.pk == key).next()
except StopIteration:
return None
UPDATE:
Ick... I figured out what my issue was.
I was trying to improve the efficiency of the changelist_view in the django admin. It seemed that the select_related logic above was still producing additional queries for each row in the results set when a foreign key was in my 'display_list'. However, I traced it down to something different. The above logic does not produce multiple queries (but if you more closely mimic Nick Johnson's way it will look a lot prettier).
The issue is that in django.contrib.admin.views.main on line 117 inside the ChangeList method there is the following code: result_list = self.query_set._clone()
. So, even though I was properly overriding the queryset in the admin and selecting the related stuff, this method was triggering a clone of the queryset which does NOT keep the attributes on the model that I had added for my 'select related', resulting in an even more inefficient page load than when I started.
Not sure what to do about it yet, but the code that selects related stuff is just fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不喜欢回答自己的问题,但答案可能对其他人有帮助。
这是我的解决方案,它将完全基于上面链接的 Nick Johnson 的解决方案来获取查询集上的相关项目。
为了能够修改管理上的查询集以使用相关的选择,我们必须跳过几个步骤。这是我所做的。 “AppEngineRelatedChangeList”的“get_results”方法唯一发生的变化是我删除了 self.query_set._clone() 并仅使用 self.query_set 代替。
I don't like answering my own question, but the answer might help others.
Here is my solution that will get related items on a queryset based entirely on Nick Johnson's solution linked above.
To be able to modify the queryset on the admin to make use of the select related we have to jump through a couple hoops. Here is what I've done. The only thing changed on the 'get_results' method of the 'AppEngineRelatedChangeList' is that I removed the self.query_set._clone() and just used self.query_set instead.