Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/db/models/fields/related.py: 24%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

778 statements  

1import functools 

2import inspect 

3from functools import partial 

4 

5from django import forms 

6from django.apps import apps 

7from django.conf import SettingsReference, settings 

8from django.core import checks, exceptions 

9from django.db import connection, router 

10from django.db.backends import utils 

11from django.db.models import Q 

12from django.db.models.constants import LOOKUP_SEP 

13from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL 

14from django.db.models.query_utils import PathInfo 

15from django.db.models.utils import make_model_tuple 

16from django.utils.functional import cached_property 

17from django.utils.translation import gettext_lazy as _ 

18 

19from . import Field 

20from .mixins import FieldCacheMixin 

21from .related_descriptors import ( 

22 ForeignKeyDeferredAttribute, 

23 ForwardManyToOneDescriptor, 

24 ForwardOneToOneDescriptor, 

25 ManyToManyDescriptor, 

26 ReverseManyToOneDescriptor, 

27 ReverseOneToOneDescriptor, 

28) 

29from .related_lookups import ( 

30 RelatedExact, 

31 RelatedGreaterThan, 

32 RelatedGreaterThanOrEqual, 

33 RelatedIn, 

34 RelatedIsNull, 

35 RelatedLessThan, 

36 RelatedLessThanOrEqual, 

37) 

38from .reverse_related import ForeignObjectRel, ManyToManyRel, ManyToOneRel, OneToOneRel 

39 

40RECURSIVE_RELATIONSHIP_CONSTANT = "self" 

41 

42 

43def resolve_relation(scope_model, relation): 

44 """ 

45 Transform relation into a model or fully-qualified model string of the form 

46 "app_label.ModelName", relative to scope_model. 

47 

48 The relation argument can be: 

49 * RECURSIVE_RELATIONSHIP_CONSTANT, i.e. the string "self", in which case 

50 the model argument will be returned. 

51 * A bare model name without an app_label, in which case scope_model's 

52 app_label will be prepended. 

53 * An "app_label.ModelName" string. 

54 * A model class, which will be returned unchanged. 

55 """ 

56 # Check for recursive relations 

57 if relation == RECURSIVE_RELATIONSHIP_CONSTANT: 

58 relation = scope_model 

59 

60 # Look for an "app.Model" relation 

61 if isinstance(relation, str): 

62 if "." not in relation: 

63 relation = "%s.%s" % (scope_model._meta.app_label, relation) 

64 

65 return relation 

66 

67 

68def lazy_related_operation(function, model, *related_models, **kwargs): 

69 """ 

70 Schedule `function` to be called once `model` and all `related_models` 

71 have been imported and registered with the app registry. `function` will 

72 be called with the newly-loaded model classes as its positional arguments, 

73 plus any optional keyword arguments. 

74 

75 The `model` argument must be a model class. Each subsequent positional 

76 argument is another model, or a reference to another model - see 

77 `resolve_relation()` for the various forms these may take. Any relative 

78 references will be resolved relative to `model`. 

79 

80 This is a convenience wrapper for `Apps.lazy_model_operation` - the app 

81 registry model used is the one found in `model._meta.apps`. 

82 """ 

83 models = [model] + [resolve_relation(model, rel) for rel in related_models] 

84 model_keys = (make_model_tuple(m) for m in models) 

85 apps = model._meta.apps 

86 return apps.lazy_model_operation(partial(function, **kwargs), *model_keys) 

87 

88 

89class RelatedField(FieldCacheMixin, Field): 

90 """Base class that all relational fields inherit from.""" 

91 

92 # Field flags 

93 one_to_many = False 

94 one_to_one = False 

95 many_to_many = False 

96 many_to_one = False 

97 

98 def __init__( 

99 self, 

100 related_name=None, 

101 related_query_name=None, 

102 limit_choices_to=None, 

103 **kwargs, 

104 ): 

105 self._related_name = related_name 

106 self._related_query_name = related_query_name 

107 self._limit_choices_to = limit_choices_to 

108 super().__init__(**kwargs) 

109 

110 @cached_property 

111 def related_model(self): 

112 # Can't cache this property until all the models are loaded. 

113 apps.check_models_ready() 

114 return self.remote_field.model 

115 

116 def check(self, **kwargs): 

117 return [ 

118 *super().check(**kwargs), 

119 *self._check_related_name_is_valid(), 

120 *self._check_related_query_name_is_valid(), 

121 *self._check_relation_model_exists(), 

122 *self._check_referencing_to_swapped_model(), 

123 *self._check_clashes(), 

124 ] 

125 

126 def _check_related_name_is_valid(self): 

127 import keyword 

128 

129 related_name = self.remote_field.related_name 

130 if related_name is None: 

131 return [] 

132 is_valid_id = ( 

133 not keyword.iskeyword(related_name) and related_name.isidentifier() 

134 ) 

135 if not (is_valid_id or related_name.endswith("+")): 

136 return [ 

137 checks.Error( 

138 "The name '%s' is invalid related_name for field %s.%s" 

139 % ( 

140 self.remote_field.related_name, 

141 self.model._meta.object_name, 

142 self.name, 

143 ), 

144 hint=( 

145 "Related name must be a valid Python identifier or end with a " 

146 "'+'" 

147 ), 

148 obj=self, 

149 id="fields.E306", 

150 ) 

151 ] 

152 return [] 

153 

154 def _check_related_query_name_is_valid(self): 

155 if self.remote_field.hidden: 

156 return [] 

157 rel_query_name = self.related_query_name() 

158 errors = [] 

159 if rel_query_name.endswith("_"): 

160 errors.append( 

161 checks.Error( 

162 "Reverse query name '%s' must not end with an underscore." 

163 % rel_query_name, 

164 hint=( 

165 "Add or change a related_name or related_query_name " 

166 "argument for this field." 

167 ), 

168 obj=self, 

169 id="fields.E308", 

170 ) 

171 ) 

172 if LOOKUP_SEP in rel_query_name: 

173 errors.append( 

174 checks.Error( 

175 "Reverse query name '%s' must not contain '%s'." 

176 % (rel_query_name, LOOKUP_SEP), 

177 hint=( 

178 "Add or change a related_name or related_query_name " 

179 "argument for this field." 

180 ), 

181 obj=self, 

182 id="fields.E309", 

183 ) 

184 ) 

185 return errors 

186 

187 def _check_relation_model_exists(self): 

188 rel_is_missing = self.remote_field.model not in self.opts.apps.get_models( 

189 include_auto_created=True 

190 ) 

191 rel_is_string = isinstance(self.remote_field.model, str) 

192 model_name = ( 

193 self.remote_field.model 

194 if rel_is_string 

195 else self.remote_field.model._meta.object_name 

196 ) 

197 if rel_is_missing and ( 

198 rel_is_string or not self.remote_field.model._meta.swapped 

199 ): 

200 return [ 

201 checks.Error( 

202 "Field defines a relation with model '%s', which is either " 

203 "not installed, or is abstract." % model_name, 

204 obj=self, 

205 id="fields.E300", 

206 ) 

207 ] 

208 return [] 

209 

210 def _check_referencing_to_swapped_model(self): 

211 if ( 

212 self.remote_field.model not in self.opts.apps.get_models() 

213 and not isinstance(self.remote_field.model, str) 

214 and self.remote_field.model._meta.swapped 

215 ): 

216 return [ 

217 checks.Error( 

218 "Field defines a relation with the model '%s', which has " 

219 "been swapped out." % self.remote_field.model._meta.label, 

220 hint="Update the relation to point at 'settings.%s'." 

221 % self.remote_field.model._meta.swappable, 

222 obj=self, 

223 id="fields.E301", 

224 ) 

225 ] 

226 return [] 

227 

228 def _check_clashes(self): 

229 """Check accessor and reverse query name clashes.""" 

230 from django.db.models.base import ModelBase 

231 

232 errors = [] 

233 opts = self.model._meta 

234 

235 # f.remote_field.model may be a string instead of a model. Skip if 

236 # model name is not resolved. 

237 if not isinstance(self.remote_field.model, ModelBase): 

238 return [] 

239 

240 # Consider that we are checking field `Model.foreign` and the models 

241 # are: 

242 # 

243 # class Target(models.Model): 

244 # model = models.IntegerField() 

245 # model_set = models.IntegerField() 

246 # 

247 # class Model(models.Model): 

248 # foreign = models.ForeignKey(Target) 

249 # m2m = models.ManyToManyField(Target) 

250 

251 # rel_opts.object_name == "Target" 

252 rel_opts = self.remote_field.model._meta 

253 # If the field doesn't install a backward relation on the target model 

254 # (so `is_hidden` returns True), then there are no clashes to check 

255 # and we can skip these fields. 

256 rel_is_hidden = self.remote_field.hidden 

257 rel_name = self.remote_field.accessor_name # i. e. "model_set" 

258 rel_query_name = self.related_query_name() # i. e. "model" 

259 # i.e. "app_label.Model.field". 

260 field_name = "%s.%s" % (opts.label, self.name) 

261 

262 # Check clashes between accessor or reverse query name of `field` 

263 # and any other field name -- i.e. accessor for Model.foreign is 

