Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/contrib/contenttypes/models.py: 49%

107 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from collections import defaultdict 

2 

3from django.apps import apps 

4from django.db import models 

5from django.utils.translation import gettext_lazy as _ 

6 

7 

8class ContentTypeManager(models.Manager): 

9 use_in_migrations = True 

10 

11 def __init__(self, *args, **kwargs): 

12 super().__init__(*args, **kwargs) 

13 # Cache shared by all the get_for_* methods to speed up 

14 # ContentType retrieval. 

15 self._cache = {} 

16 

17 def get_by_natural_key(self, app_label, model): 

18 try: 

19 ct = self._cache[self.db][(app_label, model)] 

20 except KeyError: 

21 ct = self.get(app_label=app_label, model=model) 

22 self._add_to_cache(self.db, ct) 

23 return ct 

24 

25 def _get_opts(self, model, for_concrete_model): 

26 if for_concrete_model: 

27 model = model._meta.concrete_model 

28 return model._meta 

29 

30 def _get_from_cache(self, opts): 

31 key = (opts.app_label, opts.model_name) 

32 return self._cache[self.db][key] 

33 

34 def get_for_model(self, model, for_concrete_model=True): 

35 """ 

36 Return the ContentType object for a given model, creating the 

37 ContentType if necessary. Lookups are cached so that subsequent lookups 

38 for the same model don't hit the database. 

39 """ 

40 opts = self._get_opts(model, for_concrete_model) 

41 try: 

42 return self._get_from_cache(opts) 

43 except KeyError: 

44 pass 

45 

46 # The ContentType entry was not found in the cache, therefore we 

47 # proceed to load or create it. 

48 try: 

49 # Start with get() and not get_or_create() in order to use 

50 # the db_for_read (see #20401). 

51 ct = self.get(app_label=opts.app_label, model=opts.model_name) 

52 except self.model.DoesNotExist: 

53 # Not found in the database; we proceed to create it. This time 

54 # use get_or_create to take care of any race conditions. 

55 ct, created = self.get_or_create( 

56 app_label=opts.app_label, 

57 model=opts.model_name, 

58 ) 

59 self._add_to_cache(self.db, ct) 

60 return ct 

61 

62 def get_for_models(self, *models, for_concrete_models=True): 

63 """ 

64 Given *models, return a dictionary mapping {model: content_type}. 

65 """ 

66 results = {} 

67 # Models that aren't already in the cache. 

68 needed_app_labels = set() 

69 needed_models = set() 

70 # Mapping of opts to the list of models requiring it. 

71 needed_opts = defaultdict(list) 

72 for model in models: 

73 opts = self._get_opts(model, for_concrete_models) 

74 try: 

75 ct = self._get_from_cache(opts) 

76 except KeyError: 

77 needed_app_labels.add(opts.app_label) 

78 needed_models.add(opts.model_name) 

79 needed_opts[opts].append(model) 

80 else: 

81 results[model] = ct 

82 if needed_opts: 

83 # Lookup required content types from the DB. 

84 cts = self.filter(app_label__in=needed_app_labels, model__in=needed_models) 

85 for ct in cts: 

86 opts_models = needed_opts.pop(ct.model_class()._meta, []) 

87 for model in opts_models: 

88 results[model] = ct 

89 self._add_to_cache(self.db, ct) 

90 # Create content types that weren't in the cache or DB. 

91 for opts, opts_models in needed_opts.items(): 

92 ct = self.create( 

93 app_label=opts.app_label, 

94 model=opts.model_name, 

95 ) 

96 self._add_to_cache(self.db, ct) 

97 for model in opts_models: 

98 results[model] = ct 

99 return results 

100 

101 def get_for_id(self, id): 

102 """ 

103 Lookup a ContentType by ID. Use the same shared cache as get_for_model 

104 (though ContentTypes are not created on-the-fly by get_by_id). 

105 """ 

106 try: 

107 ct = self._cache[self.db][id] 

108 except KeyError: 

109 # This could raise a DoesNotExist; that's correct behavior and will 

110 # make sure that only correct ctypes get stored in the cache dict. 

111 ct = self.get(pk=id) 

112 self._add_to_cache(self.db, ct) 

113 return ct 

114 

115 def clear_cache(self): 

116 """ 

117 Clear out the content-type cache. 

118 """ 

119 self._cache.clear() 

120 

121 def _add_to_cache(self, using, ct): 

122 """Insert a ContentType into the cache.""" 

123 # Note it's possible for ContentType objects to be stale; model_class() 

124 # will return None. Hence, there is no reliance on 

125 # model._meta.app_label here, just using the model fields instead. 

126 key = (ct.app_label, ct.model) 

127 self._cache.setdefault(using, {})[key] = ct 

128 self._cache.setdefault(using, {})[ct.id] = ct 

129 

130 

131class ContentType(models.Model): 

132 app_label = models.CharField(max_length=100) 

133 model = models.CharField(_("python model class name"), max_length=100) 

134 objects = ContentTypeManager() 

135 

136 class Meta: 

137 verbose_name = _("content type") 

138 verbose_name_plural = _("content types") 

139 db_table = "django_content_type" 

140 unique_together = [["app_label", "model"]] 

141 

142 def __str__(self): 

143 return self.app_labeled_name 

144 

145 @property 

146 def name(self): 

147 model = self.model_class() 

148 if not model: 

149 return self.model 

150 return str(model._meta.verbose_name) 

151 

152 @property 

153 def app_labeled_name(self): 

154 model = self.model_class() 

155 if not model: 

156 return self.model 

157 return "%s | %s" % (model._meta.app_label, model._meta.verbose_name) 

158 

159 def model_class(self): 

160 """Return the model class for this type of content.""" 

161 try: 

162 return apps.get_model(self.app_label, self.model) 

163 except LookupError: 

164 return None 

165 

166 def get_object_for_this_type(self, **kwargs): 

167 """ 

168 Return an object of this type for the keyword arguments given. 

169 Basically, this is a proxy around this object_type's get_object() model 

170 method. The ObjectNotExist exception, if thrown, will not be caught, 

171 so code that calls this method should catch it. 

172 """ 

173 return self.model_class()._base_manager.using(self._state.db).get(**kwargs) 

174 

175 def get_all_objects_for_this_type(self, **kwargs): 

176 """ 

177 Return all objects of this type for the keyword arguments given. 

178 """ 

179 return self.model_class()._base_manager.using(self._state.db).filter(**kwargs) 

180 

181 def natural_key(self): 

182 return (self.app_label, self.model)