Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py: 9%

611 statements  

« prev     ^ index     » next       coverage.py v7.0.5, created at 2023-01-17 06:13 +0000

1""" 

2Accessors for related objects. 

3 

4When a field defines a relation between two models, each model class provides 

5an attribute to access related instances of the other model class (unless the 

6reverse accessor has been disabled with related_name='+'). 

7 

8Accessors are implemented as descriptors in order to customize access and 

9assignment. This module defines the descriptor classes. 

10 

11Forward accessors follow foreign keys. Reverse accessors trace them back. For 

12example, with the following models:: 

13 

14 class Parent(Model): 

15 pass 

16 

17 class Child(Model): 

18 parent = ForeignKey(Parent, related_name='children') 

19 

20 ``child.parent`` is a forward many-to-one relation. ``parent.children`` is a 

21reverse many-to-one relation. 

22 

23There are three types of relations (many-to-one, one-to-one, and many-to-many) 

24and two directions (forward and reverse) for a total of six combinations. 

25 

261. Related instance on the forward side of a many-to-one relation: 

27 ``ForwardManyToOneDescriptor``. 

28 

29 Uniqueness of foreign key values is irrelevant to accessing the related 

30 instance, making the many-to-one and one-to-one cases identical as far as 

31 the descriptor is concerned. The constraint is checked upstream (unicity 

32 validation in forms) or downstream (unique indexes in the database). 

33 

342. Related instance on the forward side of a one-to-one 

35 relation: ``ForwardOneToOneDescriptor``. 

36 

37 It avoids querying the database when accessing the parent link field in 

38 a multi-table inheritance scenario. 

39 

403. Related instance on the reverse side of a one-to-one relation: 

41 ``ReverseOneToOneDescriptor``. 

42 

43 One-to-one relations are asymmetrical, despite the apparent symmetry of the 

44 name, because they're implemented in the database with a foreign key from 

45 one table to another. As a consequence ``ReverseOneToOneDescriptor`` is 

46 slightly different from ``ForwardManyToOneDescriptor``. 

47 

484. Related objects manager for related instances on the reverse side of a 

49 many-to-one relation: ``ReverseManyToOneDescriptor``. 

50 

51 Unlike the previous two classes, this one provides access to a collection 

52 of objects. It returns a manager rather than an instance. 

53 

545. Related objects manager for related instances on the forward or reverse 

55 sides of a many-to-many relation: ``ManyToManyDescriptor``. 

56 

57 Many-to-many relations are symmetrical. The syntax of Django models 

58 requires declaring them on one side but that's an implementation detail. 

59 They could be declared on the other side without any change in behavior. 

60 Therefore the forward and reverse descriptors can be the same. 

61 

62 If you're looking for ``ForwardManyToManyDescriptor`` or 

63 ``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead. 

64""" 

65 

66from asgiref.sync import sync_to_async 

67 

68from django.core.exceptions import FieldError 

69from django.db import ( 

70 DEFAULT_DB_ALIAS, 

71 NotSupportedError, 

72 connections, 

73 router, 

74 transaction, 

75) 

76from django.db.models import Q, Window, signals 

77from django.db.models.functions import RowNumber 

78from django.db.models.lookups import GreaterThan, LessThanOrEqual 

79from django.db.models.query import QuerySet 

80from django.db.models.query_utils import DeferredAttribute 

81from django.db.models.utils import AltersData, resolve_callables 

82from django.utils.functional import cached_property 

83 

84 

85class ForeignKeyDeferredAttribute(DeferredAttribute): 

86 def __set__(self, instance, value): 

87 if instance.__dict__.get(self.field.attname) != value and self.field.is_cached( 

88 instance 

89 ): 

90 self.field.delete_cached_value(instance) 

91 instance.__dict__[self.field.attname] = value 

92 

93 

94def _filter_prefetch_queryset(queryset, field_name, instances): 

95 predicate = Q(**{f"{field_name}__in": instances}) 

96 db = queryset._db or DEFAULT_DB_ALIAS 

97 if queryset.query.is_sliced: 

98 if not connections[db].features.supports_over_clause: 

99 raise NotSupportedError( 

100 "Prefetching from a limited queryset is only supported on backends " 

101 "that support window functions." 

102 ) 

103 low_mark, high_mark = queryset.query.low_mark, queryset.query.high_mark 

104 order_by = [ 

105 expr for expr, _ in queryset.query.get_compiler(using=db).get_order_by() 

106 ] 

107 window = Window(RowNumber(), partition_by=field_name, order_by=order_by) 

108 predicate &= GreaterThan(window, low_mark) 

109 if high_mark is not None: 

110 predicate &= LessThanOrEqual(window, high_mark) 

111 queryset.query.clear_limits() 

112 return queryset.filter(predicate) 

113 

114 

115class ForwardManyToOneDescriptor: 

116 """ 

117 Accessor to the related object on the forward side of a many-to-one or 

118 one-to-one (via ForwardOneToOneDescriptor subclass) relation. 

119 

120 In the example:: 

121 

122 class Child(Model): 

123 parent = ForeignKey(Parent, related_name='children') 

124 

125 ``Child.parent`` is a ``ForwardManyToOneDescriptor`` instance. 

126 """ 

127 

128 def __init__(self, field_with_rel): 

129 self.field = field_with_rel 

130 

131 @cached_property 

132 def RelatedObjectDoesNotExist(self): 

133 # The exception can't be created at initialization time since the 

134 # related model might not be resolved yet; `self.field.model` might 

135 # still be a string model reference. 

136 return type( 

137 "RelatedObjectDoesNotExist", 

138 (self.field.remote_field.model.DoesNotExist, AttributeError), 

139 { 

140 "__module__": self.field.model.__module__, 

141 "__qualname__": "%s.%s.RelatedObjectDoesNotExist" 

142 % ( 

143 self.field.model.__qualname__, 

144 self.field.name, 

145 ), 

146 }, 

147 ) 

148 

149 def is_cached(self, instance): 

150 return self.field.is_cached(instance) 

151 

152 def get_queryset(self, **hints): 

153 return self.field.remote_field.model._base_manager.db_manager(hints=hints).all() 

154 

155 def get_prefetch_queryset(self, instances, queryset=None): 

156 if queryset is None: 

157 queryset = self.get_queryset() 

158 queryset._add_hints(instance=instances[0]) 

159 

160 rel_obj_attr = self.field.get_foreign_related_value 

161 instance_attr = self.field.get_local_related_value 

162 instances_dict = {instance_attr(inst): inst for inst in instances} 

163 related_field = self.field.foreign_related_fields[0] 

164 remote_field = self.field.remote_field 

165 

166 # FIXME: This will need to be revisited when we introduce support for 

167 # composite fields. In the meantime we take this practical approach to 

168 # solve a regression on 1.6 when the reverse manager in hidden 

169 # (related_name ends with a '+'). Refs #21410. 

170 # The check for len(...) == 1 is a special case that allows the query 

171 # to be join-less and smaller. Refs #21760. 

172 if remote_field.is_hidden() or len(self.field.foreign_related_fields) == 1: 

173 query = { 

174 "%s__in" 

175 % related_field.name: {instance_attr(inst)[0] for inst in instances} 

176 } 