264 # model_set and it clashes with Target.model_set. 

265 potential_clashes = rel_opts.fields + rel_opts.many_to_many 

266 for clash_field in potential_clashes: 

267 if not rel_is_hidden and clash_field.name == rel_name: 

268 clash_name = f"{rel_opts.label}.{clash_field.name}" 

269 errors.append( 

270 checks.Error( 

271 f"Reverse accessor '{rel_opts.object_name}.{rel_name}' " 

272 f"for '{field_name}' clashes with field name " 

273 f"'{clash_name}'.", 

274 hint=( 

275 "Rename field '%s', or add/change a related_name " 

276 "argument to the definition for field '%s'." 

277 ) 

278 % (clash_name, field_name), 

279 obj=self, 

280 id="fields.E302", 

281 ) 

282 ) 

283 

284 if clash_field.name == rel_query_name: 

285 clash_name = f"{rel_opts.label}.{clash_field.name}" 

286 errors.append( 

287 checks.Error( 

288 "Reverse query name for '%s' clashes with field name '%s'." 

289 % (field_name, clash_name), 

290 hint=( 

291 "Rename field '%s', or add/change a related_name " 

292 "argument to the definition for field '%s'." 

293 ) 

294 % (clash_name, field_name), 

295 obj=self, 

296 id="fields.E303", 

297 ) 

298 ) 

299 

300 # Check clashes between accessors/reverse query names of `field` and 

301 # any other field accessor -- i. e. Model.foreign accessor clashes with 

302 # Model.m2m accessor. 

303 potential_clashes = (r for r in rel_opts.related_objects if r.field is not self) 

304 for clash_field in potential_clashes: 

305 if not rel_is_hidden and clash_field.accessor_name == rel_name: 

306 clash_name = ( 

307 f"{clash_field.related_model._meta.label}.{clash_field.field.name}" 

308 ) 

309 errors.append( 

310 checks.Error( 

311 f"Reverse accessor '{rel_opts.object_name}.{rel_name}' " 

312 f"for '{field_name}' clashes with reverse accessor for " 

313 f"'{clash_name}'.", 

314 hint=( 

315 "Add or change a related_name argument " 

316 "to the definition for '%s' or '%s'." 

317 ) 

318 % (field_name, clash_name), 

319 obj=self, 

320 id="fields.E304", 

321 ) 

322 ) 

323 

324 if clash_field.accessor_name == rel_query_name: 

325 clash_name = ( 

326 f"{clash_field.related_model._meta.label}.{clash_field.field.name}" 

327 ) 

328 errors.append( 

329 checks.Error( 

330 "Reverse query name for '%s' clashes with reverse query name " 

331 "for '%s'." % (field_name, clash_name), 

332 hint=( 

333 "Add or change a related_name argument " 

334 "to the definition for '%s' or '%s'." 

335 ) 

336 % (field_name, clash_name), 

337 obj=self, 

338 id="fields.E305", 

339 ) 

340 ) 

341 

342 return errors 

343 

344 def db_type(self, connection): 

345 # By default related field will not have a column as it relates to 

346 # columns from another table. 

347 return None 

348 

349 def contribute_to_class(self, cls, name, private_only=False, **kwargs): 

350 super().contribute_to_class(cls, name, private_only=private_only, **kwargs) 

351 

352 self.opts = cls._meta 

353 

354 if not cls._meta.abstract: 

355 if self.remote_field.related_name: 

356 related_name = self.remote_field.related_name 

357 else: 

358 related_name = self.opts.default_related_name 

359 if related_name: 

360 related_name %= { 

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

362 "model_name": cls._meta.model_name.lower(), 

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

364 } 

365 self.remote_field.related_name = related_name 

366 

367 if self.remote_field.related_query_name: 

368 related_query_name = self.remote_field.related_query_name % { 

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

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

371 } 

372 self.remote_field.related_query_name = related_query_name 

373 

374 def resolve_related_class(model, related, field): 

375 field.remote_field.model = related 

376 field.do_related_class(related, model) 

377 

378 lazy_related_operation( 

379 resolve_related_class, cls, self.remote_field.model, field=self 

380 ) 

381 

382 def deconstruct(self): 

383 name, path, args, kwargs = super().deconstruct() 

384 if self._limit_choices_to: 

385 kwargs["limit_choices_to"] = self._limit_choices_to 

386 if self._related_name is not None: 

387 kwargs["related_name"] = self._related_name 

388 if self._related_query_name is not None: 

389 kwargs["related_query_name"] = self._related_query_name 

390 return name, path, args, kwargs 

391 

392 def get_forward_related_filter(self, obj): 

393 """ 

394 Return the keyword arguments that when supplied to 

395 self.model.object.filter(), would select all instances related through 

396 this field to the remote obj. This is used to build the querysets 

397 returned by related descriptors. obj is an instance of 

398 self.related_field.model. 

399 """ 

400 return { 

401 "%s__%s" % (self.name, rh_field.name): getattr(obj, rh_field.attname) 

402 for _, rh_field in self.related_fields 

403 } 

404 

405 def get_reverse_related_filter(self, obj): 

406 """ 

407 Complement to get_forward_related_filter(). Return the keyword 

408 arguments that when passed to self.related_field.model.object.filter() 

409 select all instances of self.related_field.model related through 

410 this field to obj. obj is an instance of self.model. 

411 """ 

412 base_q = Q.create( 

413 [ 

414 (rh_field.attname, getattr(obj, lh_field.attname)) 

415 for lh_field, rh_field in self.related_fields 

416 ] 

417 ) 

418 descriptor_filter = self.get_extra_descriptor_filter(obj) 

419 if isinstance(descriptor_filter, dict): 

420 return base_q & Q(**descriptor_filter) 

421 elif descriptor_filter: 

422 return base_q & descriptor_filter 

423 return base_q 

424 

425 @property 

426 def swappable_setting(self): 

427 """ 

428 Get the setting that this is powered from for swapping, or None 

429 if it's not swapped in / marked with swappable=False. 

430 """ 

431 if self.swappable: 

432 # Work out string form of "to" 

433 if isinstance(self.remote_field.model, str): 

434 to_string = self.remote_field.model 

435 else: 

436 to_string = self.remote_field.model._meta.label 

437 return apps.get_swappable_settings_name(to_string) 

438 return None 

439 

440 def set_attributes_from_rel(self): 

441 self.name = self.name or ( 

442 self.remote_field.model._meta.model_name 

443 + "_" 

444 + self.remote_field.model._meta.pk.name 

445 ) 

446 if self.verbose_name is None: 

447 self.verbose_name = self.remote_field.model._meta.verbose_name 

448 self.remote_field.set_field_name() 

449 

450 def do_related_class(self, other, cls): 

451 self.set_attributes_from_rel() 

452 self.contribute_to_related_class(other, self.remote_field) 

453 

454 def get_limit_choices_to(self): 

455 """ 

456 Return ``limit_choices_to`` for this model field. 

457 

458 If it is a callable, it will be invoked and the result will be 

459 returned. 

460 """ 

461 if callable(self.remote_field.limit_choices_to): 

462 return self.remote_field.limit_choices_to() 

463 return self.remote_field.limit_choices_to 

464 

465 def formfield(self, **kwargs): 

466 """ 

467 Pass ``limit_choices_to`` to the field being constructed. 

468 

469 Only passes it if there is a type that supports related fields. 

470 This is a similar strategy used to pass the ``queryset`` to the field 

471 being constructed. 

472 """ 

473 defaults = {} 

474 if hasattr(self.remote_field, "get_related_field"): 

475 # If this is a callable, do not invoke it here. Just pass 

476 # it in the defaults for when the form class will later be 

477 # instantiated. 

478 limit_choices_to = self.remote_field.limit_choices_to 

479 defaults.update( 

480 { 

481 "limit_choices_to": limit_choices_to, 

482 } 

483 ) 

484 defaults.update(kwargs) 

485 return super().formfield(**defaults) 

486 

487 def related_query_name(self): 

488 """ 

489 Define the name that can be used to identify this related object in a 

490 table-spanning query. 

491 """ 

492 return ( 

493 self.remote_field.related_query_name 

494 or self.remote_field.related_name 

495 or self.opts.model_name 

496 ) 

497 

498 @property 

499 def target_field(self): 

500 """ 

501 When filtering against this relation, return the field on the remote 

502 model against which the filtering should happen. 

503 """ 

504 target_fields = self.path_infos[-1].target_fields 

505 if len(target_fields) > 1: 

506 raise exceptions.FieldError( 

507 "The relation has multiple target fields, but only single target field " 

508 "was asked for" 

509 ) 

510 return target_fields[0] 

511 

512 @cached_property 

513 def cache_name(self): 

514 return self.name 

515 

516 

517class ForeignObject(RelatedField): 

518 """ 

519 Abstraction of the ForeignKey relation to support multi-column relations. 

520 """ 

521 

522 # Field flags 

523 many_to_many = False 

524 many_to_one = True 

525 one_to_many = False 

526 one_to_one = False 

527 

528 requires_unique_target = True 

529 related_accessor_class = ReverseManyToOneDescriptor 

530 forward_related_accessor_class = ForwardManyToOneDescriptor 

