options.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. from __future__ import unicode_literals
  2. from bisect import bisect
  3. from collections import OrderedDict
  4. import warnings
  5. from django.apps import apps
  6. from django.conf import settings
  7. from django.db.models.fields.related import ManyToManyRel
  8. from django.db.models.fields import AutoField, FieldDoesNotExist
  9. from django.db.models.fields.proxy import OrderWrt
  10. from django.utils import six
  11. from django.utils.deprecation import RemovedInDjango18Warning
  12. from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
  13. from django.utils.functional import cached_property
  14. from django.utils.text import camel_case_to_spaces
  15. from django.utils.translation import activate, deactivate_all, get_language, string_concat
  16. DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
  17. 'unique_together', 'permissions', 'get_latest_by',
  18. 'order_with_respect_to', 'app_label', 'db_tablespace',
  19. 'abstract', 'managed', 'proxy', 'swappable', 'auto_created',
  20. 'index_together', 'apps', 'default_permissions',
  21. 'select_on_save')
  22. def normalize_together(option_together):
  23. """
  24. option_together can be either a tuple of tuples, or a single
  25. tuple of two strings. Normalize it to a tuple of tuples, so that
  26. calling code can uniformly expect that.
  27. """
  28. try:
  29. if not option_together:
  30. return ()
  31. if not isinstance(option_together, (tuple, list)):
  32. raise TypeError
  33. first_element = next(iter(option_together))
  34. if not isinstance(first_element, (tuple, list)):
  35. option_together = (option_together,)
  36. # Normalize everything to tuples
  37. return tuple(tuple(ot) for ot in option_together)
  38. except TypeError:
  39. # If the value of option_together isn't valid, return it
  40. # verbatim; this will be picked up by the check framework later.
  41. return option_together
  42. @python_2_unicode_compatible
  43. class Options(object):
  44. def __init__(self, meta, app_label=None):
  45. self.local_fields = []
  46. self.local_many_to_many = []
  47. self.virtual_fields = []
  48. self.model_name = None
  49. self.verbose_name = None
  50. self.verbose_name_plural = None
  51. self.db_table = ''
  52. self.ordering = []
  53. self.unique_together = []
  54. self.index_together = []
  55. self.select_on_save = False
  56. self.default_permissions = ('add', 'change', 'delete')
  57. self.permissions = []
  58. self.object_name = None
  59. self.app_label = app_label
  60. self.get_latest_by = None
  61. self.order_with_respect_to = None
  62. self.db_tablespace = settings.DEFAULT_TABLESPACE
  63. self.meta = meta
  64. self.pk = None
  65. self.has_auto_field = False
  66. self.auto_field = None
  67. self.abstract = False
  68. self.managed = True
  69. self.proxy = False
  70. # For any class that is a proxy (including automatically created
  71. # classes for deferred object loading), proxy_for_model tells us
  72. # which class this model is proxying. Note that proxy_for_model
  73. # can create a chain of proxy models. For non-proxy models, the
  74. # variable is always None.
  75. self.proxy_for_model = None
  76. # For any non-abstract class, the concrete class is the model
  77. # in the end of the proxy_for_model chain. In particular, for
  78. # concrete models, the concrete_model is always the class itself.
  79. self.concrete_model = None
  80. self.swappable = None
  81. self.parents = OrderedDict()
  82. self.auto_created = False
  83. # To handle various inheritance situations, we need to track where
  84. # managers came from (concrete or abstract base classes).
  85. self.abstract_managers = []
  86. self.concrete_managers = []
  87. # List of all lookups defined in ForeignKey 'limit_choices_to' options
  88. # from *other* models. Needed for some admin checks. Internal use only.
  89. self.related_fkey_lookups = []
  90. # A custom app registry to use, if you're making a separate model set.
  91. self.apps = apps
  92. @property
  93. def app_config(self):
  94. # Don't go through get_app_config to avoid triggering imports.
  95. return self.apps.app_configs.get(self.app_label)
  96. @property
  97. def installed(self):
  98. return self.app_config is not None
  99. def contribute_to_class(self, cls, name):
  100. from django.db import connection
  101. from django.db.backends.utils import truncate_name
  102. cls._meta = self
  103. self.model = cls
  104. # First, construct the default values for these options.
  105. self.object_name = cls.__name__
  106. self.model_name = self.object_name.lower()
  107. self.verbose_name = camel_case_to_spaces(self.object_name)
  108. # Store the original user-defined values for each option,
  109. # for use when serializing the model definition
  110. self.original_attrs = {}
  111. # Next, apply any overridden values from 'class Meta'.
  112. if self.meta:
  113. meta_attrs = self.meta.__dict__.copy()
  114. for name in self.meta.__dict__:
  115. # Ignore any private attributes that Django doesn't care about.
  116. # NOTE: We can't modify a dictionary's contents while looping
  117. # over it, so we loop over the *original* dictionary instead.
  118. if name.startswith('_'):
  119. del meta_attrs[name]
  120. for attr_name in DEFAULT_NAMES:
  121. if attr_name in meta_attrs:
  122. setattr(self, attr_name, meta_attrs.pop(attr_name))
  123. self.original_attrs[attr_name] = getattr(self, attr_name)
  124. elif hasattr(self.meta, attr_name):
  125. setattr(self, attr_name, getattr(self.meta, attr_name))
  126. self.original_attrs[attr_name] = getattr(self, attr_name)
  127. ut = meta_attrs.pop('unique_together', self.unique_together)
  128. self.unique_together = normalize_together(ut)
  129. it = meta_attrs.pop('index_together', self.index_together)
  130. self.index_together = normalize_together(it)
  131. # verbose_name_plural is a special case because it uses a 's'
  132. # by default.
  133. if self.verbose_name_plural is None:
  134. self.verbose_name_plural = string_concat(self.verbose_name, 's')
  135. # Any leftover attributes must be invalid.
  136. if meta_attrs != {}:
  137. raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
  138. else:
  139. self.verbose_name_plural = string_concat(self.verbose_name, 's')
  140. del self.meta
  141. # If the db_table wasn't provided, use the app_label + model_name.
  142. if not self.db_table:
  143. self.db_table = "%s_%s" % (self.app_label, self.model_name)
  144. self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
  145. @property
  146. def module_name(self):
  147. """
  148. This property has been deprecated in favor of `model_name`. refs #19689
  149. """
  150. warnings.warn(
  151. "Options.module_name has been deprecated in favor of model_name",
  152. RemovedInDjango18Warning, stacklevel=2)
  153. return self.model_name
  154. def _prepare(self, model):
  155. if self.order_with_respect_to:
  156. self.order_with_respect_to = self.get_field(self.order_with_respect_to)
  157. self.ordering = ('_order',)
  158. if not any(isinstance(field, OrderWrt) for field in model._meta.local_fields):
  159. model.add_to_class('_order', OrderWrt())
  160. else:
  161. self.order_with_respect_to = None
  162. if self.pk is None:
  163. if self.parents:
  164. # Promote the first parent link in lieu of adding yet another
  165. # field.
  166. field = next(six.itervalues(self.parents))
  167. # Look for a local field with the same name as the
  168. # first parent link. If a local field has already been
  169. # created, use it instead of promoting the parent
  170. already_created = [fld for fld in self.local_fields if fld.name == field.name]
  171. if already_created:
  172. field = already_created[0]
  173. field.primary_key = True
  174. self.setup_pk(field)
  175. else:
  176. auto = AutoField(verbose_name='ID', primary_key=True,
  177. auto_created=True)
  178. model.add_to_class('id', auto)
  179. def add_field(self, field):
  180. # Insert the given field in the order in which it was created, using
  181. # the "creation_counter" attribute of the field.
  182. # Move many-to-many related fields from self.fields into
  183. # self.many_to_many.
  184. if field.rel and isinstance(field.rel, ManyToManyRel):
  185. self.local_many_to_many.insert(bisect(self.local_many_to_many, field), field)
  186. if hasattr(self, '_m2m_cache'):
  187. del self._m2m_cache
  188. else:
  189. self.local_fields.insert(bisect(self.local_fields, field), field)
  190. self.setup_pk(field)
  191. if hasattr(self, '_field_cache'):
  192. del self._field_cache
  193. del self._field_name_cache
  194. # The fields, concrete_fields and local_concrete_fields are
  195. # implemented as cached properties for performance reasons.
  196. # The attrs will not exists if the cached property isn't
  197. # accessed yet, hence the try-excepts.
  198. try:
  199. del self.fields
  200. except AttributeError:
  201. pass
  202. try:
  203. del self.concrete_fields
  204. except AttributeError:
  205. pass
  206. try:
  207. del self.local_concrete_fields
  208. except AttributeError:
  209. pass
  210. if hasattr(self, '_name_map'):
  211. del self._name_map
  212. def add_virtual_field(self, field):
  213. self.virtual_fields.append(field)
  214. def setup_pk(self, field):
  215. if not self.pk and field.primary_key:
  216. self.pk = field
  217. field.serialize = False
  218. def pk_index(self):
  219. """
  220. Returns the index of the primary key field in the self.concrete_fields
  221. list.
  222. """
  223. return self.concrete_fields.index(self.pk)
  224. def setup_proxy(self, target):
  225. """
  226. Does the internal setup so that the current model is a proxy for
  227. "target".
  228. """
  229. self.pk = target._meta.pk
  230. self.proxy_for_model = target
  231. self.db_table = target._meta.db_table
  232. def __repr__(self):
  233. return '<Options for %s>' % self.object_name
  234. def __str__(self):
  235. return "%s.%s" % (smart_text(self.app_label), smart_text(self.model_name))
  236. def verbose_name_raw(self):
  237. """
  238. There are a few places where the untranslated verbose name is needed
  239. (so that we get the same value regardless of currently active
  240. locale).
  241. """
  242. lang = get_language()
  243. deactivate_all()
  244. raw = force_text(self.verbose_name)
  245. activate(lang)
  246. return raw
  247. verbose_name_raw = property(verbose_name_raw)
  248. def _swapped(self):
  249. """
  250. Has this model been swapped out for another? If so, return the model
  251. name of the replacement; otherwise, return None.
  252. For historical reasons, model name lookups using get_model() are
  253. case insensitive, so we make sure we are case insensitive here.
  254. """
  255. if self.swappable:
  256. model_label = '%s.%s' % (self.app_label, self.model_name)
  257. swapped_for = getattr(settings, self.swappable, None)
  258. if swapped_for:
  259. try:
  260. swapped_label, swapped_object = swapped_for.split('.')
  261. except ValueError:
  262. # setting not in the format app_label.model_name
  263. # raising ImproperlyConfigured here causes problems with
  264. # test cleanup code - instead it is raised in get_user_model
  265. # or as part of validation.
  266. return swapped_for
  267. if '%s.%s' % (swapped_label, swapped_object.lower()) not in (None, model_label):
  268. return swapped_for
  269. return None
  270. swapped = property(_swapped)
  271. @cached_property
  272. def fields(self):
  273. """
  274. The getter for self.fields. This returns the list of field objects
  275. available to this model (including through parent models).
  276. Callers are not permitted to modify this list, since it's a reference
  277. to this instance (not a copy).
  278. """
  279. try:
  280. self._field_name_cache
  281. except AttributeError:
  282. self._fill_fields_cache()
  283. return self._field_name_cache
  284. @cached_property
  285. def concrete_fields(self):
  286. return [f for f in self.fields if f.column is not None]
  287. @cached_property
  288. def local_concrete_fields(self):
  289. return [f for f in self.local_fields if f.column is not None]
  290. def get_fields_with_model(self):
  291. """
  292. Returns a sequence of (field, model) pairs for all fields. The "model"
  293. element is None for fields on the current model. Mostly of use when
  294. constructing queries so that we know which model a field belongs to.
  295. """
  296. try:
  297. self._field_cache
  298. except AttributeError:
  299. self._fill_fields_cache()
  300. return self._field_cache
  301. def get_concrete_fields_with_model(self):
  302. return [(field, model) for field, model in self.get_fields_with_model() if
  303. field.column is not None]
  304. def _fill_fields_cache(self):
  305. cache = []
  306. for parent in self.parents:
  307. for field, model in parent._meta.get_fields_with_model():
  308. if model:
  309. cache.append((field, model))
  310. else:
  311. cache.append((field, parent))
  312. cache.extend((f, None) for f in self.local_fields)
  313. self._field_cache = tuple(cache)
  314. self._field_name_cache = [x for x, _ in cache]
  315. def _many_to_many(self):
  316. try:
  317. self._m2m_cache
  318. except AttributeError:
  319. self._fill_m2m_cache()
  320. return list(self._m2m_cache)
  321. many_to_many = property(_many_to_many)
  322. def get_m2m_with_model(self):
  323. """
  324. The many-to-many version of get_fields_with_model().
  325. """
  326. try:
  327. self._m2m_cache
  328. except AttributeError:
  329. self._fill_m2m_cache()
  330. return list(six.iteritems(self._m2m_cache))
  331. def _fill_m2m_cache(self):
  332. cache = OrderedDict()
  333. for parent in self.parents:
  334. for field, model in parent._meta.get_m2m_with_model():
  335. if model:
  336. cache[field] = model
  337. else:
  338. cache[field] = parent
  339. for field in self.local_many_to_many:
  340. cache[field] = None
  341. self._m2m_cache = cache
  342. def get_field(self, name, many_to_many=True):
  343. """
  344. Returns the requested field by name. Raises FieldDoesNotExist on error.
  345. """
  346. to_search = (self.fields + self.many_to_many) if many_to_many else self.fields
  347. for f in to_search:
  348. if f.name == name:
  349. return f
  350. raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, name))
  351. def get_field_by_name(self, name):
  352. """
  353. Returns the (field_object, model, direct, m2m), where field_object is
  354. the Field instance for the given name, model is the model containing
  355. this field (None for local fields), direct is True if the field exists
  356. on this model, and m2m is True for many-to-many relations. When
  357. 'direct' is False, 'field_object' is the corresponding RelatedObject
  358. for this field (since the field doesn't have an instance associated
  359. with it).
  360. Uses a cache internally, so after the first access, this is very fast.
  361. """
  362. try:
  363. try:
  364. return self._name_map[name]
  365. except AttributeError:
  366. cache = self.init_name_map()
  367. return cache[name]
  368. except KeyError:
  369. raise FieldDoesNotExist('%s has no field named %r'
  370. % (self.object_name, name))
  371. def get_all_field_names(self):
  372. """
  373. Returns a list of all field names that are possible for this model
  374. (including reverse relation names). This is used for pretty printing
  375. debugging output (a list of choices), so any internal-only field names
  376. are not included.
  377. """
  378. try:
  379. cache = self._name_map
  380. except AttributeError:
  381. cache = self.init_name_map()
  382. names = sorted(cache.keys())
  383. # Internal-only names end with "+" (symmetrical m2m related names being
  384. # the main example). Trim them.
  385. return [val for val in names if not val.endswith('+')]
  386. def init_name_map(self):
  387. """
  388. Initialises the field name -> field object mapping.
  389. """
  390. cache = {}
  391. # We intentionally handle related m2m objects first so that symmetrical
  392. # m2m accessor names can be overridden, if necessary.
  393. for f, model in self.get_all_related_m2m_objects_with_model():
  394. cache[f.field.related_query_name()] = (f, model, False, True)
  395. for f, model in self.get_all_related_objects_with_model():
  396. cache[f.field.related_query_name()] = (f, model, False, False)
  397. for f, model in self.get_m2m_with_model():
  398. cache[f.name] = cache[f.attname] = (f, model, True, True)
  399. for f, model in self.get_fields_with_model():
  400. cache[f.name] = cache[f.attname] = (f, model, True, False)
  401. for f in self.virtual_fields:
  402. if hasattr(f, 'related'):
  403. cache[f.name] = cache[f.attname] = (
  404. f, None if f.model == self.model else f.model, True, False)
  405. if apps.ready:
  406. self._name_map = cache
  407. return cache
  408. def get_add_permission(self):
  409. """
  410. This method has been deprecated in favor of
  411. `django.contrib.auth.get_permission_codename`. refs #20642
  412. """
  413. warnings.warn(
  414. "`Options.get_add_permission` has been deprecated in favor "
  415. "of `django.contrib.auth.get_permission_codename`.",
  416. RemovedInDjango18Warning, stacklevel=2)
  417. return 'add_%s' % self.model_name
  418. def get_change_permission(self):
  419. """
  420. This method has been deprecated in favor of
  421. `django.contrib.auth.get_permission_codename`. refs #20642
  422. """
  423. warnings.warn(
  424. "`Options.get_change_permission` has been deprecated in favor "
  425. "of `django.contrib.auth.get_permission_codename`.",
  426. RemovedInDjango18Warning, stacklevel=2)
  427. return 'change_%s' % self.model_name
  428. def get_delete_permission(self):
  429. """
  430. This method has been deprecated in favor of
  431. `django.contrib.auth.get_permission_codename`. refs #20642
  432. """
  433. warnings.warn(
  434. "`Options.get_delete_permission` has been deprecated in favor "
  435. "of `django.contrib.auth.get_permission_codename`.",
  436. RemovedInDjango18Warning, stacklevel=2)
  437. return 'delete_%s' % self.model_name
  438. def get_all_related_objects(self, local_only=False, include_hidden=False,
  439. include_proxy_eq=False):
  440. return [k for k, v in self.get_all_related_objects_with_model(
  441. local_only=local_only, include_hidden=include_hidden,
  442. include_proxy_eq=include_proxy_eq)]
  443. def get_all_related_objects_with_model(self, local_only=False,
  444. include_hidden=False,
  445. include_proxy_eq=False):
  446. """
  447. Returns a list of (related-object, model) pairs. Similar to
  448. get_fields_with_model().
  449. """
  450. try:
  451. self._related_objects_cache
  452. except AttributeError:
  453. self._fill_related_objects_cache()
  454. predicates = []
  455. if local_only:
  456. predicates.append(lambda k, v: not v)
  457. if not include_hidden:
  458. predicates.append(lambda k, v: not k.field.rel.is_hidden())
  459. cache = (self._related_objects_proxy_cache if include_proxy_eq
  460. else self._related_objects_cache)
  461. return [t for t in cache.items() if all(p(*t) for p in predicates)]
  462. def _fill_related_objects_cache(self):
  463. cache = OrderedDict()
  464. parent_list = self.get_parent_list()
  465. for parent in self.parents:
  466. for obj, model in parent._meta.get_all_related_objects_with_model(include_hidden=True):
  467. if (obj.field.creation_counter < 0 or obj.field.rel.parent_link) and obj.model not in parent_list:
  468. continue
  469. if not model:
  470. cache[obj] = parent
  471. else:
  472. cache[obj] = model
  473. # Collect also objects which are in relation to some proxy child/parent of self.
  474. proxy_cache = cache.copy()
  475. for klass in self.apps.get_models(include_auto_created=True):
  476. if not klass._meta.swapped:
  477. for f in klass._meta.local_fields + klass._meta.virtual_fields:
  478. if (hasattr(f, 'rel') and f.rel and not isinstance(f.rel.to, six.string_types)
  479. and f.generate_reverse_relation):
  480. if self == f.rel.to._meta:
  481. cache[f.related] = None
  482. proxy_cache[f.related] = None
  483. elif self.concrete_model == f.rel.to._meta.concrete_model:
  484. proxy_cache[f.related] = None
  485. self._related_objects_cache = cache
  486. self._related_objects_proxy_cache = proxy_cache
  487. def get_all_related_many_to_many_objects(self, local_only=False):
  488. try:
  489. cache = self._related_many_to_many_cache
  490. except AttributeError:
  491. cache = self._fill_related_many_to_many_cache()
  492. if local_only:
  493. return [k for k, v in cache.items() if not v]
  494. return list(cache)
  495. def get_all_related_m2m_objects_with_model(self):
  496. """
  497. Returns a list of (related-m2m-object, model) pairs. Similar to
  498. get_fields_with_model().
  499. """
  500. try:
  501. cache = self._related_many_to_many_cache
  502. except AttributeError:
  503. cache = self._fill_related_many_to_many_cache()
  504. return list(six.iteritems(cache))
  505. def _fill_related_many_to_many_cache(self):
  506. cache = OrderedDict()
  507. parent_list = self.get_parent_list()
  508. for parent in self.parents:
  509. for obj, model in parent._meta.get_all_related_m2m_objects_with_model():
  510. if obj.field.creation_counter < 0 and obj.model not in parent_list:
  511. continue
  512. if not model:
  513. cache[obj] = parent
  514. else:
  515. cache[obj] = model
  516. for klass in self.apps.get_models():
  517. if not klass._meta.swapped:
  518. for f in klass._meta.local_many_to_many:
  519. if (f.rel
  520. and not isinstance(f.rel.to, six.string_types)
  521. and self == f.rel.to._meta):
  522. cache[f.related] = None
  523. if apps.ready:
  524. self._related_many_to_many_cache = cache
  525. return cache
  526. def get_base_chain(self, model):
  527. """
  528. Returns a list of parent classes leading to 'model' (order from closet
  529. to most distant ancestor). This has to handle the case were 'model' is
  530. a grandparent or even more distant relation.
  531. """
  532. if not self.parents:
  533. return None
  534. if model in self.parents:
  535. return [model]
  536. for parent in self.parents:
  537. res = parent._meta.get_base_chain(model)
  538. if res:
  539. res.insert(0, parent)
  540. return res
  541. return None
  542. def get_parent_list(self):
  543. """
  544. Returns a list of all the ancestor of this model as a list. Useful for
  545. determining if something is an ancestor, regardless of lineage.
  546. """
  547. result = set()
  548. for parent in self.parents:
  549. result.add(parent)
  550. result.update(parent._meta.get_parent_list())
  551. return result
  552. def get_ancestor_link(self, ancestor):
  553. """
  554. Returns the field on the current model which points to the given
  555. "ancestor". This is possible an indirect link (a pointer to a parent
  556. model, which points, eventually, to the ancestor). Used when
  557. constructing table joins for model inheritance.
  558. Returns None if the model isn't an ancestor of this one.
  559. """
  560. if ancestor in self.parents:
  561. return self.parents[ancestor]
  562. for parent in self.parents:
  563. # Tries to get a link field from the immediate parent
  564. parent_link = parent._meta.get_ancestor_link(ancestor)
  565. if parent_link:
  566. # In case of a proxied model, the first link
  567. # of the chain to the ancestor is that parent
  568. # links
  569. return self.parents[parent] or parent_link