177 else: 

178 query = {"%s__in" % self.field.related_query_name(): instances} 

179 queryset = queryset.filter(**query) 

180 

181 # Since we're going to assign directly in the cache, 

182 # we must manage the reverse relation cache manually. 

183 if not remote_field.multiple: 

184 for rel_obj in queryset: 

185 instance = instances_dict[rel_obj_attr(rel_obj)] 

186 remote_field.set_cached_value(rel_obj, instance) 

187 return ( 

188 queryset, 

189 rel_obj_attr, 

190 instance_attr, 

191 True, 

192 self.field.get_cache_name(), 

193 False, 

194 ) 

195 

196 def get_object(self, instance): 

197 qs = self.get_queryset(instance=instance) 

198 # Assuming the database enforces foreign keys, this won't fail. 

199 return qs.get(self.field.get_reverse_related_filter(instance)) 

200 

201 def __get__(self, instance, cls=None): 

202 """ 

203 Get the related instance through the forward relation. 

204 

205 With the example above, when getting ``child.parent``: 

206 

207 - ``self`` is the descriptor managing the ``parent`` attribute 

208 - ``instance`` is the ``child`` instance 

209 - ``cls`` is the ``Child`` class (we don't need it) 

210 """ 

211 if instance is None: 

212 return self 

213 

214 # The related instance is loaded from the database and then cached 

215 # by the field on the model instance state. It can also be pre-cached 

216 # by the reverse accessor (ReverseOneToOneDescriptor). 

217 try: 

218 rel_obj = self.field.get_cached_value(instance) 

219 except KeyError: 

220 has_value = None not in self.field.get_local_related_value(instance) 

221 ancestor_link = ( 

222 instance._meta.get_ancestor_link(self.field.model) 

223 if has_value 

224 else None 

225 ) 

226 if ancestor_link and ancestor_link.is_cached(instance): 

227 # An ancestor link will exist if this field is defined on a 

228 # multi-table inheritance parent of the instance's class. 

229 ancestor = ancestor_link.get_cached_value(instance) 

230 # The value might be cached on an ancestor if the instance 

231 # originated from walking down the inheritance chain. 

232 rel_obj = self.field.get_cached_value(ancestor, default=None) 

233 else: 

234 rel_obj = None 

235 if rel_obj is None and has_value: 

236 rel_obj = self.get_object(instance) 

237 remote_field = self.field.remote_field 

238 # If this is a one-to-one relation, set the reverse accessor 

239 # cache on the related object to the current instance to avoid 

240 # an extra SQL query if it's accessed later on. 

241 if not remote_field.multiple: 

242 remote_field.set_cached_value(rel_obj, instance) 

243 self.field.set_cached_value(instance, rel_obj) 

244 

245 if rel_obj is None and not self.field.null: 

246 raise self.RelatedObjectDoesNotExist( 

247 "%s has no %s." % (self.field.model.__name__, self.field.name) 

248 ) 

249 else: 

250 return rel_obj 

251 

252 def __set__(self, instance, value): 

253 """ 

254 Set the related instance through the forward relation. 

255 

256 With the example above, when setting ``child.parent = parent``: 

257 

258 - ``self`` is the descriptor managing the ``parent`` attribute 

259 - ``instance`` is the ``child`` instance 

260 - ``value`` is the ``parent`` instance on the right of the equal sign 

261 """ 

262 # An object must be an instance of the related class. 

263 if value is not None and not isinstance( 

264 value, self.field.remote_field.model._meta.concrete_model 

265 ): 

266 raise ValueError( 

267 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' 

268 % ( 

269 value, 

270 instance._meta.object_name, 

271 self.field.name, 

272 self.field.remote_field.model._meta.object_name, 

273 ) 

274 ) 

275 elif value is not None: 

276 if instance._state.db is None: 

277 instance._state.db = router.db_for_write( 

278 instance.__class__, instance=value 

279 ) 

280 if value._state.db is None: 

281 value._state.db = router.db_for_write( 

282 value.__class__, instance=instance 

283 ) 

284 if not router.allow_relation(value, instance): 

285 raise ValueError( 

286 'Cannot assign "%r": the current database router prevents this ' 

287 "relation." % value 

288 ) 

289 

290 remote_field = self.field.remote_field 

291 # If we're setting the value of a OneToOneField to None, we need to clear 

292 # out the cache on any old related object. Otherwise, deleting the 

293 # previously-related object will also cause this object to be deleted, 

294 # which is wrong. 

295 if value is None: 

296 # Look up the previously-related object, which may still be available 

297 # since we've not yet cleared out the related field. 

298 # Use the cache directly, instead of the accessor; if we haven't 

299 # populated the cache, then we don't care - we're only accessing 

300 # the object to invalidate the accessor cache, so there's no 

301 # need to populate the cache just to expire it again. 

302 related = self.field.get_cached_value(instance, default=None) 

303 

304 # If we've got an old related object, we need to clear out its 

305 # cache. This cache also might not exist if the related object 

306 # hasn't been accessed yet. 

307 if related is not None: 

308 remote_field.set_cached_value(related, None) 

309 

310 for lh_field, rh_field in self.field.related_fields: 

311 setattr(instance, lh_field.attname, None) 

312 

313 # Set the values of the related field. 

314 else: 

315 for lh_field, rh_field in self.field.related_fields: 

316 setattr(instance, lh_field.attname, getattr(value, rh_field.attname)) 

317 

318 # Set the related instance cache used by __get__ to avoid an SQL query 

319 # when accessing the attribute we just set. 

320 self.field.set_cached_value(instance, value) 

321 

322 # If this is a one-to-one relation, set the reverse accessor cache on 

323 # the related object to the current instance to avoid an extra SQL 

324 # query if it's accessed later on. 

325 if value is not None and not remote_field.multiple: 

326 remote_field.set_cached_value(value, instance) 

327 

328 def __reduce__(self): 

329 """ 

330 Pickling should return the instance attached by self.field on the 

331 model, not a new copy of that descriptor. Use getattr() to retrieve 

332 the instance directly from the model. 

333 """ 

334 return getattr, (self.field.model, self.field.name) 

335 

336 

337class ForwardOneToOneDescriptor(ForwardManyToOneDescriptor): 

338 """ 

339 Accessor to the related object on the forward side of a one-to-one relation. 

340 

341 In the example:: 

342 

343 class Restaurant(Model): 

344 place = OneToOneField(Place, related_name='restaurant') 

345 

346 ``Restaurant.place`` is a ``ForwardOneToOneDescriptor`` instance. 

347 """ 

348 

349 def get_object(self, instance): 

350 if self.field.remote_field.parent_link: 

351 deferred = instance.get_deferred_fields() 

352 # Because it's a parent link, all the data is available in the 

353 # instance, so populate the parent model with this data. 

354 rel_model = self.field.remote_field.model 

355 fields = [field.attname for field in rel_model._meta.concrete_fields] 

356 

357 # If any of the related model's fields are deferred, fallback to 

358 # fetching all fields from the related model. This avoids a query 

359 # on the related model for every deferred field. 

360 if not any(field in fields for field in deferred): 