531 rel_class = ForeignObjectRel 

532 

533 def __init__( 

534 self, 

535 to, 

536 on_delete, 

537 from_fields, 

538 to_fields, 

539 rel=None, 

540 related_name=None, 

541 related_query_name=None, 

542 limit_choices_to=None, 

543 parent_link=False, 

544 swappable=True, 

545 **kwargs, 

546 ): 

547 if rel is None: 

548 rel = self.rel_class( 

549 self, 

550 to, 

551 related_name=related_name, 

552 related_query_name=related_query_name, 

553 limit_choices_to=limit_choices_to, 

554 parent_link=parent_link, 

555 on_delete=on_delete, 

556 ) 

557 

558 super().__init__( 

559 rel=rel, 

560 related_name=related_name, 

561 related_query_name=related_query_name, 

562 limit_choices_to=limit_choices_to, 

563 **kwargs, 

564 ) 

565 

566 self.from_fields = from_fields 

567 self.to_fields = to_fields 

568 self.swappable = swappable 

569 

570 def __copy__(self): 

571 obj = super().__copy__() 

572 # Remove any cached PathInfo values. 

573 obj.__dict__.pop("path_infos", None) 

574 obj.__dict__.pop("reverse_path_infos", None) 

575 return obj 

576 

577 def check(self, **kwargs): 

578 return [ 

579 *super().check(**kwargs), 

580 *self._check_to_fields_exist(), 

581 *self._check_to_fields_composite_pk(), 

582 *self._check_unique_target(), 

583 ] 

584 

585 def _check_to_fields_exist(self): 

586 # Skip nonexistent models. 

587 if isinstance(self.remote_field.model, str): 

588 return [] 

589 

590 errors = [] 

591 for to_field in self.to_fields: 

592 if to_field: 

593 try: 

594 self.remote_field.model._meta.get_field(to_field) 

595 except exceptions.FieldDoesNotExist: 

596 errors.append( 

597 checks.Error( 

598 "The to_field '%s' doesn't exist on the related " 

599 "model '%s'." 

600 % (to_field, self.remote_field.model._meta.label), 

601 obj=self, 

602 id="fields.E312", 

603 ) 

604 ) 

605 return errors 

606 

607 def _check_to_fields_composite_pk(self): 

608 from django.db.models.fields.composite import CompositePrimaryKey 

609 

610 # Skip nonexistent models. 

611 if isinstance(self.remote_field.model, str): 

612 return [] 

613 

614 errors = [] 

615 for to_field in self.to_fields: 

616 try: 

617 field = ( 

618 self.remote_field.model._meta.pk 

619 if to_field is None 

620 else self.remote_field.model._meta.get_field(to_field) 

621 ) 

622 except exceptions.FieldDoesNotExist: 

623 pass 

624 else: 

625 if isinstance(field, CompositePrimaryKey): 

626 errors.append( 

627 checks.Error( 

628 "Field defines a relation to the CompositePrimaryKey of " 

629 f"model {self.remote_field.model._meta.object_name!r} " 

630 "which is not supported.", 

631 obj=self, 

632 id="fields.E347", 

633 ) 

634 ) 

635 return errors 

636 

637 def _check_unique_target(self): 

638 rel_is_string = isinstance(self.remote_field.model, str) 

639 if rel_is_string or not self.requires_unique_target: 

640 return [] 

641 

642 try: 

643 self.foreign_related_fields 

644 except exceptions.FieldDoesNotExist: 

645 return [] 

646 

647 if not self.foreign_related_fields: 

648 return [] 

649 

650 has_unique_constraint = any( 

651 rel_field.unique for rel_field in self.foreign_related_fields 

652 ) 

653 if not has_unique_constraint: 

654 foreign_fields = {f.name for f in self.foreign_related_fields} 

655 remote_opts = self.remote_field.model._meta 

656 has_unique_constraint = ( 

657 any( 

658 frozenset(ut) <= foreign_fields 

659 for ut in remote_opts.unique_together 

660 ) 

661 or any( 

662 frozenset(uc.fields) <= foreign_fields 

663 for uc in remote_opts.total_unique_constraints 

664 ) 

665 # If the model defines a composite primary key and the foreign key 

666 # refers to it, the target is unique. 

667 or ( 

668 frozenset(field.name for field in remote_opts.pk_fields) 

669 == foreign_fields 

670 ) 

671 ) 

672 

673 if not has_unique_constraint: 

674 if len(self.foreign_related_fields) > 1: 

675 field_combination = ", ".join( 

676 f"'{rel_field.name}'" for rel_field in self.foreign_related_fields 

677 ) 

678 model_name = self.remote_field.model.__name__ 

679 return [ 

680 checks.Error( 

681 f"No subset of the fields {field_combination} on model " 

682 f"'{model_name}' is unique.", 

683 hint=( 

684 "Mark a single field as unique=True or add a set of " 

685 "fields to a unique constraint (via unique_together " 

686 "or a UniqueConstraint (without condition) in the " 

687 "model Meta.constraints)." 

688 ), 

689 obj=self, 

690 id="fields.E310", 

691 ) 

692 ] 

693 else: 

694 field_name = self.foreign_related_fields[0].name 

695 model_name = self.remote_field.model.__name__ 

696 return [ 

697 checks.Error( 

698 f"'{model_name}.{field_name}' must be unique because it is " 

699 "referenced by a foreign key.", 

700 hint=( 

701 "Add unique=True to this field or add a " 

702 "UniqueConstraint (without condition) in the model " 

703 "Meta.constraints." 

704 ), 

705 obj=self, 

706 id="fields.E311", 

707 ) 

708 ] 

709 return [] 

710 

711 def deconstruct(self): 

712 name, path, args, kwargs = super().deconstruct() 

713 kwargs["on_delete"] = self.remote_field.on_delete 

714 kwargs["from_fields"] = self.from_fields 

715 kwargs["to_fields"] = self.to_fields 

716 

717 if self.remote_field.parent_link: 

718 kwargs["parent_link"] = self.remote_field.parent_link 

719 if isinstance(self.remote_field.model, str): 

720 if "." in self.remote_field.model: 

721 app_label, model_name = self.remote_field.model.split(".") 

722 kwargs["to"] = "%s.%s" % (app_label, model_name.lower()) 

723 else: 

724 kwargs["to"] = self.remote_field.model.lower() 

725 else: 

726 kwargs["to"] = self.remote_field.model._meta.label_lower 

727 # If swappable is True, then see if we're actually pointing to the target 

728 # of a swap. 

729 swappable_setting = self.swappable_setting 

730 if swappable_setting is not None: 

731 # If it's already a settings reference, error 

732 if hasattr(kwargs["to"], "setting_name"): 

733 if kwargs["to"].setting_name != swappable_setting: 

734 raise ValueError( 

735 "Cannot deconstruct a ForeignKey pointing to a model " 

736 "that is swapped in place of more than one model (%s and %s)" 

737 % (kwargs["to"].setting_name, swappable_setting) 

738 ) 

739 # Set it 

740 kwargs["to"] = SettingsReference( 

741 kwargs["to"], 

742 swappable_setting, 

743 ) 

744 return name, path, args, kwargs 

745 

746 def resolve_related_fields(self): 

747 if not self.from_fields or len(self.from_fields) != len(self.to_fields): 

748 raise ValueError( 

749 "Foreign Object from and to fields must be the same non-zero length" 

750 ) 

751 if isinstance(self.remote_field.model, str): 

752 raise ValueError( 

753 "Related model %r cannot be resolved" % self.remote_field.model 

754 ) 

755 related_fields = [] 

756 for from_field_name, to_field_name in zip(self.from_fields, self.to_fields): 

757 from_field = ( 

758 self 

759 if from_field_name == RECURSIVE_RELATIONSHIP_CONSTANT 

760 else self.opts.get_field(from_field_name) 

761 ) 

762 to_field = ( 

763 self.remote_field.model._meta.pk 

764 if to_field_name is None 

765 else self.remote_field.model._meta.get_field(to_field_name) 

766 ) 

767 related_fields.append((from_field, to_field)) 

768 return related_fields 

769 

770 @cached_property 

771 def related_fields(self): 

772 return self.resolve_related_fields() 

773 

774 @cached_property 

775 def reverse_related_fields(self): 

776 return [(rhs_field, lhs_field) for lhs_field, rhs_field in self.related_fields] 

777 

778 @cached_property 

779 def local_related_fields(self): 

780 return tuple(lhs_field for lhs_field, rhs_field in self.related_fields) 

781 

782 @cached_property 

783 def foreign_related_fields(self): 

784 return tuple( 

785 rhs_field for lhs_field, rhs_field in self.related_fields if rhs_field 

786 ) 

787 

788 def get_local_related_value(self, instance): 

789 return self.get_instance_value_for_fields(instance, self.local_related_fields) 

790 

791 def get_foreign_related_value(self, instance): 

792 return self.get_instance_value_for_fields(instance, self.foreign_related_fields) 

793 

794 @staticmethod 

795 def get_instance_value_for_fields(instance, fields): 

796 ret = [] 

797 opts = instance._meta 

798 for field in fields: 

