Plain is headed towards 1.0! Subscribe for development updates →

 1from plain import preflight
 2
 3NOT_PROVIDED = object()
 4
 5
 6class FieldCacheMixin:
 7    """Provide an API for working with the model's fields value cache."""
 8
 9    def get_cache_name(self):
10        raise NotImplementedError
11
12    def get_cached_value(self, instance, default=NOT_PROVIDED):
13        cache_name = self.get_cache_name()
14        try:
15            return instance._state.fields_cache[cache_name]
16        except KeyError:
17            if default is NOT_PROVIDED:
18                raise
19            return default
20
21    def is_cached(self, instance):
22        return self.get_cache_name() in instance._state.fields_cache
23
24    def set_cached_value(self, instance, value):
25        instance._state.fields_cache[self.get_cache_name()] = value
26
27    def delete_cached_value(self, instance):
28        del instance._state.fields_cache[self.get_cache_name()]
29
30
31class CheckFieldDefaultMixin:
32    _default_hint = ("<valid default>", "<invalid default>")
33
34    def _check_default(self):
35        if (
36            self.has_default()
37            and self.default is not None
38            and not callable(self.default)
39        ):
40            return [
41                preflight.Warning(
42                    "{} default should be a callable instead of an instance "
43                    "so that it's not shared between all field instances.".format(
44                        self.__class__.__name__
45                    ),
46                    hint=(
47                        "Use a callable instead, e.g., use `{}` instead of "
48                        "`{}`.".format(*self._default_hint)
49                    ),
50                    obj=self,
51                    id="fields.E010",
52                )
53            ]
54        else:
55            return []
56
57    def check(self, **kwargs):
58        errors = super().check(**kwargs)
59        errors.extend(self._check_default())
60        return errors