python - 缓存非 View 返回

标签 python django decorator django-cache

我对 View 进行了十几个权限查找,以确保用户具有在系统上执行某些操作的正确权限(即确保他们在正确的组中,如果他们可以编辑他们的个人资料,如果他们是组管理员等)。

一张支票可能是这样的:

from django.contrib.auth.decorators import user_passes_test

test_canvote = lambda u: u.has_perm('polls.can_vote')

@user_passes_test(test_canvote)
def my_view(request):
    # ...

这实际上是 Django 教程中的代码(我的有点难看)。有时,一次检查会占用大量数据库资源,会触发多个查询。随着大量用户访问经过权限检查的页面,事情很快就会变得很慢。

我的问题是,我可以(在您的帮助下)为 user_passes_test 装饰器构建一个包装器(或替代品)来搜索缓存中的键 'TESTCACHE' + user.pk + 'testname'如果不存在,则执行测试并保存结果。

我以前从未编写过装饰器,但我想它看起来与 user_passes_test 几乎相同,只是作为字符串通过了测试:

@cached_user_passes_test('test_canvote')
def my_view(request):
   # ...

和往常一样,如果我生气了或者 Django 已经为我做了这个(所以我在其他地方遇到了问题),请告诉我。

编辑:标准装饰器可以在这里找到:http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py

我认为替换 user_passes_test 可能比包装它更容易,所以这里是起点。当然,如果您觉得我的说法不正确,请告诉我:

try:
    from functools import update_wrapper, wraps
except ImportError:
    from django.utils.functional import update_wrapper, wraps  # Python 2.3, 2.4 fallback.

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect
from django.utils.http import urlquote
from django.utils.decorators import auto_adapt_to_methods

def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    """
    Decorator for views that checks that the user passes the given test,
    redirecting to the log-in page if necessary. The test should be a callable
    that takes the user object and returns True if the user passes.
    """
    if not login_url:
        from django.conf import settings
        login_url = settings.LOGIN_URL

    def decorator(view_func):
        def _wrapped_view(request, *args, **kwargs):
            if test_func(request.user):
                return view_func(request, *args, **kwargs)
            path = urlquote(request.get_full_path())
            tup = login_url, redirect_field_name, path
            return HttpResponseRedirect('%s?%s=%s' % tup)
        return wraps(view_func)(_wrapped_view)
    return auto_adapt_to_methods(decorator)

最佳答案

您可能需要序列化该函数(当我将它用作缓存的键时我没有这样做),但像这样的事情应该可行:

from django.core.cache import cache

def cached_user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    if not login_url:
        from django.conf import settings
        login_url = settings.LOGIN_URL

    def decorator(view_func):
        def _wrapped_view(request, *args, **kwargs):
            key = str(test_func) + str(request.user)
            cached_test_result = cache.get(key)
            if cached_test_result != None:
                test_result = cached_test_result
            else:
                test_result = test_func(request.user)
                cache.set(key, test_result, 60)       

            if test_result:
                return view_func(request, *args, **kwargs)
            path = urlquote(request.get_full_path())
            tup = login_url, redirect_field_name, path
            return HttpResponseRedirect('%s?%s=%s' % tup)
        return wraps(view_func)(_wrapped_view)
    return auto_adapt_to_methods(decorator)

关于python - 缓存非 View 返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2086420/

相关文章:

c++ - 将一个函数传递给 C++ 中的另一个函数,其中参数的数量可以不同

python - 为什么不能跨定义链接 Python 装饰器?

python - (python)在函数中使用装饰器进行彩色打印

django 属性错误 : dict object has no attribute 'pk'

javascript - 如果刷新页面时您不希望数据存在于 window.localstorage 中,是否有任何方法可以将表单值存储在 window.localstorage 中?

python - 我的 defaultdict(list) 不会出现在模板上,但会出现在我的 View 中

python - Pandas .resample() 方法 - 自定义标签?

python - 如何从 tkinter 的网格中删除小部件?

python - 无法安装 Tensorflow,tensorflow-base-1.12 错误

python - 将变量的数据写入 ADLS 文件中