799 # Gotcha: in some cases (like fixture loading) a model can have 

800 # different values in parent_ptr_id and parent's id. So, use 

801 # instance.pk (that is, parent_ptr_id) when asked for instance.id. 

802 if field.primary_key: 

803 possible_parent_link = opts.get_ancestor_link(field.model) 

804 if ( 

805 not possible_parent_link 

806 or possible_parent_link.primary_key 

807 or possible_parent_link.model._meta.abstract 

808 ): 

809 ret.append(instance.pk) 

810 continue 

811 ret.append(getattr(instance, field.attname)) 

812 return tuple(ret) 

813 

814 def get_attname_column(self): 

815 attname, column = super().get_attname_column() 

816 return attname, None 

817 

818 def get_joining_fields(self, reverse_join=False): 

819 return tuple( 

820 self.reverse_related_fields if reverse_join else self.related_fields 

821 ) 

822 

823 def get_reverse_joining_fields(self): 

824 return self.get_joining_fields(reverse_join=True) 

825 

826 def get_extra_descriptor_filter(self, instance): 

827 """ 

828 Return an extra filter condition for related object fetching when 

829 user does 'instance.fieldname', that is the extra filter is used in 

830 the descriptor of the field. 

831 

832 The filter should be either a dict usable in .filter(**kwargs) call or 

833 a Q-object. The condition will be ANDed together with the relation's 

834 joining columns. 

835 

836 A parallel method is get_extra_restriction() which is used in 

837 JOIN and subquery conditions. 

838 """ 

839 return {} 

840 

841 def get_extra_restriction(self, alias, related_alias): 

842 """ 

843 Return a pair condition used for joining and subquery pushdown. The 

844 condition is something that responds to as_sql(compiler, connection) 

845 method. 

846 

847 Note that currently referring both the 'alias' and 'related_alias' 

848 will not work in some conditions, like subquery pushdown. 

849 

850 A parallel method is get_extra_descriptor_filter() which is used in 

851 instance.fieldname related object fetching. 

852 """ 

853 return None 

854 

855 def get_path_info(self, filtered_relation=None): 

856 """Get path from this field to the related model.""" 

857 opts = self.remote_field.model._meta 

858 from_opts = self.model._meta 

859 return [ 

860 PathInfo( 

861 from_opts=from_opts, 

862 to_opts=opts, 

863 target_fields=self.foreign_related_fields, 

864 join_field=self, 

865 m2m=False, 

866 direct=True, 

867 filtered_relation=filtered_relation, 

868 ) 

869 ] 

870 

871 @cached_property 

872 def path_infos(self): 

873 return self.get_path_info() 

874 

875 def get_reverse_path_info(self, filtered_relation=None): 

876 """Get path from the related model to this field's model.""" 

877 opts = self.model._meta 

878 from_opts = self.remote_field.model._meta 

879 return [ 

880 PathInfo( 

881 from_opts=from_opts, 

882 to_opts=opts, 

883 target_fields=(opts.pk,), 

884 join_field=self.remote_field, 

885 m2m=not self.unique, 

886 direct=False, 

887 filtered_relation=filtered_relation, 

888 ) 

889 ] 

890 

891 @cached_property 

892 def reverse_path_infos(self): 

893 return self.get_reverse_path_info() 

894 

895 @classmethod 

896 @functools.cache 

897 def get_class_lookups(cls): 

898 bases = inspect.getmro(cls) 

899 bases = bases[: bases.index(ForeignObject) + 1] 

900 class_lookups = [parent.__dict__.get("class_lookups", {}) for parent in bases] 

901 return cls.merge_dicts(class_lookups) 

902 

903 def contribute_to_class(self, cls, name, private_only=False, **kwargs): 

904 super().contribute_to_class(cls, name, private_only=private_only, **kwargs) 

905 setattr(cls, self.name, self.forward_related_accessor_class(self)) 

906 

907 def contribute_to_related_class(self, cls, related): 

908 # Internal FK's - i.e., those with a related name ending with '+' - 

909 # and swapped models don't get a related descriptor. 

910 if not self.remote_field.hidden and not related.related_model._meta.swapped: 

911 setattr( 

912 cls._meta.concrete_model, 

913 related.accessor_name, 

914 self.related_accessor_class(related), 

915 ) 

916 # While 'limit_choices_to' might be a callable, simply pass 

917 # it along for later - this is too early because it's still 

918 # model load time. 

919 if self.remote_field.limit_choices_to: 

920 cls._meta.related_fkey_lookups.append( 

921 self.remote_field.limit_choices_to 

922 ) 

923 

924 

925ForeignObject.register_lookup(RelatedIn) 

926ForeignObject.register_lookup(RelatedExact) 

927ForeignObject.register_lookup(RelatedLessThan) 

928ForeignObject.register_lookup(RelatedGreaterThan) 

929ForeignObject.register_lookup(RelatedGreaterThanOrEqual) 

930ForeignObject.register_lookup(RelatedLessThanOrEqual) 

931ForeignObject.register_lookup(RelatedIsNull) 

932 

933 

934class ForeignKey(ForeignObject): 

935 """ 

936 Provide a many-to-one relation by adding a column to the local model 

937 to hold the remote value. 

938 

939 By default ForeignKey will target the pk of the remote model but this 

940 behavior can be changed by using the ``to_field`` argument. 

941 """ 

942 

943 descriptor_class = ForeignKeyDeferredAttribute 

944 # Field flags 

945 many_to_many = False 

946 many_to_one = True 

947 one_to_many = False 

948 one_to_one = False 

949 

950 rel_class = ManyToOneRel 

951 

952 empty_strings_allowed = False 

953 default_error_messages = { 

954 "invalid": _( 

955 "%(model)s instance with %(field)s %(value)r is not a valid choice." 

956 ) 

957 } 

958 description = _("Foreign Key (type determined by related field)") 

959 

960 def __init__( 

961 self, 

962 to, 

963 on_delete, 

964 related_name=None, 

965 related_query_name=None, 

966 limit_choices_to=None, 

967 parent_link=False, 

968 to_field=None, 

969 db_constraint=True, 

970 **kwargs, 

971 ): 

972 try: 

973 to._meta.model_name 

974 except AttributeError: 

975 if not isinstance(to, str): 

976 raise TypeError( 

977 "%s(%r) is invalid. First parameter to ForeignKey must be " 

978 "either a model, a model name, or the string %r" 

979 % ( 

980 self.__class__.__name__, 

981 to, 

982 RECURSIVE_RELATIONSHIP_CONSTANT, 

983 ) 

984 ) 

985 else: 

986 # For backwards compatibility purposes, we need to *try* and set 

987 # the to_field during FK construction. It won't be guaranteed to 

988 # be correct until contribute_to_class is called. Refs #12190. 

989 to_field = to_field or (to._meta.pk and to._meta.pk.name) 

990 if not callable(on_delete): 

991 raise TypeError("on_delete must be callable.") 

992 

993 kwargs["rel"] = self.rel_class( 

994 self, 

995 to, 

996 to_field, 

997 related_name=related_name, 

998 related_query_name=related_query_name, 

999 limit_choices_to=limit_choices_to, 

1000 parent_link=parent_link, 

1001 on_delete=on_delete, 

1002 ) 

1003 kwargs.setdefault("db_index", True) 

1004 

1005 super().__init__( 

1006 to, 

1007 on_delete, 

1008 related_name=related_name, 

1009 related_query_name=related_query_name, 

1010 limit_choices_to=limit_choices_to, 

1011 from_fields=[RECURSIVE_RELATIONSHIP_CONSTANT], 

1012 to_fields=[to_field], 

1013 **kwargs, 

1014 ) 

1015 self.db_constraint = db_constraint 

1016 

1017 def __class_getitem__(cls, *args, **kwargs): 

1018 return cls 

1019 

1020 def check(self, **kwargs): 

1021 return [ 

1022 *super().check(**kwargs), 

1023 *self._check_on_delete(), 

1024 *self._check_unique(), 

1025 ] 

1026 

1027 def _check_on_delete(self): 

1028 on_delete = getattr(self.remote_field, "on_delete", None) 

1029 if on_delete == SET_NULL and not self.null: 

1030 return [ 

1031 checks.Error( 

1032 "Field specifies on_delete=SET_NULL, but cannot be null.", 

1033 hint=( 

1034 "Set null=True argument on the field, or change the on_delete " 

1035 "rule." 

1036 ), 

1037 obj=self, 

1038 id="fields.E320", 

1039 ) 

1040 ] 

1041 elif on_delete == SET_DEFAULT and not self.has_default(): 

1042 return [ 

1043 checks.Error( 

1044 "Field specifies on_delete=SET_DEFAULT, but has no default value.", 

1045 hint="Set a default value, or change the on_delete rule.", 

1046 obj=self, 

1047 id="fields.E321", 

1048 ) 

1049 ] 

1050 else: 

1051 return [] 

1052 

1053 def _check_unique(self, **kwargs): 

