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

464 statements  

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

1import bisect 

2import copy 

3import inspect 

4from collections import defaultdict 

5 

6from django.apps import apps 

7from django.conf import settings 

8from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured 

9from django.db import connections 

10from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint 

11from django.db.models.query_utils import PathInfo 

12from django.utils.datastructures import ImmutableList, OrderedSet 

13from django.utils.functional import cached_property 

14from django.utils.module_loading import import_string 

15from django.utils.text import camel_case_to_spaces, format_lazy 

16from django.utils.translation import override 

17 

18PROXY_PARENTS = object() 

19 

20EMPTY_RELATION_TREE = () 

21 

22IMMUTABLE_WARNING = ( 

23 "The return type of '%s' should never be mutated. If you want to manipulate this " 

24 "list for your own use, make a copy first." 

25) 

26 

27DEFAULT_NAMES = ( 

28 "verbose_name", 

29 "verbose_name_plural", 

30 "db_table", 

31 "ordering", 

32 "unique_together", 

33 "permissions", 

34 "get_latest_by", 

35 "order_with_respect_to", 

36 "app_label", 

37 "db_tablespace", 

38 "abstract", 

39 "managed", 

40 "proxy", 

41 "swappable", 

42 "auto_created", 

43 "index_together", 

44 "apps", 

45 "default_permissions", 

46 "select_on_save", 

47 "default_related_name", 

48 "required_db_features", 

49 "required_db_vendor", 

50 "base_manager_name", 

51 "default_manager_name", 

52 "indexes", 

53 "constraints", 

54) 

55 

56 

57def normalize_together(option_together): 

58 """ 

59 option_together can be either a tuple of tuples, or a single 

60 tuple of two strings. Normalize it to a tuple of tuples, so that 

61 calling code can uniformly expect that. 

62 """ 

63 try: 

64 if not option_together: 

65 return () 

66 if not isinstance(option_together, (tuple, list)): 

67 raise TypeError 

68 first_element = option_together[0] 

69 if not isinstance(first_element, (tuple, list)): 

70 option_together = (option_together,) 

71 # Normalize everything to tuples 

72 return tuple(tuple(ot) for ot in option_together) 

73 except TypeError: 

74 # If the value of option_together isn't valid, return it 

75 # verbatim; this will be picked up by the check framework later. 

76 return option_together 

77 

78 

79def make_immutable_fields_list(name, data): 

80 return ImmutableList(data, warning=IMMUTABLE_WARNING % name) 

81 

82 

83class Options: 

84 FORWARD_PROPERTIES = { 

85 "fields", 

86 "many_to_many", 

87 "concrete_fields", 

88 "local_concrete_fields", 

89 "_forward_fields_map", 

90 "managers", 

91 "managers_map", 

92 "base_manager", 

93 "default_manager", 

94 } 

95 REVERSE_PROPERTIES = {"related_objects", "fields_map", "_relation_tree"} 

96 

97 default_apps = apps 

98 

99 def __init__(self, meta, app_label=None): 

100 self._get_fields_cache = {} 

101 self.local_fields = [] 

102 self.local_many_to_many = [] 

103 self.private_fields = [] 

104 self.local_managers = [] 

105 self.base_manager_name = None 

106 self.default_manager_name = None 

107 self.model_name = None 

108 self.verbose_name = None 

109 self.verbose_name_plural = None 

110 self.db_table = "" 

111 self.ordering = [] 

112 self._ordering_clash = False 

113 self.indexes = [] 

114 self.constraints = [] 

115 self.unique_together = [] 

116 self.index_together = [] 

117 self.select_on_save = False 

118 self.default_permissions = ("add", "change", "delete", "view") 

119 self.permissions = [] 

120 self.object_name = None 

121 self.app_label = app_label 

122 self.get_latest_by = None 

123 self.order_with_respect_to = None 

124 self.db_tablespace = settings.DEFAULT_TABLESPACE 

125 self.required_db_features = [] 

126 self.required_db_vendor = None 

127 self.meta = meta 

128 self.pk = None 

129 self.auto_field = None 

130 self.abstract = False 

131 self.managed = True 

132 self.proxy = False 

133 # For any class that is a proxy (including automatically created 

134 # classes for deferred object loading), proxy_for_model tells us 

135 # which class this model is proxying. Note that proxy_for_model 

136 # can create a chain of proxy models. For non-proxy models, the 

137 # variable is always None. 

138 self.proxy_for_model = None 

139 # For any non-abstract class, the concrete class is the model 

140 # in the end of the proxy_for_model chain. In particular, for 

141 # concrete models, the concrete_model is always the class itself. 