361 kwargs = {field: getattr(instance, field) for field in fields} 

362 obj = rel_model(**kwargs) 

363 obj._state.adding = instance._state.adding 

364 obj._state.db = instance._state.db 

365 return obj 

366 return super().get_object(instance) 

367 

368 def __set__(self, instance, value): 

369 super().__set__(instance, value) 

370 # If the primary key is a link to a parent model and a parent instance 

371 # is being set, update the value of the inherited pk(s). 

372 if self.field.primary_key and self.field.remote_field.parent_link: 

373 opts = instance._meta 

374 # Inherited primary key fields from this object's base classes. 

375 inherited_pk_fields = [ 

376 field 

377 for field in opts.concrete_fields 

378 if field.primary_key and field.remote_field 

379 ] 

380 for field in inherited_pk_fields: 

381 rel_model_pk_name = field.remote_field.model._meta.pk.attname 

382 raw_value = ( 

383 getattr(value, rel_model_pk_name) if value is not None else None 

384 ) 

385 setattr(instance, rel_model_pk_name, raw_value) 

386 

387 

388class ReverseOneToOneDescriptor: 

389 """ 

390 Accessor to the related object on the reverse side of a one-to-one 

391 relation. 

392 

393 In the example:: 

394 

395 class Restaurant(Model): 

396 place = OneToOneField(Place, related_name='restaurant') 

397 

398 ``Place.restaurant`` is a ``ReverseOneToOneDescriptor`` instance. 

399 """ 

400 

401 def __init__(self, related): 

402 # Following the example above, `related` is an instance of OneToOneRel 

403 # which represents the reverse restaurant field (place.restaurant). 

404 self.related = related 

405 

406 @cached_property 

407 def RelatedObjectDoesNotExist(self): 

408 # The exception isn't created at initialization time for the sake of 

409 # consistency with `ForwardManyToOneDescriptor`. 

410 return type( 

411 "RelatedObjectDoesNotExist", 

412 (self.related.related_model.DoesNotExist, AttributeError), 

413 { 

414 "__module__": self.related.model.__module__, 

415 "__qualname__": "%s.%s.RelatedObjectDoesNotExist" 

416 % ( 

417 self.related.model.__qualname__, 

418 self.related.name, 

419 ), 

420 }, 

421 ) 

422 

423 def is_cached(self, instance): 

424 return self.related.is_cached(instance) 

425 

426 def get_queryset(self, **hints): 

427 return self.related.related_model._base_manager.db_manager(hints=hints).all() 

428 

429 def get_prefetch_queryset(self, instances, queryset=None): 

430 if queryset is None: 

431 queryset = self.get_queryset() 

432 queryset._add_hints(instance=instances[0]) 

433 

434 rel_obj_attr = self.related.field.get_local_related_value 

435 instance_attr = self.related.field.get_foreign_related_value 

436 instances_dict = {instance_attr(inst): inst for inst in instances} 

437 query = {"%s__in" % self.related.field.name: instances} 

438 queryset = queryset.filter(**query) 

439 

440 # Since we're going to assign directly in the cache, 

441 # we must manage the reverse relation cache manually. 

442 for rel_obj in queryset: 

443 instance = instances_dict[rel_obj_attr(rel_obj)] 

444 self.related.field.set_cached_value(rel_obj, instance) 

445 return ( 

446 queryset, 

447 rel_obj_attr, 

448 instance_attr, 

449 True, 

450 self.related.get_cache_name(), 

451 False, 

452 ) 

453 

454 def __get__(self, instance, cls=None): 

455 """ 

456 Get the related instance through the reverse relation. 

457 

458 With the example above, when getting ``place.restaurant``: 

459 

460 - ``self`` is the descriptor managing the ``restaurant`` attribute 

461 - ``instance`` is the ``place`` instance 

462 - ``cls`` is the ``Place`` class (unused) 

463 

464 Keep in mind that ``Restaurant`` holds the foreign key to ``Place``. 

465 """ 

466 if instance is None: 

467 return self 

468 

469 # The related instance is loaded from the database and then cached 

470 # by the field on the model instance state. It can also be pre-cached 

471 # by the forward accessor (ForwardManyToOneDescriptor). 

472 try: 

473 rel_obj = self.related.get_cached_value(instance) 

474 except KeyError: 

475 related_pk = instance.pk 

476 if related_pk is None: 

477 rel_obj = None 

478 else: 

479 filter_args = self.related.field.get_forward_related_filter(instance) 

480 try: 

481 rel_obj = self.get_queryset(instance=instance).get(**filter_args) 

482 except self.related.related_model.DoesNotExist: 

483 rel_obj = None 

484 else: 

485 # Set the forward accessor cache on the related object to 

486 # the current instance to avoid an extra SQL query if it's 

487 # accessed later on. 

488 self.related.field.set_cached_value(rel_obj, instance) 

489 self.related.set_cached_value(instance, rel_obj) 

490 

491 if rel_obj is None: 

492 raise self.RelatedObjectDoesNotExist( 

493 "%s has no %s." 

494 % (instance.__class__.__name__, self.related.get_accessor_name()) 

495 ) 

496 else: 

497 return rel_obj 

498 

499 def __set__(self, instance, value): 

500 """ 

501 Set the related instance through the reverse relation. 

502 

503 With the example above, when setting ``place.restaurant = restaurant``: 

504 

505 - ``self`` is the descriptor managing the ``restaurant`` attribute 

506 - ``instance`` is the ``place`` instance 

507 - ``value`` is the ``restaurant`` instance on the right of the equal sign 

508 

509 Keep in mind that ``Restaurant`` holds the foreign key to ``Place``. 

510 """ 

511 # The similarity of the code below to the code in 

512 # ForwardManyToOneDescriptor is annoying, but there's a bunch 

513 # of small differences that would make a common base class convoluted. 

514 

515 if value is None: 

516 # Update the cached related instance (if any) & clear the cache. 

517 # Following the example above, this would be the cached 

518 # ``restaurant`` instance (if any). 

519 rel_obj = self.related.get_cached_value(instance, default=None) 

520 if rel_obj is not None: 

521 # Remove the ``restaurant`` instance from the ``place`` 

522 # instance cache. 

523 self.related.delete_cached_value(instance) 

524 # Set the ``place`` field on the ``restaurant`` 

525 # instance to None. 

526 setattr(rel_obj, self.related.field.name, None) 

527 elif not isinstance(value, self.related.related_model): 

528 # An object must be an instance of the related class. 

529 raise ValueError( 

530 'Cannot assign "%r": "%s.%s" must be a "%s" instance.' 

531 % ( 

532 value, 

533 instance._meta.object_name, 

534 self.related.get_accessor_name(), 

535 self.related.related_model._meta.object_name, 

536 ) 

537 ) 

538 else: 

539 if instance._state.db is None: 

540 instance._state.db = router.db_for_write( 

541 instance.__class__, instance=value 

542 ) 

543 if value._state.db is None: 

544 value._state.db = router.db_for_write( 

545 value.__class__, instance=instance 

546 ) 

547 if not router.allow_relation(value, instance): 

