我有一个简单的函数来根据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:
[...]
答案 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缓存一起使用?