1054 return ( 

1055 [ 

1056 checks.Warning( 

1057 "Setting unique=True on a ForeignKey has the same effect as using " 

1058 "a OneToOneField.", 

1059 hint=( 

1060 "ForeignKey(unique=True) is usually better served by a " 

1061 "OneToOneField." 

1062 ), 

1063 obj=self, 

1064 id="fields.W342", 

1065 ) 

1066 ] 

1067 if self.unique 

1068 else [] 

1069 ) 

1070 

1071 def deconstruct(self): 

1072 name, path, args, kwargs = super().deconstruct() 

1073 del kwargs["to_fields"] 

1074 del kwargs["from_fields"] 

1075 # Handle the simpler arguments 

1076 if self.db_index: 

1077 del kwargs["db_index"] 

1078 else: 

1079 kwargs["db_index"] = False 

1080 if self.db_constraint is not True: 

1081 kwargs["db_constraint"] = self.db_constraint 

1082 # Rel needs more work. 

1083 to_meta = getattr(self.remote_field.model, "_meta", None) 

1084 if self.remote_field.field_name and ( 

1085 not to_meta 

1086 or (to_meta.pk and self.remote_field.field_name != to_meta.pk.name) 

1087 ): 

1088 kwargs["to_field"] = self.remote_field.field_name 

1089 return name, path, args, kwargs 

1090 

1091 def to_python(self, value): 

1092 return self.target_field.to_python(value) 

1093 

1094 @property 

1095 def target_field(self): 

1096 return self.foreign_related_fields[0] 

1097 

1098 def validate(self, value, model_instance): 

1099 if self.remote_field.parent_link: 

1100 return 

1101 super().validate(value, model_instance) 

1102 if value is None: 

1103 return 

1104 

1105 using = router.db_for_read(self.remote_field.model, instance=model_instance) 

1106 qs = self.remote_field.model._base_manager.using(using).filter( 

1107 **{self.remote_field.field_name: value} 

1108 ) 

1109 qs = qs.complex_filter(self.get_limit_choices_to()) 

1110 if not qs.exists(): 

1111 raise exceptions.ValidationError( 

1112 self.error_messages["invalid"], 

1113 code="invalid", 

1114 params={ 

1115 "model": self.remote_field.model._meta.verbose_name, 

1116 "pk": value, 

1117 "field": self.remote_field.field_name, 

1118 "value": value, 

1119 }, # 'pk' is included for backwards compatibility 

1120 ) 

1121 

1122 def resolve_related_fields(self): 

1123 related_fields = super().resolve_related_fields() 

1124 for from_field, to_field in related_fields: 

1125 if ( 

1126 to_field 

1127 and to_field.model != self.remote_field.model._meta.concrete_model 

1128 ): 

1129 raise exceptions.FieldError( 

1130 "'%s.%s' refers to field '%s' which is not local to model " 

1131 "'%s'." 

1132 % ( 

1133 self.model._meta.label, 

1134 self.name, 

1135 to_field.name, 

1136 self.remote_field.model._meta.concrete_model._meta.label, 

1137 ) 

1138 ) 

1139 return related_fields 

1140 

1141 def get_attname(self): 

1142 return "%s_id" % self.name 

1143 

1144 def get_attname_column(self): 

1145 attname = self.get_attname() 

1146 column = self.db_column or attname 

1147 return attname, column 

1148 

1149 def get_default(self): 

1150 """Return the to_field if the default value is an object.""" 

1151 field_default = super().get_default() 

1152 if isinstance(field_default, self.remote_field.model): 

1153 return getattr(field_default, self.target_field.attname) 

1154 return field_default 

1155 

1156 def get_db_prep_save(self, value, connection): 

1157 if value is None or ( 

1158 value == "" 

1159 and ( 

1160 not self.target_field.empty_strings_allowed 

1161 or connection.features.interprets_empty_strings_as_nulls 

1162 ) 

1163 ): 

1164 return None 

1165 else: 

1166 return self.target_field.get_db_prep_save(value, connection=connection) 

1167 

1168 def get_db_prep_value(self, value, connection, prepared=False): 

1169 return self.target_field.get_db_prep_value(value, connection, prepared) 

1170 

1171 def get_prep_value(self, value): 

1172 return self.target_field.get_prep_value(value) 

1173 

1174 def contribute_to_related_class(self, cls, related): 

1175 super().contribute_to_related_class(cls, related) 

1176 if self.remote_field.field_name is None: 

1177 self.remote_field.field_name = cls._meta.pk.name 

1178 

1179 def formfield(self, *, using=None, **kwargs): 

1180 if isinstance(self.remote_field.model, str): 

1181 raise ValueError( 

1182 "Cannot create form field for %r yet, because " 

1183 "its related model %r has not been loaded yet" 

1184 % (self.name, self.remote_field.model) 

1185 ) 

1186 return super().formfield( 

1187 **{ 

1188 "form_class": forms.ModelChoiceField, 

1189 "queryset": self.remote_field.model._default_manager.using(using), 

1190 "to_field_name": self.remote_field.field_name, 

1191 **kwargs, 

1192 "blank": self.blank, 

1193 } 

1194 ) 

1195 

1196 def db_check(self, connection): 

1197 return None 

1198 

1199 def db_type(self, connection): 

1200 return self.target_field.rel_db_type(connection=connection) 

1201 

1202 def cast_db_type(self, connection): 

1203 return self.target_field.cast_db_type(connection=connection) 

1204 

1205 def db_parameters(self, connection): 

1206 target_db_parameters = self.target_field.db_parameters(connection) 

1207 return { 

1208 "type": self.db_type(connection), 

1209 "check": self.db_check(connection), 

1210 "collation": target_db_parameters.get("collation"), 

1211 } 

1212 

1213 def convert_empty_strings(self, value, expression, connection): 

1214 if (not value) and isinstance(value, str): 

1215 return None 

1216 return value 

1217 

1218 def get_db_converters(self, connection): 

1219 converters = super().get_db_converters(connection) 

1220 if connection.features.interprets_empty_strings_as_nulls: 

1221 converters += [self.convert_empty_strings] 

1222 return converters 

1223 

1224 def get_col(self, alias, output_field=None): 

1225 if output_field is None: 

1226 output_field = self.target_field 

1227 while isinstance(output_field, ForeignKey): 

1228 output_field = output_field.target_field 

1229 if output_field is self: 

1230 raise ValueError("Cannot resolve output_field.") 

1231 return super().get_col(alias, output_field) 

1232 

1233 

1234class OneToOneField(ForeignKey): 

1235 """ 

1236 A OneToOneField is essentially the same as a ForeignKey, with the exception 

1237 that it always carries a "unique" constraint with it and the reverse 

1238 relation always returns the object pointed to (since there will only ever 

1239 be one), rather than returning a list. 

1240 """ 

1241 

1242 # Field flags 

1243 many_to_many = False 

1244 many_to_one = False 

1245 one_to_many = False 

1246 one_to_one = True 

1247 

1248 related_accessor_class = ReverseOneToOneDescriptor 

1249 forward_related_accessor_class = ForwardOneToOneDescriptor 

1250 rel_class = OneToOneRel 

1251 

1252 description = _("One-to-one relationship") 

1253 

1254 def __init__(self, to, on_delete, to_field=None, **kwargs): 

1255 kwargs["unique"] = True 

1256 super().__init__(to, on_delete, to_field=to_field, **kwargs) 

1257 

1258 def deconstruct(self): 

1259 name, path, args, kwargs = super().deconstruct() 

1260 if "unique" in kwargs: 

1261 del kwargs["unique"] 

1262 return name, path, args, kwargs 

1263 

1264 def formfield(self, **kwargs): 

1265 if self.remote_field.parent_link: 

1266 return None 

1267 return super().formfield(**kwargs) 

1268 

1269 def save_form_data(self, instance, data): 

1270 if isinstance(data, self.remote_field.model): 

1271 setattr(instance, self.name, data) 

1272 else: 

1273 setattr(instance, self.attname, data) 

1274 # Remote field object must be cleared otherwise Model.save() 

1275 # will reassign attname using the related object pk. 

1276 if data is None: 

1277 setattr(instance, self.name, data) 

1278 

1279 def _check_unique(self, **kwargs): 

1280 # Override ForeignKey since check isn't applicable here. 

1281 return [] 

1282 

1283 

1284def create_many_to_many_intermediary_model(field, klass): 

1285 from django.db import models 

1286 

1287 def set_managed(model, related, through): 

1288 through._meta.managed = model._meta.managed or related._meta.managed 

1289 

1290 to_model = resolve_relation(klass, field.remote_field.model) 

1291 name = "%s_%s" % (klass._meta.object_name, field.name) 

1292 lazy_related_operation(set_managed, klass, to_model, name) 

1293 

1294 to = make_model_tuple(to_model)[1] 

1295 from_ = klass._meta.model_name 

1296 if to == from_: 

1297 to = "to_%s" % to 

1298 from_ = "from_%s" % from_ 

1299 

1300 meta = type( 

1301 "Meta", 

1302 (), 

1303 { 

1304 "db_table": field._get_m2m_db_table(klass._meta), 

1305 "auto_created": klass, 

1306 "app_label": klass._meta.app_label, 

1307 "db_tablespace": klass._meta.db_tablespace, 

1308 "unique_together": (from_, to), 

1309 "verbose_name": _("%(from)s-%(to)s relationship") 

1310 % {"from": from_, "to": to}, 

1311 "verbose_name_plural": _("%(from)s-%(to)s relationships") 

1312 % {"from": from_, "to": to}, 

1313 "apps": field.model._meta.apps, 

1314 }, 

1315 ) 