548 raise ValueError( 

549 'Cannot assign "%r": the current database router prevents this ' 

550 "relation." % value 

551 ) 

552 

553 related_pk = tuple( 

554 getattr(instance, field.attname) 

555 for field in self.related.field.foreign_related_fields 

556 ) 

557 # Set the value of the related field to the value of the related 

558 # object's related field. 

559 for index, field in enumerate(self.related.field.local_related_fields): 

560 setattr(value, field.attname, related_pk[index]) 

561 

562 # Set the related instance cache used by __get__ to avoid an SQL query 

563 # when accessing the attribute we just set. 

564 self.related.set_cached_value(instance, value) 

565 

566 # Set the forward accessor cache on the related object to the current 

567 # instance to avoid an extra SQL query if it's accessed later on. 

568 self.related.field.set_cached_value(value, instance) 

569 

570 def __reduce__(self): 

571 # Same purpose as ForwardManyToOneDescriptor.__reduce__(). 

572 return getattr, (self.related.model, self.related.name) 

573 

574 

575class ReverseManyToOneDescriptor: 

576 """ 

577 Accessor to the related objects manager on the reverse side of a 

578 many-to-one relation. 

579 

580 In the example:: 

581 

582 class Child(Model): 

583 parent = ForeignKey(Parent, related_name='children') 

584 

585 ``Parent.children`` is a ``ReverseManyToOneDescriptor`` instance. 

586 

587 Most of the implementation is delegated to a dynamically defined manager 

588 class built by ``create_forward_many_to_many_manager()`` defined below. 

589 """ 

590 

591 def __init__(self, rel): 

592 self.rel = rel 

593 self.field = rel.field 

594 

595 @cached_property 

596 def related_manager_cls(self): 

597 related_model = self.rel.related_model 

598 

599 return create_reverse_many_to_one_manager( 

600 related_model._default_manager.__class__, 

601 self.rel, 

602 ) 

603 

604 def __get__(self, instance, cls=None): 

605 """ 

606 Get the related objects through the reverse relation. 

607 

608 With the example above, when getting ``parent.children``: 

609 

610 - ``self`` is the descriptor managing the ``children`` attribute 

611 - ``instance`` is the ``parent`` instance 

612 - ``cls`` is the ``Parent`` class (unused) 

613 """ 

614 if instance is None: 

615 return self 

616 

617 return self.related_manager_cls(instance) 

618 

619 def _get_set_deprecation_msg_params(self): 

620 return ( 

621 "reverse side of a related set", 

622 self.rel.get_accessor_name(), 

623 ) 

624 

625 def __set__(self, instance, value): 

626 raise TypeError( 

627 "Direct assignment to the %s is prohibited. Use %s.set() instead." 

628 % self._get_set_deprecation_msg_params(), 

629 ) 

630 

631 

632def create_reverse_many_to_one_manager(superclass, rel): 

633 """ 

634 Create a manager for the reverse side of a many-to-one relation. 

635 

636 This manager subclasses another manager, generally the default manager of 

637 the related model, and adds behaviors specific to many-to-one relations. 

638 """ 

639 

640 class RelatedManager(superclass, AltersData): 

641 def __init__(self, instance): 

642 super().__init__() 

643 

644 self.instance = instance 

645 self.model = rel.related_model 

646 self.field = rel.field 

647 

648 self.core_filters = {self.field.name: instance} 

649 

650 def __call__(self, *, manager): 

651 manager = getattr(self.model, manager) 

652 manager_class = create_reverse_many_to_one_manager(manager.__class__, rel) 

653 return manager_class(self.instance) 

654 

655 do_not_call_in_templates = True 

656 

657 def _check_fk_val(self): 

658 for field in self.field.foreign_related_fields: 

659 if getattr(self.instance, field.attname) is None: 

660 raise ValueError( 

661 f'"{self.instance!r}" needs to have a value for field ' 

662 f'"{field.attname}" before this relationship can be used.' 

663 ) 

664 

665 def _apply_rel_filters(self, queryset): 

666 """ 

667 Filter the queryset for the instance this manager is bound to. 

668 """ 

669 db = self._db or router.db_for_read(self.model, instance=self.instance) 

670 empty_strings_as_null = connections[ 

671 db 

672 ].features.interprets_empty_strings_as_nulls 

673 queryset._add_hints(instance=self.instance) 

674 if self._db: 

675 queryset = queryset.using(self._db) 

676 queryset._defer_next_filter = True 

677 queryset = queryset.filter(**self.core_filters) 

678 for field in self.field.foreign_related_fields: 

679 val = getattr(self.instance, field.attname) 

680 if val is None or (val == "" and empty_strings_as_null): 

681 return queryset.none() 

682 if self.field.many_to_one: 

683 # Guard against field-like objects such as GenericRelation 

684 # that abuse create_reverse_many_to_one_manager() with reverse 

685 # one-to-many relationships instead and break known related 

686 # objects assignment. 

687 try: 

688 target_field = self.field.target_field 

689 except FieldError: 

690 # The relationship has multiple target fields. Use a tuple 

691 # for related object id. 

692 rel_obj_id = tuple( 

693 [ 

694 getattr(self.instance, target_field.attname) 

695 for target_field in self.field.path_infos[-1].target_fields 

696 ] 

697 ) 

698 else: 

699 rel_obj_id = getattr(self.instance, target_field.attname) 

700 queryset._known_related_objects = { 

701 self.field: {rel_obj_id: self.instance} 

702 } 

703 return queryset 

704 

705 def _remove_prefetched_objects(self): 

706 try: 

707 self.instance._prefetched_objects_cache.pop( 

708 self.field.remote_field.get_cache_name() 

709 ) 

710 except (AttributeError, KeyError): 

711 pass # nothing to clear from cache 

712 

713 def get_queryset(self): 

714 # Even if this relation is not to pk, we require still pk value. 

715 # The wish is that the instance has been already saved to DB, 

716 # although having a pk value isn't a guarantee of that. 

717 if self.instance.pk is None: 

718 raise ValueError( 

719 f"{self.instance.__class__.__name__!r} instance needs to have a " 

720 f"primary key value before this relationship can be used." 

721 ) 

722 try: 

723 return self.instance._prefetched_objects_cache[ 

724 self.field.remote_field.get_cache_name() 

725 ] 

726 except (AttributeError, KeyError): 

727 queryset = super().get_queryset() 

728 return self._apply_rel_filters(queryset) 

729 

730 def get_prefetch_queryset(self, instances, queryset=None): 

731 if queryset is None: 

732 queryset = super().get_queryset() 

733 

734 queryset._add_hints(instance=instances[0]) 

735 queryset = queryset.using(queryset._db or self._db) 

736 

737 rel_obj_attr = self.field.get_local_related_value 

738 instance_attr = self.field.get_foreign_related_value 

739 instances_dict = {instance_attr(inst): inst for inst in instances} 

740 queryset = _filter_prefetch_queryset(queryset, self.field.name, instances) 

741 

742 # Since we just bypassed this class' get_queryset(), we must manage 

743 # the reverse relation manually. 

744 for rel_obj in queryset: 

745 if not self.field.is_cached(rel_obj): 

746 instance = instances_dict[rel_obj_attr(rel_obj)] 

