在对数据库进行更改后重新评估django查询

时间:2012-05-03 15:07:55

标签: python django dry django-queryset

我在视图上获得了这个长的queryset语句

    contributions = user_profile.contributions_chosen.all()\
    .filter(payed=False).filter(belongs_to=concert)\
    .filter(contribution_def__left__gt=0)\
    .filter(contribution_def__type_of='ticket')

我在我的模板中使用

context['contributions'] = contributions

稍后在该视图中我对表contrib_chosen进行更改(添加或删除记录),如果我想更新上下文['contributions'],我需要使用相同的lenghty查询重新查询数据库。

contributions = user_profile.contributions_chosen.all()\
.filter(payed=False).filter(belongs_to=concert)\
.filter(contribution_def__left__gt=0)\
.filter(contribution_def__type_of='ticket')

然后再次更新我的上下文

context['contributions'] = contributions

所以我想知道是否有任何方式我可以避免重复我的自我,重新评估贡献,所以它实际上反映了数据库上的真实数据。 理想情况下,我会修改查询集的贡献,它的值会更新,同时数据库会反映这些变化,但我不知道如何做到这一点。

更新: 这就是我在两者之间做的事情     context ['contributions'] =贡献

我将一个新的贡献对象添加到contributions_chosen(这是一个m2m关系),

contribution = Contribution.objects.create(kwarg=something,kwarg2=somethingelse)
user_profile.contributions_chosen.add(contribution) 
contribution.save()
user_profile.save()

在某些情况下,我删除了一个贡献对象     贡献= user_profile.contributions_chosen.get(id = 1)     user_profile.contributions_chosen.get(ID = request.POST ['CON     contribution.delete()

正如您所看到的,我正在修改表contrib_chosen,因此我必须重新发出查询并更新上下文。 我做错了什么?

UPDATE 在看到关于评估的评论之后,我意识到我确实评估了我的查询集 上下文['贡献']之间的len(贡献)似乎是个问题。 我会在数据库操作之后移动它,就好了,谢谢你。

2 个答案:

答案 0 :(得分:4)

更新 似乎您尚未评估查询集contributions,因此无需担心更新它,因为它仍然没有从数据库中获取数据。

您可以在两条context['contributions'] = contributions行之间发布代码吗?通常在评估查询集contributions之前(例如通过迭代它或调用它的__len__()),它不包含从DB读取的任何内容,因此您不必更新其内容。

要重新评估查询集,您可以

# make a clone
contribution._clone()
# or any op that makes clone, for example
contribution.filter()

# or clear its cache
contribution._result_cache = None

# you could even directly add new item to contribution._result_cache, 
# but its could cause unexpected behavior w/o carefulness

答案 1 :(得分:2)

我不知道如何避免重新评估查询,但在代码中保存一些重复语句的一种方法是使用所有这些过滤器创建一个dict,并将filter args指定为一个字典:

query_args = dict(
    payed=False,
    belongs_to=concert,
    contribution_def__left__gt=0,
    contribution_def__type_of='ticket',
)

然后

contributions = user_profile.contributions_chosen.filter(**query_args)

这只是删除了一些重复的代码,但没有解决重复的查询。如果你需要更改args,只需处理query_args作为普通的Python dict,它就是一个全部:))