File: constructors.py

package info (click to toggle)
drf-extensions 0.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,308 kB
  • sloc: python: 7,421; makefile: 11
file content (122 lines) | stat: -rw-r--r-- 4,206 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import hashlib
import json

from rest_framework_extensions.key_constructor import bits
from rest_framework_extensions.settings import extensions_api_settings


class KeyConstructor:
    def __init__(self, memoize_for_request=None, params=None):
        if memoize_for_request is None:
            self.memoize_for_request = extensions_api_settings.DEFAULT_KEY_CONSTRUCTOR_MEMOIZE_FOR_REQUEST
        else:
            self.memoize_for_request = memoize_for_request
        if params is None:
            self.params = {}
        else:
            self.params = params
        self.bits = self.get_bits()

    def get_bits(self):
        _bits = {}
        for attr in dir(self.__class__):
            attr_value = getattr(self.__class__, attr)
            if isinstance(attr_value, bits.KeyBitBase):
                _bits[attr] = attr_value
        return _bits

    def __call__(self, **kwargs):
        return self.get_key(**kwargs)

    def get_key(self, view_instance, view_method, request, args, kwargs):
        if self.memoize_for_request:
            memoization_key = self._get_memoization_key(
                view_instance=view_instance,
                view_method=view_method,
                args=args,
                kwargs=kwargs
            )
            if not hasattr(request, '_key_constructor_cache'):
                request._key_constructor_cache = {}
        if self.memoize_for_request and memoization_key in request._key_constructor_cache:
            return request._key_constructor_cache.get(memoization_key)
        else:
            value = self._get_key(
                view_instance=view_instance,
                view_method=view_method,
                request=request,
                args=args,
                kwargs=kwargs
            )
            if self.memoize_for_request:
                request._key_constructor_cache[memoization_key] = value
            return value

    def _get_memoization_key(self, view_instance, view_method, args, kwargs):
        from rest_framework_extensions.utils import get_unique_method_id
        return json.dumps({
            'unique_method_id': get_unique_method_id(view_instance=view_instance, view_method=view_method),
            'args': args,
            'kwargs': kwargs,
            'instance_id': id(self)
        })

    def _get_key(self, view_instance, view_method, request, args, kwargs):
        _kwargs = {
            'view_instance': view_instance,
            'view_method': view_method,
            'request': request,
            'args': args,
            'kwargs': kwargs,
        }
        return self.prepare_key(
            self.get_data_from_bits(**_kwargs)
        )

    def prepare_key(self, key_dict):
        return hashlib.md5(json.dumps(key_dict, sort_keys=True).encode('utf-8')).hexdigest()

    def get_data_from_bits(self, **kwargs):
        result_dict = {}
        for bit_name, bit_instance in self.bits.items():
            if bit_name in self.params:
                params = self.params[bit_name]
            else:
                try:
                    params = bit_instance.params
                except AttributeError:
                    params = None
            result_dict[bit_name] = bit_instance.get_data(
                params=params, **kwargs)
        return result_dict


class DefaultKeyConstructor(KeyConstructor):
    unique_method_id = bits.UniqueMethodIdKeyBit()
    format = bits.FormatKeyBit()
    language = bits.LanguageKeyBit()


class DefaultObjectKeyConstructor(DefaultKeyConstructor):
    retrieve_sql_query = bits.RetrieveSqlQueryKeyBit()


class DefaultListKeyConstructor(DefaultKeyConstructor):
    list_sql_query = bits.ListSqlQueryKeyBit()
    pagination = bits.PaginationKeyBit()


class DefaultAPIModelInstanceKeyConstructor(KeyConstructor):
    """
    Use this constructor when the values of the model instance are required
    to identify the resource.
    """
    retrieve_model_values = bits.RetrieveModelKeyBit()


class DefaultAPIModelListKeyConstructor(KeyConstructor):
    """
    Use this constructor when the values of the model instance are required
    to identify many resources.
    """
    list_model_values = bits.ListModelKeyBit()