1316 # Construct and return the new class. 

1317 return type( 

1318 name, 

1319 (models.Model,), 

1320 { 

1321 "Meta": meta, 

1322 "__module__": klass.__module__, 

1323 from_: models.ForeignKey( 

1324 klass, 

1325 related_name="%s+" % name, 

1326 db_tablespace=field.db_tablespace, 

1327 db_constraint=field.remote_field.db_constraint, 

1328 on_delete=CASCADE, 

1329 ), 

1330 to: models.ForeignKey( 

1331 to_model, 

1332 related_name="%s+" % name, 

1333 db_tablespace=field.db_tablespace, 

1334 db_constraint=field.remote_field.db_constraint, 

1335 on_delete=CASCADE, 

1336 ), 

1337 }, 

1338 ) 

1339 

1340 

1341class ManyToManyField(RelatedField): 

1342 """ 

1343 Provide a many-to-many relation by using an intermediary model that 

1344 holds two ForeignKey fields pointed at the two sides of the relation. 

1345 

1346 Unless a ``through`` model was provided, ManyToManyField will use the 

1347 create_many_to_many_intermediary_model factory to automatically generate 

1348 the intermediary model. 

1349 """ 

1350 

1351 # Field flags 

1352 many_to_many = True 

1353 many_to_one = False 

1354 one_to_many = False 

1355 one_to_one = False 

1356 

1357 rel_class = ManyToManyRel 

1358 

1359 description = _("Many-to-many relationship") 

1360 

1361 def __init__( 

1362 self, 

1363 to, 

1364 related_name=None, 

1365 related_query_name=None, 

1366 limit_choices_to=None, 

1367 symmetrical=None, 

1368 through=None, 

1369 through_fields=None, 

1370 db_constraint=True, 

1371 db_table=None, 

1372 swappable=True, 

1373 **kwargs, 

1374 ): 

1375 try: 

1376 to._meta 

1377 except AttributeError: 

1378 if not isinstance(to, str): 

1379 raise TypeError( 

1380 "%s(%r) is invalid. First parameter to ManyToManyField " 

1381 "must be either a model, a model name, or the string %r" 

1382 % ( 

1383 self.__class__.__name__, 

1384 to, 

1385 RECURSIVE_RELATIONSHIP_CONSTANT, 

1386 ) 

1387 ) 

1388 

1389 if symmetrical is None: 

1390 symmetrical = to == RECURSIVE_RELATIONSHIP_CONSTANT 

1391 

1392 if through is not None and db_table is not None: 

1393 raise ValueError( 

1394 "Cannot specify a db_table if an intermediary model is used." 

1395 ) 

1396 

1397 kwargs["rel"] = self.rel_class( 

1398 self, 

1399 to, 

1400 related_name=related_name, 

1401 related_query_name=related_query_name, 

1402 limit_choices_to=limit_choices_to, 

1403 symmetrical=symmetrical, 

1404 through=through, 

1405 through_fields=through_fields, 

1406 db_constraint=db_constraint, 

1407 ) 

1408 self.has_null_arg = "null" in kwargs 

1409 

1410 super().__init__( 

1411 related_name=related_name, 

1412 related_query_name=related_query_name, 

1413 limit_choices_to=limit_choices_to, 

1414 **kwargs, 

1415 ) 

1416 

1417 self.db_table = db_table 

1418 self.swappable = swappable 

1419 

1420 def check(self, **kwargs): 

1421 return [ 

1422 *super().check(**kwargs), 

1423 *self._check_unique(**kwargs), 

1424 *self._check_relationship_model(**kwargs), 

1425 *self._check_ignored_options(**kwargs), 

1426 *self._check_table_uniqueness(**kwargs), 

1427 ] 

1428 

1429 def _check_unique(self, **kwargs): 

1430 if self.unique: 

1431 return [ 

1432 checks.Error( 

1433 "ManyToManyFields cannot be unique.", 

1434 obj=self, 

1435 id="fields.E330", 

1436 ) 

1437 ] 

1438 return [] 

1439 

1440 def _check_ignored_options(self, **kwargs): 

1441 warnings = [] 

1442 

1443 if self.has_null_arg: 

1444 warnings.append( 

1445 checks.Warning( 

1446 "null has no effect on ManyToManyField.", 

1447 obj=self, 

1448 id="fields.W340", 

1449 ) 

1450 ) 

1451 

1452 if self._validators: 

1453 warnings.append( 

1454 checks.Warning( 

1455 "ManyToManyField does not support validators.", 

1456 obj=self, 

1457 id="fields.W341", 

1458 ) 

1459 ) 

1460 if self.remote_field.symmetrical and self._related_name: 

1461 warnings.append( 

1462 checks.Warning( 

1463 "related_name has no effect on ManyToManyField " 

1464 'with a symmetrical relationship, e.g. to "self".', 

1465 obj=self, 

1466 id="fields.W345", 

1467 ) 

1468 ) 

1469 if self.db_comment: 

1470 warnings.append( 

1471 checks.Warning( 

1472 "db_comment has no effect on ManyToManyField.", 

1473 obj=self, 

1474 id="fields.W346", 

1475 ) 

1476 ) 

1477 

1478 return warnings 

1479 

1480 def _check_relationship_model(self, from_model=None, **kwargs): 

1481 from django.db.models.fields.composite import CompositePrimaryKey 

1482 

1483 if hasattr(self.remote_field.through, "_meta"): 

1484 qualified_model_name = "%s.%s" % ( 

1485 self.remote_field.through._meta.app_label, 

1486 self.remote_field.through.__name__, 

1487 ) 

1488 else: 

1489 qualified_model_name = self.remote_field.through 

1490 

1491 errors = [] 

1492 

1493 if self.remote_field.through not in self.opts.apps.get_models( 

1494 include_auto_created=True 

1495 ): 

1496 # The relationship model is not installed. 

1497 errors.append( 

1498 checks.Error( 

1499 "Field specifies a many-to-many relation through model " 

1500 "'%s', which has not been installed." % qualified_model_name, 

1501 obj=self, 

1502 id="fields.E331", 

1503 ) 

1504 ) 

1505 

1506 else: 

1507 assert from_model is not None, ( 

1508 "ManyToManyField with intermediate " 

1509 "tables cannot be checked if you don't pass the model " 

1510 "where the field is attached to." 

1511 ) 

1512 # Set some useful local variables 

1513 to_model = resolve_relation(from_model, self.remote_field.model) 

1514 from_model_name = from_model._meta.object_name 

1515 if isinstance(to_model, str): 

1516 to_model_name = to_model 

1517 else: 

1518 to_model_name = to_model._meta.object_name 

1519 if ( 

1520 self.remote_field.through_fields is None 

1521 and not isinstance(to_model, str) 

1522 and isinstance(to_model._meta.pk, CompositePrimaryKey) 

1523 ): 

1524 errors.append( 

1525 checks.Error( 

1526 "Field defines a relation to the CompositePrimaryKey of model " 

1527 f"{self.remote_field.model._meta.object_name!r} which is not " 

1528 "supported.", 

1529 obj=self, 

1530 id="fields.E347", 

1531 ) 

1532 ) 

1533 relationship_model_name = self.remote_field.through._meta.object_name 

1534 self_referential = from_model == to_model 

1535 # Count foreign keys in intermediate model 

1536 if self_referential: 

1537 seen_self = sum( 

1538 from_model == getattr(field.remote_field, "model", None) 

1539 for field in self.remote_field.through._meta.fields 

1540 ) 

1541 

1542 if seen_self > 2 and not self.remote_field.through_fields: 

1543 errors.append( 

1544 checks.Error( 

1545 "The model is used as an intermediate model by " 

1546 "'%s', but it has more than two foreign keys " 

1547 "to '%s', which is ambiguous. You must specify " 

1548 "which two foreign keys Django should use via the " 

1549 "through_fields keyword argument." 

1550 % (self, from_model_name), 

1551 hint=( 

1552 "Use through_fields to specify which two foreign keys " 

1553 "Django should use." 

1554 ), 

1555 obj=self.remote_field.through, 

1556 id="fields.E333", 

1557 ) 

1558 ) 

1559 

1560 else: 

1561 # Count foreign keys in relationship model 

1562 seen_from = sum( 

1563 from_model == getattr(field.remote_field, "model", None) 

1564 for field in self.remote_field.through._meta.fields 

1565 ) 

1566 seen_to = sum( 

1567 to_model == getattr(field.remote_field, "model", None) 

1568 for field in self.remote_field.through._meta.fields 

1569 ) 

1570 

1571 if seen_from > 1 and not self.remote_field.through_fields: 

