Django查询集 - 确保只检索一次结果

时间:2010-09-14 20:36:51

标签: python django

我有一个简单的函数来根据request.user:

获取一些额外的数据
def getIsland(request):
 try:
  island = Island.objects.get(user=request.user) # Retrieve
 except Island.DoesNotExist:
  island = Island(user=request.user) # Doesn't exist, create default one
  island.save()
 island.update() # Run scheduled tasks
 return island # Return

问题是函数在许多不同的地方(中间件,模板,视图ETC)被调用,因此多次执行查询。有什么方法可以帮助吗?即

def getIsland(request):
    if HasBeenEvaluatedAlreadyOnThisRequest: return cached
    else:
        [...]

3 个答案:

答案 0 :(得分:2)

您是否尝试过使用缓存?

Django有一个很棒的缓存系统:http://docs.djangoproject.com/en/dev/topics/cache/

这会让你的功能看起来像这样:

def getIsland(request):
 island = cache.get("island_"+request.user)
 if island == None:
   try:
    island = Island.objects.get(user=request.user) # Retrieve
   except Island.DoesNotExist:
    island = Island(user=request.user) # Doesn't exist, create default one
    island.save()
   island.update() # Run scheduled tasks
   cache.set("island_"+request.user, island, 60)
 return island # Return

在缓存内容时,您可能需要进行一些序列化和反序列化,但这是它的一般要点。好处是您的查询结果现在存储在RAM中x秒,并且无论哪个特定进程访问它都无关紧要。它总是在那里。适用于所有人。

答案 1 :(得分:1)

又快又脏:

def getIsland(request):
    if hasattr(request, "_cached_island"):
        return request._cached_island
    try:
        island = Island.objects.get(user=request.user) # Retrieve
    except Island.DoesNotExist:
        island = Island(user=request.user) # Doesn't exist, create default one
        island.save()
    island.update() # Run scheduled tasks
    request._cached_island = island
    return island # Return

答案 2 :(得分:0)

如果您正在运行多个进程或多台计算机访问同一个数据库,那么当然没有办法减少运行此数据库的查询数。

您可以尝试做的一件事是使用线程本地存储来保存用户的全局“缓存”。举个例子:

class UserStorage(threading.local):
    store = {}
    def getIsland(self, request):
        user_id = request.user.pk
        island = store.get(user_id)
        if island is None:
            island, created = Island.objects.get_or_create(user = user_id)
            store[user_id] = island
        island.update()
        return island

但是,您可能会注意到Island对象永远不会被更新。因此,您必须极其谨慎。您可能需要为此对象设置全局超时,但是您正在实现自己的缓存解决方案,那么为什么不将django的缓存系统与memcached或其threadlocal缓存一起使用?