142 self.concrete_model = None 

143 self.swappable = None 

144 self.parents = {} 

145 self.auto_created = False 

146 

147 # List of all lookups defined in ForeignKey 'limit_choices_to' options 

148 # from *other* models. Needed for some admin checks. Internal use only. 

149 self.related_fkey_lookups = [] 

150 

151 # A custom app registry to use, if you're making a separate model set. 

152 self.apps = self.default_apps 

153 

154 self.default_related_name = None 

155 

156 @property 

157 def label(self): 

158 return "%s.%s" % (self.app_label, self.object_name) 

159 

160 @property 

161 def label_lower(self): 

162 return "%s.%s" % (self.app_label, self.model_name) 

163 

164 @property 

165 def app_config(self): 

166 # Don't go through get_app_config to avoid triggering imports. 

167 return self.apps.app_configs.get(self.app_label) 

168 

169 @property 

170 def installed(self): 

171 return self.app_config is not None 

172 

173 def contribute_to_class(self, cls, name): 

174 from django.db import connection 

175 from django.db.backends.utils import truncate_name 

176 

177 cls._meta = self 

178 self.model = cls 

179 # First, construct the default values for these options. 

180 self.object_name = cls.__name__ 

181 self.model_name = self.object_name.lower() 

182 self.verbose_name = camel_case_to_spaces(self.object_name) 

183 

184 # Store the original user-defined values for each option, 

185 # for use when serializing the model definition 

186 self.original_attrs = {} 

187 

188 # Next, apply any overridden values from 'class Meta'. 

189 if self.meta: 189 ↛ 228line 189 didn't jump to line 228, because the condition on line 189 was never false

190 meta_attrs = self.meta.__dict__.copy() 

191 for name in self.meta.__dict__: 

192 # Ignore any private attributes that Django doesn't care about. 

193 # NOTE: We can't modify a dictionary's contents while looping 

194 # over it, so we loop over the *original* dictionary instead. 

195 if name.startswith("_"): 

196 del meta_attrs[name] 

197 for attr_name in DEFAULT_NAMES: 

198 if attr_name in meta_attrs: 

199 setattr(self, attr_name, meta_attrs.pop(attr_name)) 

200 self.original_attrs[attr_name] = getattr(self, attr_name) 

201 elif hasattr(self.meta, attr_name): 

202 setattr(self, attr_name, getattr(self.meta, attr_name)) 

203 self.original_attrs[attr_name] = getattr(self, attr_name) 

204 

205 self.unique_together = normalize_together(self.unique_together) 

206 self.index_together = normalize_together(self.index_together) 

207 # App label/class name interpolation for names of constraints and 

208 # indexes. 

209 if not getattr(cls._meta, "abstract", False): 

210 for attr_name in {"constraints", "indexes"}: 

211 objs = getattr(self, attr_name, []) 

212 setattr(self, attr_name, self._format_names_with_class(cls, objs)) 

213 

214 # verbose_name_plural is a special case because it uses a 's' 

215 # by default. 

216 if self.verbose_name_plural is None: 

217 self.verbose_name_plural = format_lazy("{}s", self.verbose_name) 

218 

219 # order_with_respect_and ordering are mutually exclusive. 

220 self._ordering_clash = bool(self.ordering and self.order_with_respect_to) 

221 

222 # Any leftover attributes must be invalid. 

223 if meta_attrs != {}: 223 ↛ 224line 223 didn't jump to line 224, because the condition on line 223 was never true

224 raise TypeError( 

225 "'class Meta' got invalid attribute(s): %s" % ",".join(meta_attrs) 

226 ) 

227 else: 

228 self.verbose_name_plural = format_lazy("{}s", self.verbose_name) 

229 del self.meta 

230 

231 # If the db_table wasn't provided, use the app_label + model_name. 

232 if not self.db_table: 

233 self.db_table = "%s_%s" % (self.app_label, self.model_name) 

234 self.db_table = truncate_name( 

235 self.db_table, connection.ops.max_name_length() 

236 ) 

237 

238 def _format_names_with_class(self, cls, objs): 

239 """App label/class name interpolation for object names.""" 

240 new_objs = [] 

241 for obj in objs: 

242 obj = obj.clone() 

243 obj.name = obj.name % { 

244 "app_label": cls._meta.app_label.lower(), 

245 "class": cls.__name__.lower(), 

246 } 

247 new_objs.append(obj) 

248 return new_objs 

249 

250 def _get_default_pk_class(self): 

251 pk_class_path = getattr( 

252 self.app_config, 

253 "default_auto_field", 

254 settings.DEFAULT_AUTO_FIELD, 

255 ) 

