# -*- coding: UTF-8 -*- import functools import hashlib import json import six from django.conf import settings from django.db.models import Model from talos.cache.base import page_cache class ListInterfaceDescriptor(object): instance_list = [] def __init__(self, func, offset_name, limit_name, element_model, element_func_list): assert isinstance(offset_name, six.string_types + (type(None),)) assert isinstance(limit_name, six.string_types) if element_model is not None: assert isinstance(element_model, type) assert issubclass(element_model, Model) if element_func_list is None: element_func_list = [] for ef in element_func_list: assert any([ callable(ef), isinstance(ef, property), ]) self.func = func self.offset_name = offset_name self.limit_name = limit_name self.element_model = element_model self.element_func_list = element_func_list self.instance_list.append(self) @classmethod def decorator(cls, offset_name=None, limit_name=None, element_model=None, element_func_list=None): def inner_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): limit = kwargs.get(limit_name, 0) if limit > settings.COUNT_LIMIT: kwargs[limit_name] = settings.COUNT_LIMIT return func(*args, **kwargs) descriptor = cls( func=wrapper, offset_name=offset_name, limit_name=limit_name, element_model=element_model, element_func_list=element_func_list, ) wrapper.list_interface_descriptor = descriptor return wrapper return inner_decorator @classmethod def get_descriptor_from_decorated_func(cls, func): return list_interface = ListInterfaceDescriptor.decorator def cache_page(timeout): def wrap(f): # bind_context和cache_page装饰器一起使用,由于ctx参数问题会报错 @functools.wraps(f) def decorated(**kwargs): method_url = "%s.%s?%s" % (f.__module__, f.__name__, json.dumps(kwargs, sort_keys=True)) method_md5 = hashlib.md5(method_url.encode()).hexdigest() cache_key = "cache:%s:rpc:%s" % (method_md5, settings.VERSION) data = page_cache.get(cache_key) try: if data: resp = json.loads(data) return resp except: pass obj = f(**kwargs) page_cache.setex(cache_key, timeout, json.dumps(obj)) return obj return decorated return wrap def listing(arg_limit='count'): def wrapper(f): @functools.wraps(f) def inner(*args, **kwargs): limit = kwargs.get(arg_limit, 0) if limit: kwargs[arg_limit] = settings.COUNT_LIMIT if limit > settings.COUNT_LIMIT else limit return f(*args, **kwargs) return inner return wrapper