747 setattr(rel_obj, self.field.name, instance) 

748 cache_name = self.field.remote_field.get_cache_name() 

749 return queryset, rel_obj_attr, instance_attr, False, cache_name, False 

750 

751 def add(self, *objs, bulk=True): 

752 self._check_fk_val() 

753 self._remove_prefetched_objects() 

754 db = router.db_for_write(self.model, instance=self.instance) 

755 

756 def check_and_update_obj(obj): 

757 if not isinstance(obj, self.model): 

758 raise TypeError( 

759 "'%s' instance expected, got %r" 

760 % ( 

761 self.model._meta.object_name, 

762 obj, 

763 ) 

764 ) 

765 setattr(obj, self.field.name, self.instance) 

766 

767 if bulk: 

768 pks = [] 

769 for obj in objs: 

770 check_and_update_obj(obj) 

771 if obj._state.adding or obj._state.db != db: 

772 raise ValueError( 

773 "%r instance isn't saved. Use bulk=False or save " 

774 "the object first." % obj 

775 ) 

776 pks.append(obj.pk) 

777 self.model._base_manager.using(db).filter(pk__in=pks).update( 

778 **{ 

779 self.field.name: self.instance, 

780 } 

781 ) 

782 else: 

783 with transaction.atomic(using=db, savepoint=False): 

784 for obj in objs: 

785 check_and_update_obj(obj) 

786 obj.save() 

787 

788 add.alters_data = True 

789 

790 async def aadd(self, *objs, bulk=True): 

791 return await sync_to_async(self.add)(*objs, bulk=bulk) 

792 

793 aadd.alters_data = True 

794 

795 def create(self, **kwargs): 

796 self._check_fk_val() 

797 kwargs[self.field.name] = self.instance 

798 db = router.db_for_write(self.model, instance=self.instance) 

799 return super(RelatedManager, self.db_manager(db)).create(**kwargs) 

800 

801 create.alters_data = True 

802 

803 async def acreate(self, **kwargs): 

804 return await sync_to_async(self.create)(**kwargs) 

805 

806 acreate.alters_data = True 

807 

808 def get_or_create(self, **kwargs): 

809 self._check_fk_val() 

810 kwargs[self.field.name] = self.instance 

811 db = router.db_for_write(self.model, instance=self.instance) 

812 return super(RelatedManager, self.db_manager(db)).get_or_create(**kwargs) 

813 

814 get_or_create.alters_data = True 

815 

816 async def aget_or_create(self, **kwargs): 

817 return await sync_to_async(self.get_or_create)(**kwargs) 

818 

819 aget_or_create.alters_data = True 

820 

821 def update_or_create(self, **kwargs): 

822 self._check_fk_val() 

823 kwargs[self.field.name] = self.instance 

824 db = router.db_for_write(self.model, instance=self.instance) 

825 return super(RelatedManager, self.db_manager(db)).update_or_create(**kwargs) 

826 

827 update_or_create.alters_data = True 

828 

829 async def aupdate_or_create(self, **kwargs): 

830 return await sync_to_async(self.update_or_create)(**kwargs) 

831 

832 aupdate_or_create.alters_data = True 

833 

834 # remove() and clear() are only provided if the ForeignKey can have a 

835 # value of null. 

836 if rel.field.null: 

837 

838 def remove(self, *objs, bulk=True): 

839 if not objs: 

840 return 

841 self._check_fk_val() 

842 val = self.field.get_foreign_related_value(self.instance) 

843 old_ids = set() 

844 for obj in objs: 

845 if not isinstance(obj, self.model): 

846 raise TypeError( 

847 "'%s' instance expected, got %r" 

848 % ( 

849 self.model._meta.object_name, 

850 obj, 

851 ) 

852 ) 

853 # Is obj actually part of this descriptor set? 

854 if self.field.get_local_related_value(obj) == val: 

855 old_ids.add(obj.pk) 

856 else: 

857 raise self.field.remote_field.model.DoesNotExist( 

858 "%r is not related to %r." % (obj, self.instance) 

859 ) 

860 self._clear(self.filter(pk__in=old_ids), bulk) 

861 

862 remove.alters_data = True 

863 

864 async def aremove(self, *objs, bulk=True): 

865 return await sync_to_async(self.remove)(*objs, bulk=bulk) 

866 

867 aremove.alters_data = True 

868 

869 def clear(self, *, bulk=True): 

870 self._check_fk_val() 

871 self._clear(self, bulk) 

872 

873 clear.alters_data = True 

874 

875 async def aclear(self, *, bulk=True): 

876 return await sync_to_async(self.clear)(bulk=bulk) 

877 

878 aclear.alters_data = True 

879 

880 def _clear(self, queryset, bulk): 

881 self._remove_prefetched_objects() 

882 db = router.db_for_write(self.model, instance=self.instance) 

883 queryset = queryset.using(db) 

884 if bulk: 

885 # `QuerySet.update()` is intrinsically atomic. 

886 queryset.update(**{self.field.name: None}) 

887 else: 

888 with transaction.atomic(using=db, savepoint=False): 

889 for obj in queryset: 

890 setattr(obj, self.field.name, None) 

891 obj.save(update_fields=[self.field.name]) 

892 

893 _clear.alters_data = True 

894 

895 def set(self, objs, *, bulk=True, clear=False): 

896 self._check_fk_val() 

897 # Force evaluation of `objs` in case it's a queryset whose value 

898 # could be affected by `manager.clear()`. Refs #19816. 

899 objs = tuple(objs) 

900 

901 if self.field.null: 

902 db = router.db_for_write(self.model, instance=self.instance) 

903 with transaction.atomic(using=db, savepoint=False): 

904 if clear: 

905 self.clear(bulk=bulk) 

906 self.add(*objs, bulk=bulk) 

907 else: 

908 old_objs = set(self.using(db).all()) 

909 new_objs = [] 

910 for obj in objs: 

911 if obj in old_objs: 

912 old_objs.remove(obj) 

913 else: 

914 new_objs.append(obj) 

915 

916 self.remove(*old_objs, bulk=bulk) 

917 self.add(*new_objs, bulk=bulk) 

918 else: 

919 self.add(*objs, bulk=bulk) 

920 

921 set.alters_data = True 

922 

923 async def aset(self, objs, *, bulk=True, clear=False): 

924 return await sync_to_async(self.set)(objs=objs, bulk=bulk, clear=clear) 

925 

926 aset.alters_data = True 

927 

928 return RelatedManager 

929 

930 

931class ManyToManyDescriptor(ReverseManyToOneDescriptor): 

932 """ 

933 Accessor to the related objects manager on the forward and reverse sides of 

934 a many-to-many relation. 

935 

936 In the example:: 

937 

938 class Pizza(Model): 

939 toppings = ManyToManyField(Topping, related_name='pizzas') 

940 

941 ``Pizza.toppings`` and ``Topping.pizzas`` are ``ManyToManyDescriptor`` 

942 instances. 

943 

944 Most of the implementation is delegated to a dynamically defined manager 

945 class built by ``create_forward_many_to_many_manager()`` defined below. 

946 """ 

947 