1572 errors.append( 

1573 checks.Error( 

1574 ( 

1575 "The model is used as an intermediate model by " 

1576 "'%s', but it has more than one foreign key " 

1577 "from '%s', which is ambiguous. You must specify " 

1578 "which foreign key Django should use via the " 

1579 "through_fields keyword argument." 

1580 ) 

1581 % (self, from_model_name), 

1582 hint=( 

1583 "If you want to create a recursive relationship, " 

1584 'use ManyToManyField("%s", through="%s").' 

1585 ) 

1586 % ( 

1587 RECURSIVE_RELATIONSHIP_CONSTANT, 

1588 relationship_model_name, 

1589 ), 

1590 obj=self, 

1591 id="fields.E334", 

1592 ) 

1593 ) 

1594 

1595 if seen_to > 1 and not self.remote_field.through_fields: 

1596 errors.append( 

1597 checks.Error( 

1598 "The model is used as an intermediate model by " 

1599 "'%s', but it has more than one foreign key " 

1600 "to '%s', which is ambiguous. You must specify " 

1601 "which foreign key Django should use via the " 

1602 "through_fields keyword argument." % (self, to_model_name), 

1603 hint=( 

1604 "If you want to create a recursive relationship, " 

1605 'use ManyToManyField("%s", through="%s").' 

1606 ) 

1607 % ( 

1608 RECURSIVE_RELATIONSHIP_CONSTANT, 

1609 relationship_model_name, 

1610 ), 

1611 obj=self, 

1612 id="fields.E335", 

1613 ) 

1614 ) 

1615 

1616 if seen_from == 0 or seen_to == 0: 

1617 errors.append( 

1618 checks.Error( 

1619 "The model is used as an intermediate model by " 

1620 "'%s', but it does not have a foreign key to '%s' or '%s'." 

1621 % (self, from_model_name, to_model_name), 

1622 obj=self.remote_field.through, 

1623 id="fields.E336", 

1624 ) 

1625 ) 

1626 

1627 # Validate `through_fields`. 

1628 if self.remote_field.through_fields is not None: 

1629 # Validate that we're given an iterable of at least two items 

1630 # and that none of them is "falsy". 

1631 if not ( 

1632 len(self.remote_field.through_fields) >= 2 

1633 and self.remote_field.through_fields[0] 

1634 and self.remote_field.through_fields[1] 

1635 ): 

1636 errors.append( 

1637 checks.Error( 

1638 "Field specifies 'through_fields' but does not provide " 

1639 "the names of the two link fields that should be used " 

1640 "for the relation through model '%s'." % qualified_model_name, 

1641 hint=( 

1642 "Make sure you specify 'through_fields' as " 

1643 "through_fields=('field1', 'field2')" 

1644 ), 

1645 obj=self, 

1646 id="fields.E337", 

1647 ) 

1648 ) 

1649 

1650 # Validate the given through fields -- they should be actual 

1651 # fields on the through model, and also be foreign keys to the 

1652 # expected models. 

1653 else: 

1654 assert from_model is not None, ( 

1655 "ManyToManyField with intermediate " 

1656 "tables cannot be checked if you don't pass the model " 

1657 "where the field is attached to." 

1658 ) 

1659 

1660 source, through, target = ( 

1661 from_model, 

1662 self.remote_field.through, 

1663 self.remote_field.model, 

1664 ) 

1665 source_field_name, target_field_name = self.remote_field.through_fields[ 

1666 :2 

1667 ] 

1668 

1669 for field_name, related_model in ( 

1670 (source_field_name, source), 

1671 (target_field_name, target), 

1672 ): 

1673 possible_field_names = [] 

1674 for f in through._meta.fields: 

1675 if ( 

1676 hasattr(f, "remote_field") 

1677 and getattr(f.remote_field, "model", None) == related_model 

1678 ): 

1679 possible_field_names.append(f.name) 

1680 if possible_field_names: 

1681 hint = ( 

1682 "Did you mean one of the following foreign keys to '%s': " 

1683 "%s?" 

1684 % ( 

1685 related_model._meta.object_name, 

1686 ", ".join(possible_field_names), 

1687 ) 

1688 ) 

1689 else: 

1690 hint = None 

1691 

1692 try: 

1693 field = through._meta.get_field(field_name) 

1694 except exceptions.FieldDoesNotExist: 

1695 errors.append( 

1696 checks.Error( 

1697 "The intermediary model '%s' has no field '%s'." 

1698 % (qualified_model_name, field_name), 

1699 hint=hint, 

1700 obj=self, 

1701 id="fields.E338", 

1702 ) 

1703 ) 

1704 else: 

1705 if not ( 

1706 hasattr(field, "remote_field") 

1707 and getattr(field.remote_field, "model", None) 

1708 == related_model 

1709 ): 

1710 errors.append( 

1711 checks.Error( 

1712 "'%s.%s' is not a foreign key to '%s'." 

1713 % ( 

1714 through._meta.object_name, 

1715 field_name, 

1716 related_model._meta.object_name, 

1717 ), 

1718 hint=hint, 

1719 obj=self, 

1720 id="fields.E339", 

1721 ) 

1722 ) 

1723 

1724 return errors 

1725 

1726 def _check_table_uniqueness(self, **kwargs): 

1727 if ( 

1728 isinstance(self.remote_field.through, str) 

1729 or not self.remote_field.through._meta.managed 

1730 ): 

1731 return [] 

1732 registered_tables = { 

1733 model._meta.db_table: model 

1734 for model in self.opts.apps.get_models(include_auto_created=True) 

1735 if model != self.remote_field.through and model._meta.managed 

1736 } 

1737 m2m_db_table = self.m2m_db_table() 

1738 model = registered_tables.get(m2m_db_table) 

1739 # The second condition allows multiple m2m relations on a model if 

1740 # some point to a through model that proxies another through model. 

1741 if ( 

1742 model 

1743 and model._meta.concrete_model 

1744 != self.remote_field.through._meta.concrete_model 

1745 ): 

1746 if model._meta.auto_created: 

1747 

1748 def _get_field_name(model): 

1749 for field in model._meta.auto_created._meta.many_to_many: 

1750 if field.remote_field.through is model: 

1751 return field.name 

1752 

1753 opts = model._meta.auto_created._meta 

1754 clashing_obj = "%s.%s" % (opts.label, _get_field_name(model)) 

1755 else: 

1756 clashing_obj = model._meta.label 

1757 if settings.DATABASE_ROUTERS: 

1758 error_class, error_id = checks.Warning, "fields.W344" 

1759 error_hint = ( 

1760 "You have configured settings.DATABASE_ROUTERS. Verify " 

1761 "that the table of %r is correctly routed to a separate " 

1762 "database." % clashing_obj 

1763 ) 

1764 else: 

1765 error_class, error_id = checks.Error, "fields.E340" 

1766 error_hint = None 

1767 return [ 

1768 error_class( 

1769 "The field's intermediary table '%s' clashes with the " 

1770 "table name of '%s'." % (m2m_db_table, clashing_obj), 

1771 obj=self, 

1772 hint=error_hint, 

1773 id=error_id, 

1774 ) 

1775 ] 

1776 return [] 

1777 

1778 def deconstruct(self): 

1779 name, path, args, kwargs = super().deconstruct() 

1780 # Handle the simpler arguments. 

1781 if self.db_table is not None: 

1782 kwargs["db_table"] = self.db_table 

1783 if self.remote_field.db_constraint is not True: 

1784 kwargs["db_constraint"] = self.remote_field.db_constraint 

1785 # Lowercase model names as they should be treated as case-insensitive. 

1786 if isinstance(self.remote_field.model, str): 

1787 if "." in self.remote_field.model: 

1788 app_label, model_name = self.remote_field.model.split(".") 

1789 kwargs["to"] = "%s.%s" % (app_label, model_name.lower()) 

1790 else: 

1791 kwargs["to"] = self.remote_field.model.lower() 

1792 else: 

1793 kwargs["to"] = self.remote_field.model._meta.label_lower 

1794 if getattr(self.remote_field, "through", None) is not None: 

1795 if isinstance(self.remote_field.through, str): 

1796 kwargs["through"] = self.remote_field.through 

1797 elif not self.remote_field.through._meta.auto_created: 

1798 kwargs["through"] = self.remote_field.through._meta.label 

1799 # If swappable is True, then see if we're actually pointing to the target 

1800 # of a swap. 

1801 swappable_setting = self.swappable_setting 

1802 if swappable_setting is not None: 

1803 # If it's already a settings reference, error. 

1804 if hasattr(kwargs["to"], "setting_name"): 

1805 if kwargs["to"].setting_name != swappable_setting: 

1806 raise ValueError( 

1807 "Cannot deconstruct a ManyToManyField pointing to a " 

1808 "model that is swapped in place of more than one model " 

1809 "(%s and %s)" % (kwargs["to"].setting_name, swappable_setting) 

1810 ) 

1811 

1812 kwargs["to"] = SettingsReference( 

1813 kwargs["to"], 

1814 swappable_setting, 

1815 ) 

1816 return name, path, args, kwargs 

1817 

1818 def _get_path_info(self, direct=False, filtered_relation=None): 

1819 """Called by both direct and indirect m2m traversal.""" 

1820 int_model = self.remote_field.through 

1821 linkfield1 = int_model._meta.get_field(self.m2m_field_name()) 

1822 linkfield2 = int_model._meta.get_field(self.m2m_reverse_field_name()) 

