Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/db/models/options.py: 19%
477 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1import bisect
2import copy
3import inspect
4import warnings
5from collections import defaultdict
7from django.apps import apps
8from django.conf import settings
9from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
10from django.db import connections
11from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint
12from django.db.models.query_utils import PathInfo
13from django.utils.datastructures import ImmutableList, OrderedSet
14from django.utils.deprecation import RemovedInDjango51Warning
15from django.utils.functional import cached_property
16from django.utils.module_loading import import_string
17from django.utils.text import camel_case_to_spaces, format_lazy
18from django.utils.translation import override
20PROXY_PARENTS = object()
22EMPTY_RELATION_TREE = ()
24IMMUTABLE_WARNING = (
25 "The return type of '%s' should never be mutated. If you want to manipulate this "
26 "list for your own use, make a copy first."
27)
29DEFAULT_NAMES = (
30 "verbose_name",
31 "verbose_name_plural",
32 "db_table",
33 "db_table_comment",
34 "ordering",
35 "unique_together",
36 "permissions",
37 "get_latest_by",
38 "order_with_respect_to",
39 "app_label",
40 "db_tablespace",
41 "abstract",
42 "managed",
43 "proxy",
44 "swappable",
45 "auto_created",
46 # Must be kept for backward compatibility with old migrations.
47 "index_together",
48 "apps",
49 "default_permissions",
50 "select_on_save",
51 "default_related_name",
52 "required_db_features",
53 "required_db_vendor",
54 "base_manager_name",
55 "default_manager_name",
56 "indexes",
57 "constraints",
58)
61def normalize_together(option_together):
62 """
63 option_together can be either a tuple of tuples, or a single
64 tuple of two strings. Normalize it to a tuple of tuples, so that
65 calling code can uniformly expect that.
66 """
67 try:
68 if not option_together:
69 return ()
70 if not isinstance(option_together, (tuple, list)):
71 raise TypeError
72 first_element = option_together[0]
73 if not isinstance(first_element, (tuple, list)):
74 option_together = (option_together,)
75 # Normalize everything to tuples
76 return tuple(tuple(ot) for ot in option_together)
77 except TypeError:
78 # If the value of option_together isn't valid, return it
79 # verbatim; this will be picked up by the check framework later.
80 return option_together
83def make_immutable_fields_list(name, data):
84 return ImmutableList(data, warning=IMMUTABLE_WARNING % name)
87class Options:
88 FORWARD_PROPERTIES = {
89 "fields",
90 "many_to_many",
91 "concrete_fields",
92 "local_concrete_fields",
93 "_non_pk_concrete_field_names",
94 "_forward_fields_map",
95 "managers",
96 "managers_map",
97 "base_manager",
98 "default_manager",
99 }
100 REVERSE_PROPERTIES = {"related_objects", "fields_map", "_relation_tree"}
102 default_apps = apps
104 def __init__(self, meta, app_label=None):
105 self._get_fields_cache = {}
106 self.local_fields = []
107 self.local_many_to_many = []
108 self.private_fields = []
109 self.local_managers = []
110 self.base_manager_name = None
111 self.default_manager_name = None
112 self.model_name = None
113 self.verbose_name = None
114 self.verbose_name_plural = None
115 self.db_table = ""
116 self.db_table_comment = ""
117 self.ordering = []
118 self._ordering_clash = False
119 self.indexes = []
120 self.constraints = []
121 self.unique_together = []
122 self.index_together = [] # RemovedInDjango51Warning.
123 self.select_on_save = False
124 self.default_permissions = ("add", "change", "delete", "view")
125 self.permissions = []
126 self.object_name = None
127 self.app_label = app_label
128 self.get_latest_by = None
129 self.order_with_respect_to = None
130 self.db_tablespace = settings.DEFAULT_TABLESPACE
131 self.required_db_features = []
132 self.required_db_vendor = None
133 self.meta = meta
134 self.pk = None
135 self.auto_field = None
136 self.abstract = False
137 self.managed = True
138 self.proxy = False
139 # For any class that is a proxy (including automatically created
140 # classes for deferred object loading), proxy_for_model tells us
141 # which class this model is proxying. Note that proxy_for_model
142 # can create a chain of proxy models. For non-proxy models, the
143 # variable is always None.
144 self.proxy_for_model = None
145 # For any non-abstract class, the concrete class is the model
146 # in the end of the proxy_for_model chain. In particular, for
147 # concrete models, the concrete_model is always the class itself.
148 self.concrete_model = None
149 self.swappable = None
150 self.parents = {}
151 self.auto_created = False
153 # List of all lookups defined in ForeignKey 'limit_choices_to' options
154 # from *other* models. Needed for some admin checks. Internal use only.
155 self.related_fkey_lookups = []
157 # A custom app registry to use, if you're making a separate model set.
158 self.apps = self.default_apps
160 self.default_related_name = None
162 @property
163 def label(self):
164 return "%s.%s" % (self.app_label, self.object_name)
166 @property
167 def label_lower(self):
168 return "%s.%s" % (self.app_label, self.model_name)
170 @property
171 def app_config(self):
172 # Don't go through get_app_config to avoid triggering imports.
173 return self.apps.app_configs.get(self.app_label)
175 def contribute_to_class(self, cls, name):
176 from django.db import connection
177 from django.db.backends.utils import truncate_name
179 cls._meta = self
180 self.model = cls
181 # First, construct the default values for these options.
182 self.object_name = cls.__name__
183 self.model_name = self.object_name.lower()
184 self.verbose_name = camel_case_to_spaces(self.object_name)
186 # Store the original user-defined values for each option,
187 # for use when serializing the model definition
188 self.original_attrs = {}
190 # Next, apply any overridden values from 'class Meta'.
191 if self.meta:
192 meta_attrs = self.meta.__dict__.copy()
193 for name in self.meta.__dict__:
194 # Ignore any private attributes that Django doesn't care about.
195 # NOTE: We can't modify a dictionary's contents while looping
196 # over it, so we loop over the *original* dictionary instead.
197 if name.startswith("_"):
198 del meta_attrs[name]
199 for attr_name in DEFAULT_NAMES:
200 if attr_name in meta_attrs:
201 setattr(self, attr_name, meta_attrs.pop(attr_name))
202 self.original_attrs[attr_name] = getattr(self, attr_name)
203 elif hasattr(self.meta, attr_name):
204 setattr(self, attr_name, getattr(self.meta, attr_name))
205 self.original_attrs[attr_name] = getattr(self, attr_name)
207 self.unique_together = normalize_together(self.unique_together)
208 self.index_together = normalize_together(self.index_together)
209 if self.index_together:
210 warnings.warn(
211 f"'index_together' is deprecated. Use 'Meta.indexes' in "
212 f"{self.label!r} instead.",
213 RemovedInDjango51Warning,
214 )
215 # App label/class name interpolation for names of constraints and
216 # indexes.
217 if not getattr(cls._meta, "abstract", False):
218 for attr_name in {"constraints", "indexes"}:
219 objs = getattr(self, attr_name, [])
220 setattr(self, attr_name, self._format_names_with_class(cls, objs))
222 # verbose_name_plural is a special case because it uses a 's'
223 # by default.
224 if self.verbose_name_plural is None:
225 self.verbose_name_plural = format_lazy("{}s", self.verbose_name)
227 # order_with_respect_and ordering are mutually exclusive.
228 self._ordering_clash = bool(self.ordering and self.order_with_respect_to)
230 # Any leftover attributes must be invalid.
231 if meta_attrs != {}:
232 raise TypeError(
233 "'class Meta' got invalid attribute(s): %s" % ",".join(meta_attrs)
234 )
235 else:
236 self.verbose_name_plural = format_lazy("{}s", self.verbose_name)
237 del self.meta
239 # If the db_table wasn't provided, use the app_label + model_name.
240 if not self.db_table:
241 self.db_table = "%s_%s" % (self.app_label, self.model_name)
242 self.db_table = truncate_name(
243 self.db_table, connection.ops.max_name_length()
244 )
246 def _format_names_with_class(self, cls, objs):
247 """App label/class name interpolation for object names."""
248 new_objs = []
249 for obj in objs:
250 obj = obj.clone()
251 obj.name = obj.name % {
252 "app_label": cls._meta.app_label.lower(),
253 "class": cls.__name__.lower(),
254 }
255 new_objs.append(obj)
256 return new_objs
258 def _get_default_pk_class(self):
259 pk_class_path = getattr(
260 self.app_config,
261 "default_auto_field",
262 settings.DEFAULT_AUTO_FIELD,
263 )
264 if self.app_config and self.app_config._is_default_auto_field_overridden:
265 app_config_class = type(self.app_config)
266 source = (
267 f"{app_config_class.__module__}."
268 f"{app_config_class.__qualname__}.default_auto_field"
269 )
270 else:
271 source = "DEFAULT_AUTO_FIELD"
272 if not pk_class_path:
273 raise ImproperlyConfigured(f"{source} must not be empty.")
274 try:
275 pk_class = import_string(pk_class_path)
276 except ImportError as e:
277 msg = (
278 f"{source} refers to the module '{pk_class_path}' that could "
279 f"not be imported."
280 )
281 raise ImproperlyConfigured(msg) from e
282 if not issubclass(pk_class, AutoField):
283 raise ValueError(
284 f"Primary key '{pk_class_path}' referred by {source} must "
285 f"subclass AutoField."
286 )
287 return pk_class
289 def _prepare(self, model):
290 if self.order_with_respect_to:
291 # The app registry will not be ready at this point, so we cannot
292 # use get_field().
293 query = self.order_with_respect_to
294 try:
295 self.order_with_respect_to = next(
296 f
297 for f in self._get_fields(reverse=False)
298 if f.name == query or f.attname == query
299 )
300 except StopIteration:
301 raise FieldDoesNotExist(
302 "%s has no field named '%s'" % (self.object_name, query)
303 )
305 self.ordering = ("_order",)
306 if not any(
307 isinstance(field, OrderWrt) for field in model._meta.local_fields
308 ):
309 model.add_to_class("_order", OrderWrt())
310 else:
311 self.order_with_respect_to = None
313 if self.pk is None:
314 if self.parents:
315 # Promote the first parent link in lieu of adding yet another
316 # field.
317 field = next(iter(self.parents.values()))
318 # Look for a local field with the same name as the
319 # first parent link. If a local field has already been
320 # created, use it instead of promoting the parent
321 already_created = [
322 fld for fld in self.local_fields if fld.name == field.name
323 ]
324 if already_created:
325 field = already_created[0]
326 field.primary_key = True
327 self.setup_pk(field)
328 else:
329 pk_class = self._get_default_pk_class()
330 auto = pk_class(verbose_name="ID", primary_key=True, auto_created=True)
331 model.add_to_class("id", auto)
333 def add_manager(self, manager):
334 self.local_managers.append(manager)
335 self._expire_cache()
337 def add_field(self, field, private=False):
338 # Insert the given field in the order in which it was created, using
339 # the "creation_counter" attribute of the field.
340 # Move many-to-many related fields from self.fields into
341 # self.many_to_many.
342 if private:
343 self.private_fields.append(field)
344 elif field.is_relation and field.many_to_many:
345 bisect.insort(self.local_many_to_many, field)
346 else:
347 bisect.insort(self.local_fields, field)
348 self.setup_pk(field)
350 # If the field being added is a relation to another known field,
351 # expire the cache on this field and the forward cache on the field
352 # being referenced, because there will be new relationships in the
353 # cache. Otherwise, expire the cache of references *to* this field.
354 # The mechanism for getting at the related model is slightly odd -
355 # ideally, we'd just ask for field.related_model. However, related_model
356 # is a cached property, and all the models haven't been loaded yet, so
357 # we need to make sure we don't cache a string reference.
358 if (
359 field.is_relation
360 and hasattr(field.remote_field, "model")
361 and field.remote_field.model
362 ):
363 try:
364 field.remote_field.model._meta._expire_cache(forward=False)
365 except AttributeError:
366 pass
367 self._expire_cache()
368 else:
369 self._expire_cache(reverse=False)
371 def setup_pk(self, field):
372 if not self.pk and field.primary_key:
373 self.pk = field
374 field.serialize = False
376 def setup_proxy(self, target):
377 """
378 Do the internal setup so that the current model is a proxy for
379 "target".
380 """
381 self.pk = target._meta.pk
382 self.proxy_for_model = target
383 self.db_table = target._meta.db_table
385 def __repr__(self):
386 return "<Options for %s>" % self.object_name
388 def __str__(self):
389 return self.label_lower
391 def can_migrate(self, connection):
392 """
393 Return True if the model can/should be migrated on the `connection`.
394 `connection` can be either a real connection or a connection alias.
395 """
396 if self.proxy or self.swapped or not self.managed:
397 return False
398 if isinstance(connection, str):
399 connection = connections[connection]
400 if self.required_db_vendor:
401 return self.required_db_vendor == connection.vendor
402 if self.required_db_features:
403 return all(
404 getattr(connection.features, feat, False)
405 for feat in self.required_db_features
406 )
407 return True
409 @property
410 def verbose_name_raw(self):
411 """Return the untranslated verbose name."""
412 with override(None):
413 return str(self.verbose_name)
415 @property
416 def swapped(self):
417 """
418 Has this model been swapped out for another? If so, return the model
419 name of the replacement; otherwise, return None.
421 For historical reasons, model name lookups using get_model() are
422 case insensitive, so we make sure we are case insensitive here.
423 """
424 if self.swappable:
425 swapped_for = getattr(settings, self.swappable, None)
426 if swapped_for:
427 try:
428 swapped_label, swapped_object = swapped_for.split(".")
429 except ValueError:
430 # setting not in the format app_label.model_name
431 # raising ImproperlyConfigured here causes problems with
432 # test cleanup code - instead it is raised in get_user_model
433 # or as part of validation.
434 return swapped_for
436 if (
437 "%s.%s" % (swapped_label, swapped_object.lower())
438 != self.label_lower
439 ):
440 return swapped_for
441 return None
443 @cached_property
444 def managers(self):
445 managers = []
446 seen_managers = set()
447 bases = (b for b in self.model.mro() if hasattr(b, "_meta"))
448 for depth, base in enumerate(bases):
449 for manager in base._meta.local_managers:
450 if manager.name in seen_managers:
451 continue
453 manager = copy.copy(manager)
454 manager.model = self.model
455 seen_managers.add(manager.name)
456 managers.append((depth, manager.creation_counter, manager))
458 return make_immutable_fields_list(
459 "managers",
460 (m[2] for m in sorted(managers)),
461 )
463 @cached_property
464 def managers_map(self):
465 return {manager.name: manager for manager in self.managers}
467 @cached_property
468 def base_manager(self):
469 base_manager_name = self.base_manager_name
470 if not base_manager_name:
471 # Get the first parent's base_manager_name if there's one.
472 for parent in self.model.mro()[1:]:
473 if hasattr(parent, "_meta"):
474 if parent._base_manager.name != "_base_manager":
475 base_manager_name = parent._base_manager.name
476 break
478 if base_manager_name:
479 try:
480 return self.managers_map[base_manager_name]
481 except KeyError:
482 raise ValueError(
483 "%s has no manager named %r"
484 % (
485 self.object_name,
486 base_manager_name,
487 )
488 )
490 manager = Manager()
491 manager.name = "_base_manager"
492 manager.model = self.model
493 manager.auto_created = True
494 return manager
496 @cached_property
497 def default_manager(self):
498 default_manager_name = self.default_manager_name
499 if not default_manager_name and not self.local_managers:
500 # Get the first parent's default_manager_name if there's one.
501 for parent in self.model.mro()[1:]:
502 if hasattr(parent, "_meta"):
503 default_manager_name = parent._meta.default_manager_name
504 break
506 if default_manager_name:
507 try:
508 return self.managers_map[default_manager_name]
509 except KeyError:
510 raise ValueError(
511 "%s has no manager named %r"
512 % (
513 self.object_name,
514 default_manager_name,
515 )
516 )
518 if self.managers:
519 return self.managers[0]
521 @cached_property
522 def fields(self):
523 """
524 Return a list of all forward fields on the model and its parents,
525 excluding ManyToManyFields.
527 Private API intended only to be used by Django itself; get_fields()
528 combined with filtering of field properties is the public API for
529 obtaining this field list.
530 """
531 # For legacy reasons, the fields property should only contain forward
532 # fields that are not private or with a m2m cardinality. Therefore we
533 # pass these three filters as filters to the generator.
534 # The third lambda is a longwinded way of checking f.related_model - we don't
535 # use that property directly because related_model is a cached property,
536 # and all the models may not have been loaded yet; we don't want to cache
537 # the string reference to the related_model.
538 def is_not_an_m2m_field(f):
539 return not (f.is_relation and f.many_to_many)
541 def is_not_a_generic_relation(f):
542 return not (f.is_relation and f.one_to_many)
544 def is_not_a_generic_foreign_key(f):
545 return not (
546 f.is_relation
547 and f.many_to_one
548 and not (hasattr(f.remote_field, "model") and f.remote_field.model)
549 )
551 return make_immutable_fields_list(
552 "fields",
553 (
554 f
555 for f in self._get_fields(reverse=False)
556 if is_not_an_m2m_field(f)
557 and is_not_a_generic_relation(f)
558 and is_not_a_generic_foreign_key(f)
559 ),
560 )
562 @cached_property
563 def concrete_fields(self):
564 """
565 Return a list of all concrete fields on the model and its parents.
567 Private API intended only to be used by Django itself; get_fields()
568 combined with filtering of field properties is the public API for
569 obtaining this field list.
570 """
571 return make_immutable_fields_list(
572 "concrete_fields", (f for f in self.fields if f.concrete)
573 )
575 @cached_property
576 def local_concrete_fields(self):
577 """
578 Return a list of all concrete fields on the model.
580 Private API intended only to be used by Django itself; get_fields()
581 combined with filtering of field properties is the public API for
582 obtaining this field list.
583 """
584 return make_immutable_fields_list(
585 "local_concrete_fields", (f for f in self.local_fields if f.concrete)
586 )
588 @cached_property
589 def many_to_many(self):
590 """
591 Return a list of all many to many fields on the model and its parents.
593 Private API intended only to be used by Django itself; get_fields()
594 combined with filtering of field properties is the public API for
595 obtaining this list.
596 """
597 return make_immutable_fields_list(
598 "many_to_many",
599 (
600 f
601 for f in self._get_fields(reverse=False)
602 if f.is_relation and f.many_to_many
603 ),
604 )
606 @cached_property
607 def related_objects(self):
608 """
609 Return all related objects pointing to the current model. The related
610 objects can come from a one-to-one, one-to-many, or many-to-many field
611 relation type.
613 Private API intended only to be used by Django itself; get_fields()
614 combined with filtering of field properties is the public API for
615 obtaining this field list.
616 """
617 all_related_fields = self._get_fields(
618 forward=False, reverse=True, include_hidden=True
619 )
620 return make_immutable_fields_list(
621 "related_objects",
622 (
623 obj
624 for obj in all_related_fields
625 if not obj.hidden or obj.field.many_to_many
626 ),
627 )
629 @cached_property
630 def _forward_fields_map(self):
631 res = {}
632 fields = self._get_fields(reverse=False)
633 for field in fields:
634 res[field.name] = field
635 # Due to the way Django's internals work, get_field() should also
636 # be able to fetch a field by attname. In the case of a concrete
637 # field with relation, includes the *_id name too
638 try:
639 res[field.attname] = field
640 except AttributeError:
641 pass
642 return res
644 @cached_property
645 def fields_map(self):
646 res = {}
647 fields = self._get_fields(forward=False, include_hidden=True)
648 for field in fields:
649 res[field.name] = field
650 # Due to the way Django's internals work, get_field() should also
651 # be able to fetch a field by attname. In the case of a concrete
652 # field with relation, includes the *_id name too
653 try:
654 res[field.attname] = field
655 except AttributeError:
656 pass
657 return res
659 def get_field(self, field_name):
660 """
661 Return a field instance given the name of a forward or reverse field.
662 """
663 try:
664 # In order to avoid premature loading of the relation tree
665 # (expensive) we prefer checking if the field is a forward field.
666 return self._forward_fields_map[field_name]
667 except KeyError:
668 # If the app registry is not ready, reverse fields are
669 # unavailable, therefore we throw a FieldDoesNotExist exception.
670 if not self.apps.models_ready:
671 raise FieldDoesNotExist(
672 "%s has no field named '%s'. The app cache isn't ready yet, "
673 "so if this is an auto-created related field, it won't "
674 "be available yet." % (self.object_name, field_name)
675 )
677 try:
678 # Retrieve field instance by name from cached or just-computed
679 # field map.
680 return self.fields_map[field_name]
681 except KeyError:
682 raise FieldDoesNotExist(
683 "%s has no field named '%s'" % (self.object_name, field_name)
684 )
686 def get_base_chain(self, model):
687 """
688 Return a list of parent classes leading to `model` (ordered from
689 closest to most distant ancestor). This has to handle the case where
690 `model` is a grandparent or even more distant relation.
691 """
692 if not self.parents:
693 return []
694 if model in self.parents:
695 return [model]
696 for parent in self.parents:
697 res = parent._meta.get_base_chain(model)
698 if res:
699 res.insert(0, parent)
700 return res
701 return []
703 def get_parent_list(self):
704 """
705 Return all the ancestors of this model as a list ordered by MRO.
706 Useful for determining if something is an ancestor, regardless of lineage.
707 """
708 result = OrderedSet(self.parents)
709 for parent in self.parents:
710 for ancestor in parent._meta.get_parent_list():
711 result.add(ancestor)
712 return list(result)
714 def get_ancestor_link(self, ancestor):
715 """
716 Return the field on the current model which points to the given
717 "ancestor". This is possible an indirect link (a pointer to a parent
718 model, which points, eventually, to the ancestor). Used when
719 constructing table joins for model inheritance.
721 Return None if the model isn't an ancestor of this one.
722 """
723 if ancestor in self.parents:
724 return self.parents[ancestor]
725 for parent in self.parents:
726 # Tries to get a link field from the immediate parent
727 parent_link = parent._meta.get_ancestor_link(ancestor)
728 if parent_link:
729 # In case of a proxied model, the first link
730 # of the chain to the ancestor is that parent
731 # links
732 return self.parents[parent] or parent_link
734 def get_path_to_parent(self, parent):
735 """
736 Return a list of PathInfos containing the path from the current
737 model to the parent model, or an empty list if parent is not a
738 parent of the current model.
739 """
740 if self.model is parent:
741 return []
742 # Skip the chain of proxy to the concrete proxied model.
743 proxied_model = self.concrete_model
744 path = []
745 opts = self
746 for int_model in self.get_base_chain(parent):
747 if int_model is proxied_model:
748 opts = int_model._meta
749 else:
750 final_field = opts.parents[int_model]
751 targets = (final_field.remote_field.get_related_field(),)
752 opts = int_model._meta
753 path.append(
754 PathInfo(
755 from_opts=final_field.model._meta,
756 to_opts=opts,
757 target_fields=targets,
758 join_field=final_field,
759 m2m=False,
760 direct=True,
761 filtered_relation=None,
762 )
763 )
764 return path
766 def get_path_from_parent(self, parent):
767 """
768 Return a list of PathInfos containing the path from the parent
769 model to the current model, or an empty list if parent is not a
770 parent of the current model.
771 """
772 if self.model is parent:
773 return []
774 model = self.concrete_model
775 # Get a reversed base chain including both the current and parent
776 # models.
777 chain = model._meta.get_base_chain(parent)
778 chain.reverse()
779 chain.append(model)
780 # Construct a list of the PathInfos between models in chain.
781 path = []
782 for i, ancestor in enumerate(chain[:-1]):
783 child = chain[i + 1]
784 link = child._meta.get_ancestor_link(ancestor)
785 path.extend(link.reverse_path_infos)
786 return path
788 def _populate_directed_relation_graph(self):
789 """
790 This method is used by each model to find its reverse objects. As this
791 method is very expensive and is accessed frequently (it looks up every
792 field in a model, in every app), it is computed on first access and then
793 is set as a property on every model.
794 """
795 related_objects_graph = defaultdict(list)
797 all_models = self.apps.get_models(include_auto_created=True)
798 for model in all_models:
799 opts = model._meta
800 # Abstract model's fields are copied to child models, hence we will
801 # see the fields from the child models.
802 if opts.abstract:
803 continue
804 fields_with_relations = (
805 f
806 for f in opts._get_fields(reverse=False, include_parents=False)
807 if f.is_relation and f.related_model is not None
808 )
809 for f in fields_with_relations:
810 if not isinstance(f.remote_field.model, str):
811 remote_label = f.remote_field.model._meta.concrete_model._meta.label
812 related_objects_graph[remote_label].append(f)
814 for model in all_models:
815 # Set the relation_tree using the internal __dict__. In this way
816 # we avoid calling the cached property. In attribute lookup,
817 # __dict__ takes precedence over a data descriptor (such as
818 # @cached_property). This means that the _meta._relation_tree is
819 # only called if related_objects is not in __dict__.
820 related_objects = related_objects_graph[
821 model._meta.concrete_model._meta.label
822 ]
823 model._meta.__dict__["_relation_tree"] = related_objects
824 # It seems it is possible that self is not in all_models, so guard
825 # against that with default for get().
826 return self.__dict__.get("_relation_tree", EMPTY_RELATION_TREE)
828 @cached_property
829 def _relation_tree(self):
830 return self._populate_directed_relation_graph()
832 def _expire_cache(self, forward=True, reverse=True):
833 # This method is usually called by apps.cache_clear(), when the
834 # registry is finalized, or when a new field is added.
835 if forward:
836 for cache_key in self.FORWARD_PROPERTIES:
837 if cache_key in self.__dict__:
838 delattr(self, cache_key)
839 if reverse and not self.abstract:
840 for cache_key in self.REVERSE_PROPERTIES:
841 if cache_key in self.__dict__:
842 delattr(self, cache_key)
843 self._get_fields_cache = {}
845 def get_fields(self, include_parents=True, include_hidden=False):
846 """
847 Return a list of fields associated to the model. By default, include
848 forward and reverse fields, fields derived from inheritance, but not
849 hidden fields. The returned fields can be changed using the parameters:
851 - include_parents: include fields derived from inheritance
852 - include_hidden: include fields that have a related_name that
853 starts with a "+"
854 """
855 if include_parents is False:
856 include_parents = PROXY_PARENTS
857 return self._get_fields(
858 include_parents=include_parents, include_hidden=include_hidden
859 )
861 def _get_fields(
862 self,
863 forward=True,
864 reverse=True,
865 include_parents=True,
866 include_hidden=False,
867 seen_models=None,
868 ):
869 """
870 Internal helper function to return fields of the model.
871 * If forward=True, then fields defined on this model are returned.
872 * If reverse=True, then relations pointing to this model are returned.
873 * If include_hidden=True, then fields with is_hidden=True are returned.
874 * The include_parents argument toggles if fields from parent models
875 should be included. It has three values: True, False, and
876 PROXY_PARENTS. When set to PROXY_PARENTS, the call will return all
877 fields defined for the current model or any of its parents in the
878 parent chain to the model's concrete model.
879 """
880 if include_parents not in (True, False, PROXY_PARENTS):
881 raise TypeError(
882 "Invalid argument for include_parents: %s" % (include_parents,)
883 )
884 # This helper function is used to allow recursion in ``get_fields()``
885 # implementation and to provide a fast way for Django's internals to
886 # access specific subsets of fields.
888 # We must keep track of which models we have already seen. Otherwise we
889 # could include the same field multiple times from different models.
890 topmost_call = seen_models is None
891 if topmost_call:
892 seen_models = set()
893 seen_models.add(self.model)
895 # Creates a cache key composed of all arguments
896 cache_key = (forward, reverse, include_parents, include_hidden, topmost_call)
898 try:
899 # In order to avoid list manipulation. Always return a shallow copy
900 # of the results.
901 return self._get_fields_cache[cache_key]
902 except KeyError:
903 pass
905 fields = []
906 # Recursively call _get_fields() on each parent, with the same
907 # options provided in this call.
908 if include_parents is not False:
909 for parent in self.parents:
910 # In diamond inheritance it is possible that we see the same
911 # model from two different routes. In that case, avoid adding
912 # fields from the same parent again.
913 if parent in seen_models:
914 continue
915 if (
916 parent._meta.concrete_model != self.concrete_model
917 and include_parents == PROXY_PARENTS
918 ):
919 continue
920 for obj in parent._meta._get_fields(
921 forward=forward,
922 reverse=reverse,
923 include_parents=include_parents,
924 include_hidden=include_hidden,
925 seen_models=seen_models,
926 ):
927 if (
928 not getattr(obj, "parent_link", False)
929 or obj.model == self.concrete_model
930 ):
931 fields.append(obj)
932 if reverse and not self.proxy:
933 # Tree is computed once and cached until the app cache is expired.
934 # It is composed of a list of fields pointing to the current model
935 # from other models.
936 all_fields = self._relation_tree
937 for field in all_fields:
938 # If hidden fields should be included or the relation is not
939 # intentionally hidden, add to the fields dict.
940 if include_hidden or not field.remote_field.hidden:
941 fields.append(field.remote_field)
943 if forward:
944 fields += self.local_fields
945 fields += self.local_many_to_many
946 # Private fields are recopied to each child model, and they get a
947 # different model as field.model in each child. Hence we have to
948 # add the private fields separately from the topmost call. If we
949 # did this recursively similar to local_fields, we would get field
950 # instances with field.model != self.model.
951 if topmost_call:
952 fields += self.private_fields
954 # In order to avoid list manipulation. Always
955 # return a shallow copy of the results
956 fields = make_immutable_fields_list("get_fields()", fields)
958 # Store result into cache for later access
959 self._get_fields_cache[cache_key] = fields
960 return fields
962 @cached_property
963 def total_unique_constraints(self):
964 """
965 Return a list of total unique constraints. Useful for determining set
966 of fields guaranteed to be unique for all rows.
967 """
968 return [
969 constraint
970 for constraint in self.constraints
971 if (
972 isinstance(constraint, UniqueConstraint)
973 and constraint.condition is None
974 and not constraint.contains_expressions
975 )
976 ]
978 @cached_property
979 def _property_names(self):
980 """Return a set of the names of the properties defined on the model."""
981 names = []
982 for name in dir(self.model):
983 attr = inspect.getattr_static(self.model, name)
984 if isinstance(attr, property):
985 names.append(name)
986 return frozenset(names)
988 @cached_property
989 def _non_pk_concrete_field_names(self):
990 """
991 Return a set of the non-pk concrete field names defined on the model.
992 """
993 names = []
994 for field in self.concrete_fields:
995 if not field.primary_key:
996 names.append(field.name)
997 if field.name != field.attname:
998 names.append(field.attname)
999 return frozenset(names)
1001 @cached_property
1002 def db_returning_fields(self):
1003 """
1004 Private API intended only to be used by Django itself.
1005 Fields to be returned after a database insert.
1006 """
1007 return [
1008 field
1009 for field in self._get_fields(
1010 forward=True, reverse=False, include_parents=PROXY_PARENTS
1011 )
1012 if getattr(field, "db_returning", False)
1013 ]