948 def __init__(self, rel, reverse=False): 

949 super().__init__(rel) 

950 

951 self.reverse = reverse 

952 

953 @property 

954 def through(self): 

955 # through is provided so that you have easy access to the through 

956 # model (Book.authors.through) for inlines, etc. This is done as 

957 # a property to ensure that the fully resolved value is returned. 

958 return self.rel.through 

959 

960 @cached_property 

961 def related_manager_cls(self): 

962 related_model = self.rel.related_model if self.reverse else self.rel.model 

963 

964 return create_forward_many_to_many_manager( 

965 related_model._default_manager.__class__, 

966 self.rel, 

967 reverse=self.reverse, 

968 ) 

969 

970 def _get_set_deprecation_msg_params(self): 

971 return ( 

972 "%s side of a many-to-many set" 

973 % ("reverse" if self.reverse else "forward"), 

974 self.rel.get_accessor_name() if self.reverse else self.field.name, 

975 ) 

976 

977 

978def create_forward_many_to_many_manager(superclass, rel, reverse): 

979 """ 

980 Create a manager for the either side of a many-to-many relation. 

981 

982 This manager subclasses another manager, generally the default manager of 

983 the related model, and adds behaviors specific to many-to-many relations. 

984 """ 

985 

986 class ManyRelatedManager(superclass, AltersData): 

987 def __init__(self, instance=None): 

988 super().__init__() 

989 

990 self.instance = instance 

991 

992 if not reverse: 

993 self.model = rel.model 

994 self.query_field_name = rel.field.related_query_name() 

995 self.prefetch_cache_name = rel.field.name 

996 self.source_field_name = rel.field.m2m_field_name() 

997 self.target_field_name = rel.field.m2m_reverse_field_name() 

998 self.symmetrical = rel.symmetrical 

999 else: 

1000 self.model = rel.related_model 

1001 self.query_field_name = rel.field.name 

1002 self.prefetch_cache_name = rel.field.related_query_name() 

1003 self.source_field_name = rel.field.m2m_reverse_field_name() 

1004 self.target_field_name = rel.field.m2m_field_name() 

1005 self.symmetrical = False 

1006 

1007 self.through = rel.through 

1008 self.reverse = reverse 

1009 

1010 self.source_field = self.through._meta.get_field(self.source_field_name) 

1011 self.target_field = self.through._meta.get_field(self.target_field_name) 

1012 

1013 self.core_filters = {} 

1014 self.pk_field_names = {} 

1015 for lh_field, rh_field in self.source_field.related_fields: 

1016 core_filter_key = "%s__%s" % (self.query_field_name, rh_field.name) 

1017 self.core_filters[core_filter_key] = getattr(instance, rh_field.attname) 

1018 self.pk_field_names[lh_field.name] = rh_field.name 

1019 

1020 self.related_val = self.source_field.get_foreign_related_value(instance) 

1021 if None in self.related_val: 

1022 raise ValueError( 

1023 '"%r" needs to have a value for field "%s" before ' 

1024 "this many-to-many relationship can be used." 

1025 % (instance, self.pk_field_names[self.source_field_name]) 

1026 ) 

1027 # Even if this relation is not to pk, we require still pk value. 

1028 # The wish is that the instance has been already saved to DB, 

1029 # although having a pk value isn't a guarantee of that. 

1030 if instance.pk is None: 

1031 raise ValueError( 

1032 "%r instance needs to have a primary key value before " 

1033 "a many-to-many relationship can be used." 

1034 % instance.__class__.__name__ 

1035 ) 

1036 

1037 def __call__(self, *, manager): 

1038 manager = getattr(self.model, manager) 

1039 manager_class = create_forward_many_to_many_manager( 

1040 manager.__class__, rel, reverse 

1041 ) 

1042 return manager_class(instance=self.instance) 

1043 

1044 do_not_call_in_templates = True 

1045 

1046 def _build_remove_filters(self, removed_vals): 

1047 filters = Q.create([(self.source_field_name, self.related_val)]) 

1048 # No need to add a subquery condition if removed_vals is a QuerySet without 

1049 # filters. 

1050 removed_vals_filters = ( 

1051 not isinstance(removed_vals, QuerySet) or removed_vals._has_filters() 

1052 ) 

1053 if removed_vals_filters: 

1054 filters &= Q.create([(f"{self.target_field_name}__in", removed_vals)]) 

1055 if self.symmetrical: 

1056 symmetrical_filters = Q.create( 

1057 [(self.target_field_name, self.related_val)] 

1058 ) 

1059 if removed_vals_filters: 

1060 symmetrical_filters &= Q.create( 

1061 [(f"{self.source_field_name}__in", removed_vals)] 

1062 ) 

1063 filters |= symmetrical_filters 

1064 return filters 

1065 

1066 def _apply_rel_filters(self, queryset): 

1067 """ 

1068 Filter the queryset for the instance this manager is bound to. 

1069 """ 

1070 queryset._add_hints(instance=self.instance) 

1071 if self._db: 

1072 queryset = queryset.using(self._db) 

1073 queryset._defer_next_filter = True 

1074 return queryset._next_is_sticky().filter(**self.core_filters) 

1075 

1076 def _remove_prefetched_objects(self): 

1077 try: 

1078 self.instance._prefetched_objects_cache.pop(self.prefetch_cache_name) 

1079 except (AttributeError, KeyError): 

1080 pass # nothing to clear from cache 

1081 

1082 def get_queryset(self): 

1083 try: 

1084 return self.instance._prefetched_objects_cache[self.prefetch_cache_name] 

1085 except (AttributeError, KeyError): 

1086 queryset = super().get_queryset() 

1087 return self._apply_rel_filters(queryset) 

1088 

1089 def get_prefetch_queryset(self, instances, queryset=None): 

1090 if queryset is None: 

1091 queryset = super().get_queryset() 

1092 

1093 queryset._add_hints(instance=instances[0]) 

1094 queryset = queryset.using(queryset._db or self._db) 

1095 queryset = _filter_prefetch_queryset( 

1096 queryset._next_is_sticky(), self.query_field_name, instances 

1097 ) 

1098 

1099 # M2M: need to annotate the query in order to get the primary model 

1100 # that the secondary model was actually related to. We know that 

1101 # there will already be a join on the join table, so we can just add 

1102 # the select. 

1103 

1104 # For non-autocreated 'through' models, can't assume we are 

1105 # dealing with PK values. 

1106 fk = self.through._meta.get_field(self.source_field_name) 

1107 join_table = fk.model._meta.db_table 

1108 connection = connections[queryset.db] 

1109 qn = connection.ops.quote_name 

1110 queryset = queryset.extra( 

1111 select={ 

1112 "_prefetch_related_val_%s" 

1113 % f.attname: "%s.%s" 

1114 % (qn(join_table), qn(f.column)) 

1115 for f in fk.local_related_fields 

1116 } 

1117 ) 

1118 return ( 

1119 queryset, 

1120 lambda result: tuple( 

1121 getattr(result, "_prefetch_related_val_%s" % f.attname) 

1122 for f in fk.local_related_fields 

1123 ), 

1124 lambda inst: tuple( 

1125 f.get_db_prep_value(getattr(inst, f.attname), connection) 

1126 for f in fk.foreign_related_fields 

1127 ), 

1128 False, 

1129 self.prefetch_cache_name, 

1130 False, 

1131 ) 