1823 if direct: 

1824 join1infos = linkfield1.reverse_path_infos 

1825 if filtered_relation: 

1826 join2infos = linkfield2.get_path_info(filtered_relation) 

1827 else: 

1828 join2infos = linkfield2.path_infos 

1829 else: 

1830 join1infos = linkfield2.reverse_path_infos 

1831 if filtered_relation: 

1832 join2infos = linkfield1.get_path_info(filtered_relation) 

1833 else: 

1834 join2infos = linkfield1.path_infos 

1835 # Get join infos between the last model of join 1 and the first model 

1836 # of join 2. Assume the only reason these may differ is due to model 

1837 # inheritance. 

1838 join1_final = join1infos[-1].to_opts 

1839 join2_initial = join2infos[0].from_opts 

1840 if join1_final is join2_initial: 

1841 intermediate_infos = [] 

1842 elif issubclass(join1_final.model, join2_initial.model): 

1843 intermediate_infos = join1_final.get_path_to_parent(join2_initial.model) 

1844 else: 

1845 intermediate_infos = join2_initial.get_path_from_parent(join1_final.model) 

1846 

1847 return [*join1infos, *intermediate_infos, *join2infos] 

1848 

1849 def get_path_info(self, filtered_relation=None): 

1850 return self._get_path_info(direct=True, filtered_relation=filtered_relation) 

1851 

1852 @cached_property 

1853 def path_infos(self): 

1854 return self.get_path_info() 

1855 

1856 def get_reverse_path_info(self, filtered_relation=None): 

1857 return self._get_path_info(direct=False, filtered_relation=filtered_relation) 

1858 

1859 @cached_property 

1860 def reverse_path_infos(self): 

1861 return self.get_reverse_path_info() 

1862 

1863 def _get_m2m_db_table(self, opts): 

1864 """ 

1865 Function that can be curried to provide the m2m table name for this 

1866 relation. 

1867 """ 

1868 if self.remote_field.through is not None: 

1869 return self.remote_field.through._meta.db_table 

1870 elif self.db_table: 

1871 return self.db_table 

1872 else: 

1873 m2m_table_name = "%s_%s" % (utils.strip_quotes(opts.db_table), self.name) 

1874 return utils.truncate_name(m2m_table_name, connection.ops.max_name_length()) 

1875 

1876 def _get_m2m_attr(self, related, attr): 

1877 """ 

1878 Function that can be curried to provide the source accessor or DB 

1879 column name for the m2m table. 

1880 """ 

1881 cache_attr = "_m2m_%s_cache" % attr 

1882 if hasattr(self, cache_attr): 

1883 return getattr(self, cache_attr) 

1884 if self.remote_field.through_fields is not None: 

1885 link_field_name = self.remote_field.through_fields[0] 

1886 else: 

1887 link_field_name = None 

1888 for f in self.remote_field.through._meta.fields: 

1889 if ( 

1890 f.is_relation 

1891 and f.remote_field.model == related.related_model 

1892 and (link_field_name is None or link_field_name == f.name) 

1893 ): 

1894 setattr(self, cache_attr, getattr(f, attr)) 

1895 return getattr(self, cache_attr) 

1896 

1897 def _get_m2m_reverse_attr(self, related, attr): 

1898 """ 

1899 Function that can be curried to provide the related accessor or DB 

1900 column name for the m2m table. 

1901 """ 

1902 cache_attr = "_m2m_reverse_%s_cache" % attr 

1903 if hasattr(self, cache_attr): 

1904 return getattr(self, cache_attr) 

1905 found = False 

1906 if self.remote_field.through_fields is not None: 

1907 link_field_name = self.remote_field.through_fields[1] 

1908 else: 

1909 link_field_name = None 

1910 for f in self.remote_field.through._meta.fields: 

1911 if f.is_relation and f.remote_field.model == related.model: 

1912 if link_field_name is None and related.related_model == related.model: 

1913 # If this is an m2m-intermediate to self, 

1914 # the first foreign key you find will be 

1915 # the source column. Keep searching for 

1916 # the second foreign key. 

1917 if found: 

1918 setattr(self, cache_attr, getattr(f, attr)) 

1919 break 

1920 else: 

1921 found = True 

1922 elif link_field_name is None or link_field_name == f.name: 

1923 setattr(self, cache_attr, getattr(f, attr)) 

1924 break 

1925 return getattr(self, cache_attr) 

1926 

1927 def contribute_to_class(self, cls, name, **kwargs): 

1928 # To support multiple relations to self, it's useful to have a non-None 

1929 # related name on symmetrical relations for internal reasons. The 

1930 # concept doesn't make a lot of sense externally ("you want me to 

1931 # specify *what* on my non-reversible relation?!"), so we set it up 

1932 # automatically. The funky name reduces the chance of an accidental 

1933 # clash. 

1934 if self.remote_field.symmetrical and ( 

1935 self.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT 

1936 or self.remote_field.model == cls._meta.object_name 

1937 ): 

1938 self.remote_field.related_name = "%s_rel_+" % name 

1939 elif self.remote_field.hidden: 

1940 # If the backwards relation is disabled, replace the original 

1941 # related_name with one generated from the m2m field name. Django 

1942 # still uses backwards relations internally and we need to avoid 

1943 # clashes between multiple m2m fields with related_name == '+'. 

1944 self.remote_field.related_name = "_%s_%s_%s_+" % ( 

1945 cls._meta.app_label, 

1946 cls.__name__.lower(), 

1947 name, 

1948 ) 

1949 

1950 super().contribute_to_class(cls, name, **kwargs) 

1951 

1952 # The intermediate m2m model is not auto created if: 

1953 # 1) There is a manually specified intermediate, or 

1954 # 2) The class owning the m2m field is abstract. 

1955 # 3) The class owning the m2m field has been swapped out. 

1956 if not cls._meta.abstract: 

1957 if self.remote_field.through: 

1958 

1959 def resolve_through_model(_, model, field): 

1960 field.remote_field.through = model 

1961 

1962 lazy_related_operation( 

1963 resolve_through_model, cls, self.remote_field.through, field=self 

1964 ) 

1965 elif not cls._meta.swapped: 

1966 self.remote_field.through = create_many_to_many_intermediary_model( 

1967 self, cls 

1968 ) 

1969 

1970 # Add the descriptor for the m2m relation. 

1971 setattr(cls, self.name, ManyToManyDescriptor(self.remote_field, reverse=False)) 

1972 

1973 # Set up the accessor for the m2m table name for the relation. 

1974 self.m2m_db_table = partial(self._get_m2m_db_table, cls._meta) 

1975 

1976 def contribute_to_related_class(self, cls, related): 

1977 # Internal M2Ms (i.e., those with a related name ending with '+') 

1978 # and swapped models don't get a related descriptor. 

1979 if not self.remote_field.hidden and not related.related_model._meta.swapped: 

1980 setattr( 

1981 cls, 

1982 related.accessor_name, 

1983 ManyToManyDescriptor(self.remote_field, reverse=True), 

1984 ) 

1985 

1986 # Set up the accessors for the column names on the m2m table. 

1987 self.m2m_column_name = partial(self._get_m2m_attr, related, "column") 

1988 self.m2m_reverse_name = partial(self._get_m2m_reverse_attr, related, "column") 

1989 

1990 self.m2m_field_name = partial(self._get_m2m_attr, related, "name") 

1991 self.m2m_reverse_field_name = partial( 

1992 self._get_m2m_reverse_attr, related, "name" 

1993 ) 

1994 

1995 get_m2m_rel = partial(self._get_m2m_attr, related, "remote_field") 

1996 self.m2m_target_field_name = lambda: get_m2m_rel().field_name 

1997 get_m2m_reverse_rel = partial( 

1998 self._get_m2m_reverse_attr, related, "remote_field" 

1999 ) 

2000 self.m2m_reverse_target_field_name = lambda: get_m2m_reverse_rel().field_name 

2001 

2002 def set_attributes_from_rel(self): 

2003 pass 

2004 

2005 def value_from_object(self, obj): 

2006 return list(getattr(obj, self.attname).all()) if obj._is_pk_set() else [] 

2007 

2008 def save_form_data(self, instance, data): 

2009 getattr(instance, self.attname).set(data) 

2010 

2011 def formfield(self, *, using=None, **kwargs): 

2012 defaults = { 

2013 "form_class": forms.ModelMultipleChoiceField, 

2014 "queryset": self.remote_field.model._default_manager.using(using), 

2015 **kwargs, 

2016 } 

2017 # If initial is passed in, it's a list of related objects, but the 

2018 # MultipleChoiceField takes a list of IDs. 

2019 if defaults.get("initial") is not None: 

2020 initial = defaults["initial"] 

2021 if callable(initial): 

2022 initial = initial() 

2023 defaults["initial"] = [i.pk for i in initial] 

2024 return super().formfield(**defaults) 

2025 

2026 def db_check(self, connection): 

2027 return None 

2028 

2029 def db_type(self, connection): 

2030 # A ManyToManyField is not represented by a single column, 

2031 # so return None. 

2032 return None 

2033 

2034 def db_parameters(self, connection): 

2035 return {"type": None, "check": None}