256 if self.app_config and self.app_config._is_default_auto_field_overridden: 

257 app_config_class = type(self.app_config) 

258 source = ( 

259 f"{app_config_class.__module__}." 

260 f"{app_config_class.__qualname__}.default_auto_field" 

261 ) 

262 else: 

263 source = "DEFAULT_AUTO_FIELD" 

264 if not pk_class_path: 264 ↛ 265line 264 didn't jump to line 265, because the condition on line 264 was never true

265 raise ImproperlyConfigured(f"{source} must not be empty.") 

266 try: 

267 pk_class = import_string(pk_class_path) 

268 except ImportError as e: 

269 msg = ( 

270 f"{source} refers to the module '{pk_class_path}' that could " 

271 f"not be imported." 

272 ) 

273 raise ImproperlyConfigured(msg) from e 

274 if not issubclass(pk_class, AutoField): 274 ↛ 275line 274 didn't jump to line 275, because the condition on line 274 was never true

275 raise ValueError( 

276 f"Primary key '{pk_class_path}' referred by {source} must " 

277 f"subclass AutoField." 

278 ) 

279 return pk_class 

280 

281 def _prepare(self, model): 

282 if self.order_with_respect_to: 282 ↛ 285line 282 didn't jump to line 285, because the condition on line 282 was never true

283 # The app registry will not be ready at this point, so we cannot 

284 # use get_field(). 

285 query = self.order_with_respect_to 

286 try: 

287 self.order_with_respect_to = next( 

288 f 

289 for f in self._get_fields(reverse=False) 

290 if f.name == query or f.attname == query 

291 ) 

292 except StopIteration: 

293 raise FieldDoesNotExist( 

294 "%s has no field named '%s'" % (self.object_name, query) 

295 ) 

296 

297 self.ordering = ("_order",) 

298 if not any( 

299 isinstance(field, OrderWrt) for field in model._meta.local_fields 

300 ): 

301 model.add_to_class("_order", OrderWrt()) 

302 else: 

303 self.order_with_respect_to = None 

304 

305 if self.pk is None: 

306 if self.parents: 

307 # Promote the first parent link in lieu of adding yet another 

308 # field. 

309 field = next(iter(self.parents.values())) 

310 # Look for a local field with the same name as the 

311 # first parent link. If a local field has already been 

312 # created, use it instead of promoting the parent 

313 already_created = [ 

314 fld for fld in self.local_fields if fld.name == field.name 

315 ] 

316 if already_created: 316 ↛ 318line 316 didn't jump to line 318, because the condition on line 316 was never false

317 field = already_created[0] 

318 field.primary_key = True 

319 self.setup_pk(field) 

320 else: 

321 pk_class = self._get_default_pk_class() 

322 auto = pk_class(verbose_name="ID", primary_key=True, auto_created=True) 

323 model.add_to_class("id", auto) 

324 

325 def add_manager(self, manager): 

326 self.local_managers.append(manager) 

327 self._expire_cache() 

328 

329 def add_field(self, field, private=False): 

330 # Insert the given field in the order in which it was created, using 

331 # the "creation_counter" attribute of the field. 

332 # Move many-to-many related fields from self.fields into 

333 # self.many_to_many. 

334 if private: 

335 self.private_fields.append(field) 

336 elif field.is_relation and field.many_to_many: 

337 bisect.insort(self.local_many_to_many, field) 

338 else: 

339 bisect.insort(self.local_fields, field) 

340 self.setup_pk(field) 

341 

342 # If the field being added is a relation to another known field, 

343 # expire the cache on this field and the forward cache on the field 

344 # being referenced, because there will be new relationships in the 

345 # cache. Otherwise, expire the cache of references *to* this field. 

346 # The mechanism for getting at the related model is slightly odd - 

347 # ideally, we'd just ask for field.related_model. However, related_model 

348 # is a cached property, and all the models haven't been loaded yet, so 

349 # we need to make sure we don't cache a string reference. 

350 if ( 

351 field.is_relation 

352 and hasattr(field.remote_field, "model") 

353 and field.remote_field.model 

354 ): 

355 try: 

356 field.remote_field.model._meta._expire_cache(forward=False) 

357 except AttributeError: 

358 pass 

359 self._expire_cache() 

360 else: 

361 self._expire_cache(reverse=False) 

362 

363 def setup_pk(self, field): 

364 if not self.pk and field.primary_key: 

365 self.pk = field 

366 field.serialize = False 

367 

368 def setup_proxy(self, target): 

369 """ 

370 Do the internal setup so that the current model is a proxy for 

371 "target". 

372 """ 