1132 

1133 def add(self, *objs, through_defaults=None): 

1134 self._remove_prefetched_objects() 

1135 db = router.db_for_write(self.through, instance=self.instance) 

1136 with transaction.atomic(using=db, savepoint=False): 

1137 self._add_items( 

1138 self.source_field_name, 

1139 self.target_field_name, 

1140 *objs, 

1141 through_defaults=through_defaults, 

1142 ) 

1143 # If this is a symmetrical m2m relation to self, add the mirror 

1144 # entry in the m2m table. 

1145 if self.symmetrical: 

1146 self._add_items( 

1147 self.target_field_name, 

1148 self.source_field_name, 

1149 *objs, 

1150 through_defaults=through_defaults, 

1151 ) 

1152 

1153 add.alters_data = True 

1154 

1155 async def aadd(self, *objs, through_defaults=None): 

1156 return await sync_to_async(self.add)( 

1157 *objs, through_defaults=through_defaults 

1158 ) 

1159 

1160 aadd.alters_data = True 

1161 

1162 def remove(self, *objs): 

1163 self._remove_prefetched_objects() 

1164 self._remove_items(self.source_field_name, self.target_field_name, *objs) 

1165 

1166 remove.alters_data = True 

1167 

1168 async def aremove(self, *objs): 

1169 return await sync_to_async(self.remove)(*objs) 

1170 

1171 aremove.alters_data = True 

1172 

1173 def clear(self): 

1174 db = router.db_for_write(self.through, instance=self.instance) 

1175 with transaction.atomic(using=db, savepoint=False): 

1176 signals.m2m_changed.send( 

1177 sender=self.through, 

1178 action="pre_clear", 

1179 instance=self.instance, 

1180 reverse=self.reverse, 

1181 model=self.model, 

1182 pk_set=None, 

1183 using=db, 

1184 ) 

1185 self._remove_prefetched_objects() 

1186 filters = self._build_remove_filters(super().get_queryset().using(db)) 

1187 self.through._default_manager.using(db).filter(filters).delete() 

1188 

1189 signals.m2m_changed.send( 

1190 sender=self.through, 

1191 action="post_clear", 

1192 instance=self.instance, 

1193 reverse=self.reverse, 

1194 model=self.model, 

1195 pk_set=None, 

1196 using=db, 

1197 ) 

1198 

1199 clear.alters_data = True 

1200 

1201 async def aclear(self): 

1202 return await sync_to_async(self.clear)() 

1203 

1204 aclear.alters_data = True 

1205 

1206 def set(self, objs, *, clear=False, through_defaults=None): 

1207 # Force evaluation of `objs` in case it's a queryset whose value 

1208 # could be affected by `manager.clear()`. Refs #19816. 

1209 objs = tuple(objs) 

1210 

1211 db = router.db_for_write(self.through, instance=self.instance) 

1212 with transaction.atomic(using=db, savepoint=False): 

1213 if clear: 

1214 self.clear() 

1215 self.add(*objs, through_defaults=through_defaults) 

1216 else: 

1217 old_ids = set( 

1218 self.using(db).values_list( 

1219 self.target_field.target_field.attname, flat=True 

1220 ) 

1221 ) 

1222 

1223 new_objs = [] 

1224 for obj in objs: 

1225 fk_val = ( 

1226 self.target_field.get_foreign_related_value(obj)[0] 

1227 if isinstance(obj, self.model) 

1228 else self.target_field.get_prep_value(obj) 

1229 ) 

1230 if fk_val in old_ids: 

1231 old_ids.remove(fk_val) 

1232 else: 

1233 new_objs.append(obj) 

1234 

1235 self.remove(*old_ids) 

1236 self.add(*new_objs, through_defaults=through_defaults) 

1237 

1238 set.alters_data = True 

1239 

1240 async def aset(self, objs, *, clear=False, through_defaults=None): 

1241 return await sync_to_async(self.set)( 

1242 objs=objs, clear=clear, through_defaults=through_defaults 

1243 ) 

1244 

1245 aset.alters_data = True 

1246 

1247 def create(self, *, through_defaults=None, **kwargs): 

1248 db = router.db_for_write(self.instance.__class__, instance=self.instance) 

1249 new_obj = super(ManyRelatedManager, self.db_manager(db)).create(**kwargs) 

1250 self.add(new_obj, through_defaults=through_defaults) 

1251 return new_obj 

1252 

1253 create.alters_data = True 

1254 

1255 async def acreate(self, *, through_defaults=None, **kwargs): 

1256 return await sync_to_async(self.create)( 

1257 through_defaults=through_defaults, **kwargs 

1258 ) 

1259 

1260 acreate.alters_data = True 

1261 

1262 def get_or_create(self, *, through_defaults=None, **kwargs): 

1263 db = router.db_for_write(self.instance.__class__, instance=self.instance) 

1264 obj, created = super(ManyRelatedManager, self.db_manager(db)).get_or_create( 

1265 **kwargs 

1266 ) 

1267 # We only need to add() if created because if we got an object back 

1268 # from get() then the relationship already exists. 

1269 if created: 

1270 self.add(obj, through_defaults=through_defaults) 

1271 return obj, created 

1272 

1273 get_or_create.alters_data = True 

1274 

1275 async def aget_or_create(self, *, through_defaults=None, **kwargs): 

1276 return await sync_to_async(self.get_or_create)( 

1277 through_defaults=through_defaults, **kwargs 

1278 ) 

1279 

1280 aget_or_create.alters_data = True 

1281 

1282 def update_or_create(self, *, through_defaults=None, **kwargs): 

1283 db = router.db_for_write(self.instance.__class__, instance=self.instance) 

1284 obj, created = super( 

1285 ManyRelatedManager, self.db_manager(db) 

1286 ).update_or_create(**kwargs) 

1287 # We only need to add() if created because if we got an object back 

1288 # from get() then the relationship already exists. 

1289 if created: 

1290 self.add(obj, through_defaults=through_defaults) 

1291 return obj, created 

1292 

1293 update_or_create.alters_data = True 

1294 

1295 async def aupdate_or_create(self, *, through_defaults=None, **kwargs): 

1296 return await sync_to_async(self.update_or_create)( 

1297 through_defaults=through_defaults, **kwargs 

1298 ) 

1299 

1300 aupdate_or_create.alters_data = True 

1301 

1302 def _get_target_ids(self, target_field_name, objs): 

1303 """ 

1304 Return the set of ids of `objs` that the target field references. 

1305 """ 

1306 from django.db.models import Model 

1307 

1308 target_ids = set() 

1309 target_field = self.through._meta.get_field(target_field_name) 

1310 for obj in objs: 

1311 if isinstance(obj, self.model): 

1312 if not router.allow_relation(obj, self.instance): 

1313 raise ValueError( 

1314 'Cannot add "%r": instance is on database "%s", ' 

1315 'value is on database "%s"' 

1316 % (obj, self.instance._state.db, obj._state.db) 

1317 ) 

