Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import logging 

2from typing import Optional, TYPE_CHECKING, Any, Sequence 

3 

4logger = logging.getLogger(__name__) 

5 

6 

7class CachedFieldsMixin: 

8 """ 

9 Cached fields mixin. Usage: 

10 1) List cached field names in cached_fields list 

11 2) Implement get_xxx functions where xxx is cached field name 

12 3) Call update_cached_fields() to refresh 

13 4) Optionally call update_cached_fields_pre_save() on pre_save signal for objects (to automatically refresh on save) 

14 """ 

15 cached_fields: Sequence[str] = [] 

16 

17 if TYPE_CHECKING: 

18 pk: Any = None 

19 

20 def save(self, force_insert=False, force_update=False, using=None, 

21 update_fields=None): 

22 pass 

23 

24 def update_cached_fields(self, commit: bool = True, exceptions: bool = True, 

25 updated_fields: Optional[Sequence[str]] = None): 

26 """ 

27 Updates cached fields using get_xxx calls for each cached field (in cached_fields list). 

28 :param commit: Save update fields to DB 

29 :param exceptions: Raise exceptions or not 

30 :param updated_fields: List of cached fields to update. Pass None for all cached fields. 

31 """ 

32 try: 

33 fields = updated_fields or self.cached_fields 

34 for k in fields: 

35 f = 'get_' + k 

36 if not hasattr(self, f): 

37 raise Exception('Field {k} marked as cached in {obj} but function get_{k}() does not exist'.format(k=k, obj=self)) 

38 v = self.__getattribute__(f)() 

39 setattr(self, k, v) 

40 if commit: 

41 self.save(update_fields=fields) # pytype: disable=attribute-error 

42 except Exception as e: 

43 logger.error('%s.update_cached_fields: %s', self.__class__, e) 

44 if exceptions: 

45 raise e 

46 

47 def update_cached_fields_pre_save(self, update_fields: Optional[Sequence[str]]): 

48 """ 

49 Call on pre_save signal for objects (to automatically refresh on save). 

50 :param update_fields: list of fields to update 

51 """ 

52 if hasattr(self, 'pk') and self.pk and update_fields is None: 

53 self.update_cached_fields(commit=False, exceptions=False) 

54 

55 

56def update_cached_fields(*args): 

57 """ 

58 Calls update_cached_fields() for each object passed in as argument. 

59 Supports also iterable objects by checking __iter__ attribute. 

60 :param args: List of objects 

61 :return: None 

62 """ 

63 for a in args: 

64 if a is not None: 

65 if hasattr(a, '__iter__'): 

66 for e in a: 

67 e.update_cached_fields() 

68 else: 

69 a.update_cached_fields()