373 self.pk = target._meta.pk 

374 self.proxy_for_model = target 

375 self.db_table = target._meta.db_table 

376 

377 def __repr__(self): 

378 return "<Options for %s>" % self.object_name 

379 

380 def __str__(self): 

381 return self.label_lower 

382 

383 def can_migrate(self, connection): 

384 """ 

385 Return True if the model can/should be migrated on the `connection`. 

386 `connection` can be either a real connection or a connection alias. 

387 """ 

388 if self.proxy or self.swapped or not self.managed: 

389 return False 

390 if isinstance(connection, str): 390 ↛ 392line 390 didn't jump to line 392, because the condition on line 390 was never false

391 connection = connections[connection] 

392 if self.required_db_vendor: 392 ↛ 393line 392 didn't jump to line 393, because the condition on line 392 was never true

393 return self.required_db_vendor == connection.vendor 

394 if self.required_db_features: 394 ↛ 395line 394 didn't jump to line 395, because the condition on line 394 was never true

395 return all( 

396 getattr(connection.features, feat, False) 

397 for feat in self.required_db_features 

398 ) 

399 return True 

400 

401 @property 

402 def verbose_name_raw(self): 

403 """Return the untranslated verbose name.""" 

404 with override(None): 

405 return str(self.verbose_name) 

406 

407 @property 

408 def swapped(self): 

409 """ 

410 Has this model been swapped out for another? If so, return the model 

411 name of the replacement; otherwise, return None. 

412 

413 For historical reasons, model name lookups using get_model() are 

414 case insensitive, so we make sure we are case insensitive here. 

415 """ 

416 if self.swappable: 

417 swapped_for = getattr(settings, self.swappable, None) 

418 if swapped_for: 418 ↛ 433line 418 didn't jump to line 433, because the condition on line 418 was never false

419 try: 

420 swapped_label, swapped_object = swapped_for.split(".") 

421 except ValueError: 

422 # setting not in the format app_label.model_name 

423 # raising ImproperlyConfigured here causes problems with 

424 # test cleanup code - instead it is raised in get_user_model 

425 # or as part of validation. 

426 return swapped_for 

427 

428 if ( 428 ↛ 433line 428 didn't jump to line 433

429 "%s.%s" % (swapped_label, swapped_object.lower()) 

430 != self.label_lower 

431 ): 

432 return swapped_for 

433 return None 

434 

435 @cached_property 

436 def managers(self): 

437 managers = [] 

438 seen_managers = set() 

439 bases = (b for b in self.model.mro() if hasattr(b, "_meta")) 

440 for depth, base in enumerate(bases): 

441 for manager in base._meta.local_managers: 

442 if manager.name in seen_managers: 

443 continue 

444 

445 manager = copy.copy(manager) 

446 manager.model = self.model 

447 seen_managers.add(manager.name) 

448 managers.append((depth, manager.creation_counter, manager)) 

449 

450 return make_immutable_fields_list( 

451 "managers", 

452 (m[2] for m in sorted(managers)), 

453 ) 

454 

455 @cached_property 

456 def managers_map(self): 

457 return {manager.name: manager for manager in self.managers} 

458 

459 @cached_property 

460 def base_manager(self): 

461 base_manager_name = self.base_manager_name 

462 if not base_manager_name: 

463 # Get the first parent's base_manager_name if there's one. 

464 for parent in self.model.mro()[1:]: 

465 if hasattr(parent, "_meta"): 

466 if parent._base_manager.name != "_base_manager": 

467 base_manager_name = parent._base_manager.name 

468 break 

469 

470 if base_manager_name: 

471 try: 

472 return self.managers_map[base_manager_name] 

473 except KeyError: 

474 raise ValueError( 

475 "%s has no manager named %r" 

476 % ( 

477 self.object_name, 

478 base_manager_name, 

479 ) 

480 ) 

481 

482 manager = Manager() 

483 manager.name = "_base_manager" 

484 manager.model = self.model 

485 manager.auto_created = True 

486 return manager 

487 

488 @cached_property 

489 def default_manager(self): 

490 default_manager_name = self.default_manager_name 

491 if not default_manager_name and not self.local_managers: 

492 # Get the first parent's default_manager_name if there's one. 

493 for parent in self.model.mro()[1:]: 493 ↛ 498line 493 didn't jump to line 498, because the loop on line 493 didn't complete

494 if hasattr(parent, "_meta"): 494 ↛ 493line 494 didn't jump to line 493, because the condition on line 494 was never false

495 default_manager_name = parent._meta.default_manager_name 

496 break 

497 