1318 target_id = target_field.get_foreign_related_value(obj)[0] 

1319 if target_id is None: 

1320 raise ValueError( 

1321 'Cannot add "%r": the value for field "%s" is None' 

1322 % (obj, target_field_name) 

1323 ) 

1324 target_ids.add(target_id) 

1325 elif isinstance(obj, Model): 

1326 raise TypeError( 

1327 "'%s' instance expected, got %r" 

1328 % (self.model._meta.object_name, obj) 

1329 ) 

1330 else: 

1331 target_ids.add(target_field.get_prep_value(obj)) 

1332 return target_ids 

1333 

1334 def _get_missing_target_ids( 

1335 self, source_field_name, target_field_name, db, target_ids 

1336 ): 

1337 """ 

1338 Return the subset of ids of `objs` that aren't already assigned to 

1339 this relationship. 

1340 """ 

1341 vals = ( 

1342 self.through._default_manager.using(db) 

1343 .values_list(target_field_name, flat=True) 

1344 .filter( 

1345 **{ 

1346 source_field_name: self.related_val[0], 

1347 "%s__in" % target_field_name: target_ids, 

1348 } 

1349 ) 

1350 ) 

1351 return target_ids.difference(vals) 

1352 

1353 def _get_add_plan(self, db, source_field_name): 

1354 """ 

1355 Return a boolean triple of the way the add should be performed. 

1356 

1357 The first element is whether or not bulk_create(ignore_conflicts) 

1358 can be used, the second whether or not signals must be sent, and 

1359 the third element is whether or not the immediate bulk insertion 

1360 with conflicts ignored can be performed. 

1361 """ 

1362 # Conflicts can be ignored when the intermediary model is 

1363 # auto-created as the only possible collision is on the 

1364 # (source_id, target_id) tuple. The same assertion doesn't hold for 

1365 # user-defined intermediary models as they could have other fields 

1366 # causing conflicts which must be surfaced. 

1367 can_ignore_conflicts = ( 

1368 self.through._meta.auto_created is not False 

1369 and connections[db].features.supports_ignore_conflicts 

1370 ) 

1371 # Don't send the signal when inserting duplicate data row 

1372 # for symmetrical reverse entries. 

1373 must_send_signals = ( 

1374 self.reverse or source_field_name == self.source_field_name 

1375 ) and (signals.m2m_changed.has_listeners(self.through)) 

1376 # Fast addition through bulk insertion can only be performed 

1377 # if no m2m_changed listeners are connected for self.through 

1378 # as they require the added set of ids to be provided via 

1379 # pk_set. 

1380 return ( 

1381 can_ignore_conflicts, 

1382 must_send_signals, 

1383 (can_ignore_conflicts and not must_send_signals), 

1384 ) 

1385 

1386 def _add_items( 

1387 self, source_field_name, target_field_name, *objs, through_defaults=None 

1388 ): 

1389 # source_field_name: the PK fieldname in join table for the source object 

1390 # target_field_name: the PK fieldname in join table for the target object 

1391 # *objs - objects to add. Either object instances, or primary keys 

1392 # of object instances. 

1393 if not objs: 

1394 return 

1395 

1396 through_defaults = dict(resolve_callables(through_defaults or {})) 

1397 target_ids = self._get_target_ids(target_field_name, objs) 

1398 db = router.db_for_write(self.through, instance=self.instance) 

1399 can_ignore_conflicts, must_send_signals, can_fast_add = self._get_add_plan( 

1400 db, source_field_name 

1401 ) 

1402 if can_fast_add: 

1403 self.through._default_manager.using(db).bulk_create( 

1404 [ 

1405 self.through( 

1406 **{ 

1407 "%s_id" % source_field_name: self.related_val[0], 

1408 "%s_id" % target_field_name: target_id, 

1409 } 

1410 ) 

1411 for target_id in target_ids 

1412 ], 

1413 ignore_conflicts=True, 

1414 ) 

1415 return 

1416 

1417 missing_target_ids = self._get_missing_target_ids( 

1418 source_field_name, target_field_name, db, target_ids 

1419 ) 

1420 with transaction.atomic(using=db, savepoint=False): 

1421 if must_send_signals: 

1422 signals.m2m_changed.send( 

1423 sender=self.through, 

1424 action="pre_add", 

1425 instance=self.instance, 

1426 reverse=self.reverse, 

1427 model=self.model, 

1428 pk_set=missing_target_ids, 

1429 using=db, 

1430 ) 

1431 # Add the ones that aren't there already. 

1432 self.through._default_manager.using(db).bulk_create( 

1433 [ 

1434 self.through( 

1435 **through_defaults, 

1436 **{ 

1437 "%s_id" % source_field_name: self.related_val[0], 

1438 "%s_id" % target_field_name: target_id, 

1439 }, 

1440 ) 

1441 for target_id in missing_target_ids 

1442 ], 

1443 ignore_conflicts=can_ignore_conflicts, 

1444 ) 

1445 

1446 if must_send_signals: 

1447 signals.m2m_changed.send( 

1448 sender=self.through, 

1449 action="post_add", 

1450 instance=self.instance, 

1451 reverse=self.reverse, 

1452 model=self.model, 

1453 pk_set=missing_target_ids, 

1454 using=db, 

1455 ) 

1456 

1457 def _remove_items(self, source_field_name, target_field_name, *objs): 

1458 # source_field_name: the PK colname in join table for the source object 

1459 # target_field_name: the PK colname in join table for the target object 

1460 # *objs - objects to remove. Either object instances, or primary 

1461 # keys of object instances. 

1462 if not objs: 

1463 return 

1464 

1465 # Check that all the objects are of the right type 

1466 old_ids = set() 

1467 for obj in objs: 

1468 if isinstance(obj, self.model): 

1469 fk_val = self.target_field.get_foreign_related_value(obj)[0] 

1470 old_ids.add(fk_val) 

1471 else: 

1472 old_ids.add(obj) 

1473 

1474 db = router.db_for_write(self.through, instance=self.instance) 

1475 with transaction.atomic(using=db, savepoint=False): 

1476 # Send a signal to the other end if need be. 

1477 signals.m2m_changed.send( 

1478 sender=self.through, 

1479 action="pre_remove", 

1480 instance=self.instance, 

1481 reverse=self.reverse, 

1482 model=self.model, 

1483 pk_set=old_ids, 

1484 using=db, 

1485 ) 

1486 target_model_qs = super().get_queryset() 

1487 if target_model_qs._has_filters(): 

1488 old_vals = target_model_qs.using(db).filter( 

1489 **{"%s__in" % self.target_field.target_field.attname: old_ids} 

1490 ) 

1491 else: 

1492 old_vals = old_ids 

1493 filters = self._build_remove_filters(old_vals) 

1494 self.through._default_manager.using(db).filter(filters).delete() 

1495 

1496 signals.m2m_changed.send( 

1497 sender=self.through, 

1498 action="post_remove", 

1499 instance=self.instance, 

1500 reverse=self.reverse, 

1501 model=self.model, 

1502 pk_set=old_ids, 

1503 using=db, 

1504 ) 

1505 

1506 return ManyRelatedManager