498 if default_manager_name: 498 ↛ 499line 498 didn't jump to line 499, because the condition on line 498 was never true

499 try: 

500 return self.managers_map[default_manager_name] 

501 except KeyError: 

502 raise ValueError( 

503 "%s has no manager named %r" 

504 % ( 

505 self.object_name, 

506 default_manager_name, 

507 ) 

508 ) 

509 

510 if self.managers: 510 ↛ exitline 510 didn't return from function 'default_manager', because the condition on line 510 was never false

511 return self.managers[0] 

512 

513 @cached_property 

514 def fields(self): 

515 """ 

516 Return a list of all forward fields on the model and its parents, 

517 excluding ManyToManyFields. 

518 

519 Private API intended only to be used by Django itself; get_fields() 

520 combined with filtering of field properties is the public API for 

521 obtaining this field list. 

522 """ 

523 # For legacy reasons, the fields property should only contain forward 

524 # fields that are not private or with a m2m cardinality. Therefore we 

525 # pass these three filters as filters to the generator. 

526 # The third lambda is a longwinded way of checking f.related_model - we don't 

527 # use that property directly because related_model is a cached property, 

528 # and all the models may not have been loaded yet; we don't want to cache 

529 # the string reference to the related_model. 

530 def is_not_an_m2m_field(f): 

531 return not (f.is_relation and f.many_to_many) 

532 

533 def is_not_a_generic_relation(f): 

534 return not (f.is_relation and f.one_to_many) 

535 

536 def is_not_a_generic_foreign_key(f): 

537 return not ( 

538 f.is_relation 

539 and f.many_to_one 

540 and not (hasattr(f.remote_field, "model") and f.remote_field.model) 

541 ) 

542 

543 return make_immutable_fields_list( 

544 "fields", 

545 ( 

546 f 

547 for f in self._get_fields(reverse=False) 

548 if is_not_an_m2m_field(f) 

549 and is_not_a_generic_relation(f) 

550 and is_not_a_generic_foreign_key(f) 

551 ), 

552 ) 

553 

554 @cached_property 

555 def concrete_fields(self): 

556 """ 

557 Return a list of all concrete fields on the model and its parents. 

558 

559 Private API intended only to be used by Django itself; get_fields() 

560 combined with filtering of field properties is the public API for 

561 obtaining this field list. 

562 """ 

563 return make_immutable_fields_list( 

564 "concrete_fields", (f for f in self.fields if f.concrete) 

565 ) 

566 

567 @cached_property 

568 def local_concrete_fields(self): 

569 """ 

570 Return a list of all concrete fields on the model. 

571 

572 Private API intended only to be used by Django itself; get_fields() 

573 combined with filtering of field properties is the public API for 

574 obtaining this field list. 

575 """ 

576 return make_immutable_fields_list( 

577 "local_concrete_fields", (f for f in self.local_fields if f.concrete) 

578 ) 

579 

580 @cached_property 

581 def many_to_many(self): 

582 """ 

583 Return a list of all many to many fields on the model and its parents. 

584 

585 Private API intended only to be used by Django itself; get_fields() 

586 combined with filtering of field properties is the public API for 

587 obtaining this list. 

588 """ 

589 return make_immutable_fields_list( 

590 "many_to_many", 

591 ( 

592 f 

593 for f in self._get_fields(reverse=False) 

594 if f.is_relation and f.many_to_many 

595 ), 

596 ) 

597 

598 @cached_property 

599 def related_objects(self): 

600 """ 

601 Return all related objects pointing to the current model. The related 

602 objects can come from a one-to-one, one-to-many, or many-to-many field 

603 relation type. 

604 

605 Private API intended only to be used by Django itself; get_fields() 

606 combined with filtering of field properties is the public API for 

607 obtaining this field list. 

608 """ 

609 all_related_fields = self._get_fields( 

610 forward=False, reverse=True, include_hidden=True 

611 ) 

612 return make_immutable_fields_list( 

613 "related_objects", 

614 ( 

615 obj 

616 for obj in all_related_fields 

617 if not obj.hidden or obj.field.many_to_many 

618 ), 

619 ) 

620 

621 @cached_property 

622 def _forward_fields_map(self): 

623 res = {} 

624 fields = self._get_fields(reverse=False) 

625 for field in fields: 

626 res[field.name] = field 

627 # Due to the way Django's internals work, get_field() should also 

628 # be able to fetch a field by attname. In the case of a concrete 

629 # field with relation, includes the *_id name too 

630 try: 

631 res[field.attname] = field 

632 except AttributeError: 

633 pass 

634 return res 

635 

636 @cached_property 

637 def fields_map(self): 

638 res = {} 

639 fields = self._get_fields(forward=False, include_hidden=True) 

640 for field in fields: 

641 res[field.name] = field 

642 # Due to the way Django's internals work, get_field() should also 

643 # be able to fetch a field by attname. In the case of a concrete 

644 # field with relation, includes the *_id name too 

645 try: 

646 res[field.attname] = field 

647 except AttributeError: 

648 pass 

649 return res 

650 

651 def get_field(self, field_name): 

652 """ 

653 Return a field instance given the name of a forward or reverse field. 

654 """ 

655 try: 

656 # In order to avoid premature loading of the relation tree 

657 # (expensive) we prefer checking if the field is a forward field. 

658 return self._forward_fields_map[field_name] 

659 except KeyError: 

660 # If the app registry is not ready, reverse fields are 

661 # unavailable, therefore we throw a FieldDoesNotExist exception. 

662 if not self.apps.models_ready: 662 ↛ 663line 662 didn't jump to line 663, because the condition on line 662 was never true

663 raise FieldDoesNotExist( 

664 "%s has no field named '%s'. The app cache isn't ready yet, " 

665 "so if this is an auto-created related field, it won't " 

666 "be available yet." % (self.object_name, field_name) 

667 ) 

668 

669 try: 

670 # Retrieve field instance by name from cached or just-computed 

671 # field map. 

672 return self.fields_map[field_name] 

673 except KeyError: 

674 raise FieldDoesNotExist( 

675 "%s has no field named '%s'" % (self.object_name, field_name) 

676 ) 

677 

678 def get_base_chain(self, model): 

679 """ 

680 Return a list of parent classes leading to `model` (ordered from 

681 closest to most distant ancestor). This has to handle the case where 

682 `model` is a grandparent or even more distant relation. 

683 """ 

684 if not self.parents: 684 ↛ 685line 684 didn't jump to line 685, because the condition on line 684 was never true

685 return [] 

686 if model in self.parents: 686 ↛ 688line 686 didn't jump to line 688, because the condition on line 686 was never false

687 return [model] 

688 for parent in self.parents: 

689 res = parent._meta.get_base_chain(model) 

690 if res: 

691 res.insert(0, parent) 

692 return res 

693 return [] 

694 

695 def get_parent_list(self): 

696 """ 

697 Return all the ancestors of this model as a list ordered by MRO. 

698 Useful for determining if something is an ancestor, regardless of lineage. 

699 """ 

700 result = OrderedSet(self.parents) 

701 for parent in self.parents: 

702 for ancestor in parent._meta.get_parent_list(): 702 ↛ 703line 702 didn't jump to line 703, because the loop on line 702 never started

703 result.add(ancestor) 

704 return list(result) 

705 

706 def get_ancestor_link(self, ancestor): 

707 """ 

708 Return the field on the current model which points to the given 

709 "ancestor". This is possible an indirect link (a pointer to a parent 

710 model, which points, eventually, to the ancestor). Used when 

711 constructing table joins for model inheritance. 

712 

713 Return None if the model isn't an ancestor of this one. 

714 """ 

715 if ancestor in self.parents: 

716 return self.parents[ancestor] 

717 for parent in self.parents: 

718 # Tries to get a link field from the immediate parent 

719 parent_link = parent._meta.get_ancestor_link(ancestor) 

720 if parent_link: 720 ↛ 724line 720 didn't jump to line 724, because the condition on line 720 was never true

721 # In case of a proxied model, the first link 

722 # of the chain to the ancestor is that parent 

723 # links 

724 return self.parents[parent] or parent_link 

725 

726 def get_path_to_parent(self, parent): 

727 """ 

728 Return a list of PathInfos containing the path from the current 

729 model to the parent model, or an empty list if parent is not a 

730 parent of the current model. 

731 """ 

732 if self.model is parent: 732 ↛ 733line 732 didn't jump to line 733, because the condition on line 732 was never true

733 return [] 

734 # Skip the chain of proxy to the concrete proxied model. 

735 proxied_model = self.concrete_model 

736 path = [] 

737 opts = self 

738 for int_model in self.get_base_chain(parent): 

739 if int_model is proxied_model: 

740 opts = int_model._meta 

741 else: 

742 final_field = opts.parents[int_model] 

743 targets = (final_field.remote_field.get_related_field(),) 

744 opts = int_model._meta 

745 path.append( 

746 PathInfo( 

747 from_opts=final_field.model._meta, 

748 to_opts=opts, 

749 target_fields=targets, 

750 join_field=final_field, 

751 m2m=False, 

752 direct=True, 

753 filtered_relation=None, 

754 ) 

755 ) 

756 return path 

757 

758 def get_path_from_parent(self, parent): 

759 """ 

760 Return a list of PathInfos containing the path from the parent 

761 model to the current model, or an empty list if parent is not a 

762 parent of the current model. 

763 """ 

764 if self.model is parent: 

765 return [] 

766 model = self.concrete_model 

767 # Get a reversed base chain including both the current and parent 

768 # models. 

769 chain = model._meta.get_base_chain(parent) 

770 chain.reverse() 

771 chain.append(model) 

772 # Construct a list of the PathInfos between models in chain. 

773 path = [] 

774 for i, ancestor in enumerate(chain[:-1]): 

775 child = chain[i + 1] 

776 link = child._meta.get_ancestor_link(ancestor) 

777 path.extend(link.get_reverse_path_info()) 

778 return path 

779 

780 def _populate_directed_relation_graph(self): 

781 """ 

782 This method is used by each model to find its reverse objects. As this 

783 method is very expensive and is accessed frequently (it looks up every 

784 field in a model, in every app), it is computed on first access and then 

785 is set as a property on every model. 

786 """ 

787 related_objects_graph = defaultdict(list) 

788 

789 all_models = self.apps.get_models(include_auto_created=True) 

790 for model in all_models: 

791 opts = model._meta 

792 # Abstract model's fields are copied to child models, hence we will 

793 # see the fields from the child models. 

794 if opts.abstract: 794 ↛ 795line 794 didn't jump to line 795, because the condition on line 794 was never true

795 continue 

796 fields_with_relations = ( 

797 f 

798 for f in opts._get_fields(reverse=False, include_parents=False) 

799 if f.is_relation and f.related_model is not None 

800 ) 

801 for f in fields_with_relations: 

802 if not isinstance(f.remote_field.model, str): 802 ↛ 801line 802 didn't jump to line 801, because the condition on line 802 was never false

803 remote_label = f.remote_field.model._meta.concrete_model._meta.label 

804 related_objects_graph[remote_label].append(f) 

805 

806 for model in all_models: 

807 # Set the relation_tree using the internal __dict__. In this way 

808 # we avoid calling the cached property. In attribute lookup, 

809 # __dict__ takes precedence over a data descriptor (such as 

810 # @cached_property). This means that the _meta._relation_tree is 

811 # only called if related_objects is not in __dict__. 

812 related_objects = related_objects_graph[ 

813 model._meta.concrete_model._meta.label 

814 ] 

815 model._meta.__dict__["_relation_tree"] = related_objects 

816 # It seems it is possible that self is not in all_models, so guard 

817 # against that with default for get(). 

818 return self.__dict__.get("_relation_tree", EMPTY_RELATION_TREE) 

819 

820 @cached_property 

821 def _relation_tree(self): 

822 return self._populate_directed_relation_graph() 

823 

824 def _expire_cache(self, forward=True, reverse=True): 

825 # This method is usually called by apps.cache_clear(), when the 

826 # registry is finalized, or when a new field is added. 

827 if forward: 

828 for cache_key in self.FORWARD_PROPERTIES: 

829 if cache_key in self.__dict__: 

830 delattr(self, cache_key) 

831 if reverse and not self.abstract: 

832 for cache_key in self.REVERSE_PROPERTIES: 

833 if cache_key in self.__dict__: 

834 delattr(self, cache_key) 

835 self._get_fields_cache = {} 

836 

837 def get_fields(self, include_parents=True, include_hidden=False): 

838 """ 

839 Return a list of fields associated to the model. By default, include 

840 forward and reverse fields, fields derived from inheritance, but not 

841 hidden fields. The returned fields can be changed using the parameters: 

842 

843 - include_parents: include fields derived from inheritance 

844 - include_hidden: include fields that have a related_name that 

845 starts with a "+" 

846 """ 

847 if include_parents is False: 847 ↛ 848line 847 didn't jump to line 848, because the condition on line 847 was never true

848 include_parents = PROXY_PARENTS 

849 return self._get_fields( 

850 include_parents=include_parents, include_hidden=include_hidden 

851 ) 

852 

853 def _get_fields( 

854 self, 

855 forward=True, 

856 reverse=True, 

857 include_parents=True, 

858 include_hidden=False, 

859 seen_models=None, 

860 ): 

861 """ 

862 Internal helper function to return fields of the model. 

863 * If forward=True, then fields defined on this model are returned. 

864 * If reverse=True, then relations pointing to this model are returned. 

865 * If include_hidden=True, then fields with is_hidden=True are returned. 

866 * The include_parents argument toggles if fields from parent models 

867 should be included. It has three values: True, False, and 

868 PROXY_PARENTS. When set to PROXY_PARENTS, the call will return all 

869 fields defined for the current model or any of its parents in the 

870 parent chain to the model's concrete model. 

871 """ 

872 if include_parents not in (True, False, PROXY_PARENTS): 872 ↛ 873line 872 didn't jump to line 873, because the condition on line 872 was never true

873 raise TypeError( 

874 "Invalid argument for include_parents: %s" % (include_parents,) 

875 ) 

876 # This helper function is used to allow recursion in ``get_fields()`` 

877 # implementation and to provide a fast way for Django's internals to 

878 # access specific subsets of fields. 

879 

880 # We must keep track of which models we have already seen. Otherwise we 

881 # could include the same field multiple times from different models. 

882 topmost_call = seen_models is None 

883 if topmost_call: 

884 seen_models = set() 

885 seen_models.add(self.model) 

886 

887 # Creates a cache key composed of all arguments 

888 cache_key = (forward, reverse, include_parents, include_hidden, topmost_call) 

889 

890 try: 

891 # In order to avoid list manipulation. Always return a shallow copy 

892 # of the results. 

893 return self._get_fields_cache[cache_key] 

894 except KeyError: 

895 pass 

896 

897 fields = [] 

898 # Recursively call _get_fields() on each parent, with the same 

899 # options provided in this call. 

900 if include_parents is not False: 

901 for parent in self.parents: 

902 # In diamond inheritance it is possible that we see the same 

903 # model from two different routes. In that case, avoid adding 

904 # fields from the same parent again. 

905 if parent in seen_models: 905 ↛ 906line 905 didn't jump to line 906, because the condition on line 905 was never true

906 continue 

907 if ( 

908 parent._meta.concrete_model != self.concrete_model 

909 and include_parents == PROXY_PARENTS 

910 ): 

911 continue 

912 for obj in parent._meta._get_fields( 

913 forward=forward, 

914 reverse=reverse, 

915 include_parents=include_parents, 

916 include_hidden=include_hidden, 

917 seen_models=seen_models, 

918 ): 

919 if ( 

920 not getattr(obj, "parent_link", False) 

921 or obj.model == self.concrete_model 

922 ): 

923 fields.append(obj) 

924 if reverse and not self.proxy: 

925 # Tree is computed once and cached until the app cache is expired. 

926 # It is composed of a list of fields pointing to the current model 

927 # from other models. 

928 all_fields = self._relation_tree 

929 for field in all_fields: 

930 # If hidden fields should be included or the relation is not 

931 # intentionally hidden, add to the fields dict. 

932 if include_hidden or not field.remote_field.hidden: 

933 fields.append(field.remote_field) 

934 

935 if forward: 

936 fields += self.local_fields 

937 fields += self.local_many_to_many 

938 # Private fields are recopied to each child model, and they get a 

939 # different model as field.model in each child. Hence we have to 

940 # add the private fields separately from the topmost call. If we 

941 # did this recursively similar to local_fields, we would get field 

942 # instances with field.model != self.model. 

943 if topmost_call: 

944 fields += self.private_fields 

945 

946 # In order to avoid list manipulation. Always 

947 # return a shallow copy of the results 

948 fields = make_immutable_fields_list("get_fields()", fields) 

949 

950 # Store result into cache for later access 

951 self._get_fields_cache[cache_key] = fields 

952 return fields 

953 

954 @cached_property 

955 def total_unique_constraints(self): 

956 """ 

957 Return a list of total unique constraints. Useful for determining set 

958 of fields guaranteed to be unique for all rows. 

959 """ 

960 return [ 

961 constraint 

962 for constraint in self.constraints 

963 if ( 

964 isinstance(constraint, UniqueConstraint) 

965 and constraint.condition is None 

966 and not constraint.contains_expressions 

967 ) 

968 ] 

969 

970 @cached_property 

971 def _property_names(self): 

972 """Return a set of the names of the properties defined on the model.""" 

973 names = [] 

974 for name in dir(self.model): 

975 attr = inspect.getattr_static(self.model, name) 

976 if isinstance(attr, property): 

977 names.append(name) 

978 return frozenset(names) 

979 

980 @cached_property 

981 def db_returning_fields(self): 

982 """ 

983 Private API intended only to be used by Django itself. 

984 Fields to be returned after a database insert. 

985 """ 

986 return [ 

987 field 

988 for field in self._get_fields( 

989 forward=True, reverse=False, include_parents=PROXY_PARENTS 

990 ) 

991 if getattr(field, "db_returning", False) 

992 ]