Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/forms/models.py: 16%

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

721 statements  

1""" 

2Helper functions for creating Form classes from Django models 

3and database field objects. 

4""" 

5 

6from itertools import chain 

7 

8from django.core.exceptions import ( 

9 NON_FIELD_ERRORS, 

10 FieldError, 

11 ImproperlyConfigured, 

12 ValidationError, 

13) 

14from django.core.validators import ProhibitNullCharactersValidator 

15from django.db.models.utils import AltersData 

16from django.forms.fields import ChoiceField, Field 

17from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass 

18from django.forms.formsets import BaseFormSet, formset_factory 

19from django.forms.utils import ErrorList 

20from django.forms.widgets import ( 

21 HiddenInput, 

22 MultipleHiddenInput, 

23 RadioSelect, 

24 SelectMultiple, 

25) 

26from django.utils.choices import BaseChoiceIterator 

27from django.utils.hashable import make_hashable 

28from django.utils.text import capfirst, get_text_list 

29from django.utils.translation import gettext 

30from django.utils.translation import gettext_lazy as _ 

31 

32__all__ = ( 

33 "ModelForm", 

34 "BaseModelForm", 

35 "model_to_dict", 

36 "fields_for_model", 

37 "ModelChoiceField", 

38 "ModelMultipleChoiceField", 

39 "ALL_FIELDS", 

40 "BaseModelFormSet", 

41 "modelformset_factory", 

42 "BaseInlineFormSet", 

43 "inlineformset_factory", 

44 "modelform_factory", 

45) 

46 

47ALL_FIELDS = "__all__" 

48 

49 

50def construct_instance(form, instance, fields=None, exclude=None): 

51 """ 

52 Construct and return a model instance from the bound ``form``'s 

53 ``cleaned_data``, but do not save the returned instance to the database. 

54 """ 

55 from django.db import models 

56 

57 opts = instance._meta 

58 

59 cleaned_data = form.cleaned_data 

60 file_field_list = [] 

61 for f in opts.fields: 

62 if ( 

63 not f.editable 

64 or isinstance(f, models.AutoField) 

65 or f.name not in cleaned_data 

66 ): 

67 continue 

68 if fields is not None and f.name not in fields: 

69 continue 

70 if exclude and f.name in exclude: 

71 continue 

72 # Leave defaults for fields that aren't in POST data, except for 

73 # checkbox inputs because they don't appear in POST data if not checked. 

74 if ( 

75 f.has_default() 

76 and form[f.name].field.widget.value_omitted_from_data( 

77 form.data, form.files, form.add_prefix(f.name) 

78 ) 

79 and cleaned_data.get(f.name) in form[f.name].field.empty_values 

80 ): 

81 continue 

82 # Defer saving file-type fields until after the other fields, so a 

83 # callable upload_to can use the values from other fields. 

84 if isinstance(f, models.FileField): 

85 file_field_list.append(f) 

86 else: 

87 f.save_form_data(instance, cleaned_data[f.name]) 

88 

89 for f in file_field_list: 

90 f.save_form_data(instance, cleaned_data[f.name]) 

91 

92 return instance 

93 

94 

95# ModelForms ################################################################# 

96 

97 

98def model_to_dict(instance, fields=None, exclude=None): 

99 """ 

100 Return a dict containing the data in ``instance`` suitable for passing as 

101 a Form's ``initial`` keyword argument. 

102 

103 ``fields`` is an optional list of field names. If provided, return only the 

104 named. 

105 

106 ``exclude`` is an optional list of field names. If provided, exclude the 

107 named from the returned dict, even if they are listed in the ``fields`` 

108 argument. 

109 """ 

110 opts = instance._meta 

111 data = {} 

112 for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): 

113 if not getattr(f, "editable", False): 

114 continue 

115 if fields is not None and f.name not in fields: 

116 continue 

117 if exclude and f.name in exclude: 

118 continue 

119 data[f.name] = f.value_from_object(instance) 

120 return data 

121 

122 

123def apply_limit_choices_to_to_formfield(formfield): 

124 """Apply limit_choices_to to the formfield's queryset if needed.""" 

125 from django.db.models import Exists, OuterRef, Q 

126 

127 if hasattr(formfield, "queryset") and hasattr(formfield, "get_limit_choices_to"): 

128 limit_choices_to = formfield.get_limit_choices_to() 

129 if limit_choices_to: 

130 complex_filter = limit_choices_to 

131 if not isinstance(complex_filter, Q): 

132 complex_filter = Q(**limit_choices_to) 

133 complex_filter &= Q(pk=OuterRef("pk")) 

134 # Use Exists() to avoid potential duplicates. 

135 formfield.queryset = formfield.queryset.filter( 

136 Exists(formfield.queryset.model._base_manager.filter(complex_filter)), 

137 ) 

138 

139 

140def fields_for_model( 

141 model, 

142 fields=None, 

143 exclude=None, 

144 widgets=None, 

145 formfield_callback=None, 

146 localized_fields=None, 

147 labels=None, 

148 help_texts=None, 

149 error_messages=None, 

150 field_classes=None, 

151 *, 

152 apply_limit_choices_to=True, 

153 form_declared_fields=None, 

154): 

155 """ 

156 Return a dictionary containing form fields for the given model. 

157 

158 ``fields`` is an optional list of field names. If provided, return only the 

159 named fields. 

160 

161 ``exclude`` is an optional list of field names. If provided, exclude the 

162 named fields from the returned fields, even if they are listed in the 

163 ``fields`` argument. 

164 

165 ``widgets`` is a dictionary of model field names mapped to a widget. 

166 

167 ``formfield_callback`` is a callable that takes a model field and returns 

168 a form field. 

169 

170 ``localized_fields`` is a list of names of fields which should be localized. 

171 

172 ``labels`` is a dictionary of model field names mapped to a label. 

173 

174 ``help_texts`` is a dictionary of model field names mapped to a help text. 

175 

176 ``error_messages`` is a dictionary of model field names mapped to a 

177 dictionary of error messages. 

178 

179 ``field_classes`` is a dictionary of model field names mapped to a form 

180 field class. 

181 

182 ``apply_limit_choices_to`` is a boolean indicating if limit_choices_to 

183 should be applied to a field's queryset. 

184 

185 ``form_declared_fields`` is a dictionary of form fields created directly on 

186 a form. 

187 """ 

188 form_declared_fields = form_declared_fields or {} 

189 field_dict = {} 

190 ignored = [] 

191 opts = model._meta 

192 # Avoid circular import 

193 from django.db.models import Field as ModelField 

194 

195 sortable_private_fields = [ 

196 f for f in opts.private_fields if isinstance(f, ModelField) 

197 ] 

198 for f in sorted( 

199 chain(opts.concrete_fields, sortable_private_fields, opts.many_to_many) 

200 ): 

201 if not getattr(f, "editable", False): 

202 if ( 

203 fields is not None 

204 and f.name in fields 

205 and (exclude is None or f.name not in exclude) 

206 ): 

207 raise FieldError( 

208 "'%s' cannot be specified for %s model form as it is a " 

209 "non-editable field" % (f.name, model.__name__) 

210 ) 

211 continue 

212 if fields is not None and f.name not in fields: 

213 continue 

214 if exclude and f.name in exclude: 

215 continue 

216 if f.name in form_declared_fields: 

217 field_dict[f.name] = form_declared_fields[f.name] 

218 continue 

219 

220 kwargs = {} 

221 if widgets and f.name in widgets: 

222 kwargs["widget"] = widgets[f.name] 

223 if localized_fields == ALL_FIELDS or ( 

224 localized_fields and f.name in localized_fields 

225 ): 

226 kwargs["localize"] = True 

227 if labels and f.name in labels: 

228 kwargs["label"] = labels[f.name] 

229 if help_texts and f.name in help_texts: 

230 kwargs["help_text"] = help_texts[f.name] 

231 if error_messages and f.name in error_messages: 

232 kwargs["error_messages"] = error_messages[f.name] 

233 if field_classes and f.name in field_classes: 

234 kwargs["form_class"] = field_classes[f.name] 

235 

236 if formfield_callback is None: 

237 formfield = f.formfield(**kwargs) 

238 elif not callable(formfield_callback): 

239 raise TypeError("formfield_callback must be a function or callable") 

240 else: 

241 formfield = formfield_callback(f, **kwargs) 

242 

243 if formfield: 

244 if apply_limit_choices_to: 

245 apply_limit_choices_to_to_formfield(formfield) 

246 field_dict[f.name] = formfield 

247 else: 

248 ignored.append(f.name) 

249 if fields: 

250 field_dict = { 

251 f: field_dict.get(f) 

252 for f in fields 

253 if (not exclude or f not in exclude) and f not in ignored 

254 } 

255 return field_dict 

256 

257 

258class ModelFormOptions: 

259 def __init__(self, options=None): 

260 self.model = getattr(options, "model", None) 

261 self.fields = getattr(options, "fields", None) 

262 self.exclude = getattr(options, "exclude", None) 

263 self.widgets = getattr(options, "widgets", None) 

264 self.localized_fields = getattr(options, "localized_fields", None) 

265 self.labels = getattr(options, "labels", None) 

266 self.help_texts = getattr(options, "help_texts", None) 

267 self.error_messages = getattr(options, "error_messages", None) 

268 self.field_classes = getattr(options, "field_classes", None) 

269 self.formfield_callback = getattr(options, "formfield_callback", None) 

270 

271 

272class ModelFormMetaclass(DeclarativeFieldsMetaclass): 

273 def __new__(mcs, name, bases, attrs): 

274 new_class = super().__new__(mcs, name, bases, attrs) 

275 

276 if bases == (BaseModelForm,): 

277 return new_class 

278 

279 opts = new_class._meta = ModelFormOptions(getattr(new_class, "Meta", None)) 

280 

281 # We check if a string was passed to `fields` or `exclude`, 

282 # which is likely to be a mistake where the user typed ('foo') instead 

283 # of ('foo',) 

284 for opt in ["fields", "exclude", "localized_fields"]: 

285 value = getattr(opts, opt) 

286 if isinstance(value, str) and value != ALL_FIELDS: 

287 msg = ( 

288 "%(model)s.Meta.%(opt)s cannot be a string. " 

289 "Did you mean to type: ('%(value)s',)?" 

290 % { 

291 "model": new_class.__name__, 

292 "opt": opt, 

293 "value": value, 

294 } 

295 ) 

296 raise TypeError(msg) 

297 

298 if opts.model: 

299 # If a model is defined, extract form fields from it. 

300 if opts.fields is None and opts.exclude is None: 

301 raise ImproperlyConfigured( 

302 "Creating a ModelForm without either the 'fields' attribute " 

303 "or the 'exclude' attribute is prohibited; form %s " 

304 "needs updating." % name 

305 ) 

306 

307 if opts.fields == ALL_FIELDS: 

308 # Sentinel for fields_for_model to indicate "get the list of 

309 # fields from the model" 

310 opts.fields = None 

311 

312 fields = fields_for_model( 

313 opts.model, 

314 opts.fields, 

315 opts.exclude, 

316 opts.widgets, 

317 opts.formfield_callback, 

318 opts.localized_fields, 

319 opts.labels, 

320 opts.help_texts, 

321 opts.error_messages, 

322 opts.field_classes, 

323 # limit_choices_to will be applied during ModelForm.__init__(). 

324 apply_limit_choices_to=False, 

325 form_declared_fields=new_class.declared_fields, 

326 ) 

327 

328 # make sure opts.fields doesn't specify an invalid field 

329 none_model_fields = {k for k, v in fields.items() if not v} 

330 missing_fields = none_model_fields.difference(new_class.declared_fields) 

331 if missing_fields: 

332 message = "Unknown field(s) (%s) specified for %s" 

333 message %= (", ".join(missing_fields), opts.model.__name__) 

334 raise FieldError(message) 

335 # Include all the other declared fields. 

336 fields.update(new_class.declared_fields) 

337 else: 

338 fields = new_class.declared_fields 

339 

340 new_class.base_fields = fields 

341 

342 return new_class 

343 

344 

345class BaseModelForm(BaseForm, AltersData): 

346 def __init__( 

347 self, 

348 data=None, 

349 files=None, 

350 auto_id="id_%s", 

351 prefix=None, 

352 initial=None, 

353 error_class=ErrorList, 

354 label_suffix=None, 

355 empty_permitted=False, 

356 instance=None, 

357 use_required_attribute=None, 

358 renderer=None, 

359 ): 

360 opts = self._meta 

361 if opts.model is None: 

362 raise ValueError("ModelForm has no model class specified.") 

363 if instance is None: 

364 # if we didn't get an instance, instantiate a new one 

365 self.instance = opts.model() 

366 object_data = {} 

367 else: 

368 self.instance = instance 

369 object_data = model_to_dict(instance, opts.fields, opts.exclude) 

370 # if initial was provided, it should override the values from instance 

371 if initial is not None: 

372 object_data.update(initial) 

373 # self._validate_unique will be set to True by BaseModelForm.clean(). 

374 # It is False by default so overriding self.clean() and failing to call 

375 # super will stop validate_unique from being called. 

376 self._validate_unique = False 

377 super().__init__( 

378 data, 

379 files, 

380 auto_id, 

381 prefix, 

382 object_data, 

383 error_class, 

384 label_suffix, 

385 empty_permitted, 

386 use_required_attribute=use_required_attribute, 

387 renderer=renderer, 

388 ) 

389 for formfield in self.fields.values(): 

390 apply_limit_choices_to_to_formfield(formfield) 

391 

392 def _get_validation_exclusions(self): 

393 """ 

394 For backwards-compatibility, exclude several types of fields from model 

395 validation. See tickets #12507, #12521, #12553. 

396 """ 

397 exclude = set() 

398 # Build up a list of fields that should be excluded from model field 

399 # validation and unique checks. 

400 for f in self.instance._meta.fields: 

401 field = f.name 

402 # Exclude fields that aren't on the form. The developer may be 

403 # adding these values to the model after form validation. 

404 if field not in self.fields: 

405 exclude.add(f.name) 

406 

407 # Don't perform model validation on fields that were defined 

408 # manually on the form and excluded via the ModelForm's Meta 

409 # class. See #12901. 

410 elif self._meta.fields and field not in self._meta.fields: 

411 exclude.add(f.name) 

412 elif self._meta.exclude and field in self._meta.exclude: 

413 exclude.add(f.name) 

414 

415 # Exclude fields that failed form validation. There's no need for 

416 # the model fields to validate them as well. 

417 elif field in self._errors: 

418 exclude.add(f.name) 

419 

420 # Exclude empty fields that are not required by the form, if the 

421 # underlying model field is required. This keeps the model field 

422 # from raising a required error. Note: don't exclude the field from 

423 # validation if the model field allows blanks. If it does, the blank 

424 # value may be included in a unique check, so cannot be excluded 

425 # from validation. 

426 else: 

427 form_field = self.fields[field] 

428 field_value = self.cleaned_data.get(field) 

429 if ( 

430 not f.blank 

431 and not form_field.required 

432 and field_value in form_field.empty_values 

433 ): 

434 exclude.add(f.name) 

435 return exclude 

436 

437 def clean(self): 

438 self._validate_unique = True 

439 return self.cleaned_data 

440 

441 def _update_errors(self, errors): 

442 # Override any validation error messages defined at the model level 

443 # with those defined at the form level. 

444 opts = self._meta 

445 

446 # Allow the model generated by construct_instance() to raise 

447 # ValidationError and have them handled in the same way as others. 

448 if hasattr(errors, "error_dict"): 

449 error_dict = errors.error_dict 

450 else: 

451 error_dict = {NON_FIELD_ERRORS: errors} 

452 

453 for field, messages in error_dict.items(): 

454 if ( 

455 field == NON_FIELD_ERRORS 

456 and opts.error_messages 

457 and NON_FIELD_ERRORS in opts.error_messages 

458 ): 

459 error_messages = opts.error_messages[NON_FIELD_ERRORS] 

460 elif field in self.fields: 

461 error_messages = self.fields[field].error_messages 

462 else: 

463 continue 

464 

465 for message in messages: 

466 if ( 

467 isinstance(message, ValidationError) 

468 and message.code in error_messages 

469 ): 

470 message.message = error_messages[message.code] 

471 

472 self.add_error(None, errors) 

473 

474 def _post_clean(self): 

475 opts = self._meta 

476 

477 exclude = self._get_validation_exclusions() 

478 

479 # Foreign Keys being used to represent inline relationships 

480 # are excluded from basic field value validation. This is for two 

481 # reasons: firstly, the value may not be supplied (#12507; the 

482 # case of providing new values to the admin); secondly the 

483 # object being referred to may not yet fully exist (#12749). 

484 # However, these fields *must* be included in uniqueness checks, 

485 # so this can't be part of _get_validation_exclusions(). 

486 for name, field in self.fields.items(): 

487 if isinstance(field, InlineForeignKeyField): 

488 exclude.add(name) 

489 

490 try: 

491 self.instance = construct_instance( 

492 self, self.instance, opts.fields, opts.exclude 

493 ) 

494 except ValidationError as e: 

495 self._update_errors(e) 

496 

497 try: 

498 self.instance.full_clean(exclude=exclude, validate_unique=False) 

499 except ValidationError as e: 

500 self._update_errors(e) 

501 

502 # Validate uniqueness if needed. 

503 if self._validate_unique: 

504 self.validate_unique() 

505 

506 def validate_unique(self): 

507 """ 

508 Call the instance's validate_unique() method and update the form's 

509 validation errors if any were raised. 

510 """ 

511 exclude = self._get_validation_exclusions() 

512 try: 

513 self.instance.validate_unique(exclude=exclude) 

514 except ValidationError as e: 

515 self._update_errors(e) 

516 

517 def _save_m2m(self): 

518 """ 

519 Save the many-to-many fields and generic relations for this form. 

520 """ 

521 cleaned_data = self.cleaned_data 

522 exclude = self._meta.exclude 

523 fields = self._meta.fields 

524 opts = self.instance._meta 

525 # Note that for historical reasons we want to include also 

526 # private_fields here. (GenericRelation was previously a fake 

527 # m2m field). 

528 for f in chain(opts.many_to_many, opts.private_fields): 

529 if not hasattr(f, "save_form_data"): 

530 continue 

531 if fields and f.name not in fields: 

532 continue 

533 if exclude and f.name in exclude: 

534 continue 

535 if f.name in cleaned_data: 

536 f.save_form_data(self.instance, cleaned_data[f.name]) 

537 

538 def save(self, commit=True): 

539 """ 

540 Save this form's self.instance object if commit=True. Otherwise, add 

541 a save_m2m() method to the form which can be called after the instance 

542 is saved manually at a later time. Return the model instance. 

543 """ 

544 if self.errors: 

545 raise ValueError( 

546 "The %s could not be %s because the data didn't validate." 

547 % ( 

548 self.instance._meta.object_name, 

549 "created" if self.instance._state.adding else "changed", 

550 ) 

551 ) 

552 if commit: 

553 # If committing, save the instance and the m2m data immediately. 

554 self.instance.save() 

555 self._save_m2m() 

556 else: 

557 # If not committing, add a method to the form to allow deferred 

558 # saving of m2m data. 

559 self.save_m2m = self._save_m2m 

560 return self.instance 

561 

562 save.alters_data = True 

563 

564 

565class ModelForm(BaseModelForm, metaclass=ModelFormMetaclass): 

566 pass 

567 

568 

569def modelform_factory( 

570 model, 

571 form=ModelForm, 

572 fields=None, 

573 exclude=None, 

574 formfield_callback=None, 

575 widgets=None, 

576 localized_fields=None, 

577 labels=None, 

578 help_texts=None, 

579 error_messages=None, 

580 field_classes=None, 

581): 

582 """ 

583 Return a ModelForm containing form fields for the given model. You can 

584 optionally pass a `form` argument to use as a starting point for 

585 constructing the ModelForm. 

586 

587 ``fields`` is an optional list of field names. If provided, include only 

588 the named fields in the returned fields. If omitted or '__all__', use all 

589 fields. 

590 

591 ``exclude`` is an optional list of field names. If provided, exclude the 

592 named fields from the returned fields, even if they are listed in the 

593 ``fields`` argument. 

594 

595 ``widgets`` is a dictionary of model field names mapped to a widget. 

596 

597 ``localized_fields`` is a list of names of fields which should be localized. 

598 

599 ``formfield_callback`` is a callable that takes a model field and returns 

600 a form field. 

601 

602 ``labels`` is a dictionary of model field names mapped to a label. 

603 

604 ``help_texts`` is a dictionary of model field names mapped to a help text. 

605 

606 ``error_messages`` is a dictionary of model field names mapped to a 

607 dictionary of error messages. 

608 

609 ``field_classes`` is a dictionary of model field names mapped to a form 

610 field class. 

611 """ 

612 # Create the inner Meta class. FIXME: ideally, we should be able to 

613 # construct a ModelForm without creating and passing in a temporary 

614 # inner class. 

615 

616 # Build up a list of attributes that the Meta object will have. 

617 attrs = {"model": model} 

618 if fields is not None: 

619 attrs["fields"] = fields 

620 if exclude is not None: 

621 attrs["exclude"] = exclude 

622 if widgets is not None: 

623 attrs["widgets"] = widgets 

624 if localized_fields is not None: 

625 attrs["localized_fields"] = localized_fields 

626 if labels is not None: 

627 attrs["labels"] = labels 

628 if help_texts is not None: 

629 attrs["help_texts"] = help_texts 

630 if error_messages is not None: 

631 attrs["error_messages"] = error_messages 

632 if field_classes is not None: 

633 attrs["field_classes"] = field_classes 

634 

635 # If parent form class already has an inner Meta, the Meta we're 

636 # creating needs to inherit from the parent's inner meta. 

637 bases = (form.Meta,) if hasattr(form, "Meta") else () 

638 Meta = type("Meta", bases, attrs) 

639 if formfield_callback: 

640 Meta.formfield_callback = staticmethod(formfield_callback) 

641 # Give this new form class a reasonable name. 

642 class_name = model.__name__ + "Form" 

643 

644 # Class attributes for the new form class. 

645 form_class_attrs = {"Meta": Meta} 

646 

647 if getattr(Meta, "fields", None) is None and getattr(Meta, "exclude", None) is None: 

648 raise ImproperlyConfigured( 

649 "Calling modelform_factory without defining 'fields' or " 

650 "'exclude' explicitly is prohibited." 

651 ) 

652 

653 # Instantiate type(form) in order to use the same metaclass as form. 

654 return type(form)(class_name, (form,), form_class_attrs) 

655 

656 

657# ModelFormSets ############################################################## 

658 

659 

660class BaseModelFormSet(BaseFormSet, AltersData): 

661 """ 

662 A ``FormSet`` for editing a queryset and/or adding new objects to it. 

663 """ 

664 

665 model = None 

666 edit_only = False 

667 

668 # Set of fields that must be unique among forms of this set. 

669 unique_fields = set() 

670 

671 def __init__( 

672 self, 

673 data=None, 

674 files=None, 

675 auto_id="id_%s", 

676 prefix=None, 

677 queryset=None, 

678 *, 

679 initial=None, 

680 **kwargs, 

681 ): 

682 self.queryset = queryset 

683 self.initial_extra = initial 

684 super().__init__( 

685 **{ 

686 "data": data, 

687 "files": files, 

688 "auto_id": auto_id, 

689 "prefix": prefix, 

690 **kwargs, 

691 } 

692 ) 

693 

694 def initial_form_count(self): 

695 """Return the number of forms that are required in this FormSet.""" 

696 if not self.is_bound: 

697 return len(self.get_queryset()) 

698 return super().initial_form_count() 

699 

700 def _existing_object(self, pk): 

701 if not hasattr(self, "_object_dict"): 

702 self._object_dict = {o.pk: o for o in self.get_queryset()} 

703 return self._object_dict.get(pk) 

704 

705 def _get_to_python(self, field): 

706 """ 

707 If the field is a related field, fetch the concrete field's (that 

708 is, the ultimate pointed-to field's) to_python. 

709 """ 

710 while field.remote_field is not None: 

711 field = field.remote_field.get_related_field() 

712 return field.to_python 

713 

714 def _construct_form(self, i, **kwargs): 

715 pk_required = i < self.initial_form_count() 

716 if pk_required: 

717 if self.is_bound: 

718 pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) 

719 try: 

720 pk = self.data[pk_key] 

721 except KeyError: 

722 # The primary key is missing. The user may have tampered 

723 # with POST data. 

724 pass 

725 else: 

726 to_python = self._get_to_python(self.model._meta.pk) 

727 try: 

728 pk = to_python(pk) 

729 except ValidationError: 

730 # The primary key exists but is an invalid value. The 

731 # user may have tampered with POST data. 

732 pass 

733 else: 

734 kwargs["instance"] = self._existing_object(pk) 

735 else: 

736 kwargs["instance"] = self.get_queryset()[i] 

737 elif self.initial_extra: 

738 # Set initial values for extra forms 

739 try: 

740 kwargs["initial"] = self.initial_extra[i - self.initial_form_count()] 

741 except IndexError: 

742 pass 

743 form = super()._construct_form(i, **kwargs) 

744 if pk_required: 

745 form.fields[self.model._meta.pk.name].required = True 

746 return form 

747 

748 def get_queryset(self): 

749 if not hasattr(self, "_queryset"): 

750 if self.queryset is not None: 

751 qs = self.queryset 

752 else: 

753 qs = self.model._default_manager.get_queryset() 

754 

755 # If the queryset isn't already ordered we need to add an 

756 # artificial ordering here to make sure that all formsets 

757 # constructed from this queryset have the same form order. 

758 if not qs.ordered: 

759 qs = qs.order_by(self.model._meta.pk.name) 

760 

761 # Removed queryset limiting here. As per discussion re: #13023 

762 # on django-dev, max_num should not prevent existing 

763 # related objects/inlines from being displayed. 

764 self._queryset = qs 

765 return self._queryset 

766 

767 def save_new(self, form, commit=True): 

768 """Save and return a new model instance for the given form.""" 

769 return form.save(commit=commit) 

770 

771 def save_existing(self, form, obj, commit=True): 

772 """Save and return an existing model instance for the given form.""" 

773 return form.save(commit=commit) 

774 

775 def delete_existing(self, obj, commit=True): 

776 """Deletes an existing model instance.""" 

777 if commit: 

778 obj.delete() 

779 

780 def save(self, commit=True): 

781 """ 

782 Save model instances for every form, adding and changing instances 

783 as necessary, and return the list of instances. 

784 """ 

785 if not commit: 

786 self.saved_forms = [] 

787 

788 def save_m2m(): 

789 for form in self.saved_forms: 

790 form.save_m2m() 

791 

792 self.save_m2m = save_m2m 

793 if self.edit_only: 

794 return self.save_existing_objects(commit) 

795 else: 

796 return self.save_existing_objects(commit) + self.save_new_objects(commit) 

797 

798 save.alters_data = True 

799 

800 def clean(self): 

801 self.validate_unique() 

802 

803 def validate_unique(self): 

804 # Collect unique_checks and date_checks to run from all the forms. 

805 all_unique_checks = set() 

806 all_date_checks = set() 

807 forms_to_delete = self.deleted_forms 

808 valid_forms = [ 

809 form 

810 for form in self.forms 

811 if form.is_valid() and form not in forms_to_delete 

812 ] 

813 for form in valid_forms: 

814 exclude = form._get_validation_exclusions() 

815 unique_checks, date_checks = form.instance._get_unique_checks( 

816 exclude=exclude, 

817 include_meta_constraints=True, 

818 ) 

819 all_unique_checks.update(unique_checks) 

820 all_date_checks.update(date_checks) 

821 

822 errors = [] 

823 # Do each of the unique checks (unique and unique_together) 

824 for uclass, unique_check in all_unique_checks: 

825 seen_data = set() 

826 for form in valid_forms: 

827 # Get the data for the set of fields that must be unique among 

828 # the forms. 

829 row_data = ( 

830 field if field in self.unique_fields else form.cleaned_data[field] 

831 for field in unique_check 

832 if field in form.cleaned_data 

833 ) 

834 # Reduce Model instances to their primary key values 

835 row_data = tuple( 

836 ( 

837 d._get_pk_val() 

838 if hasattr(d, "_get_pk_val") 

839 # Prevent "unhashable type" errors later on. 

840 else make_hashable(d) 

841 ) 

842 for d in row_data 

843 ) 

844 if row_data and None not in row_data: 

845 # if we've already seen it then we have a uniqueness failure 

846 if row_data in seen_data: 

847 # poke error messages into the right places and mark 

848 # the form as invalid 

849 errors.append(self.get_unique_error_message(unique_check)) 

850 form._errors[NON_FIELD_ERRORS] = self.error_class( 

851 [self.get_form_error()], 

852 renderer=self.renderer, 

853 ) 

854 # Remove the data from the cleaned_data dict since it 

855 # was invalid. 

856 for field in unique_check: 

857 if field in form.cleaned_data: 

858 del form.cleaned_data[field] 

859 # mark the data as seen 

860 seen_data.add(row_data) 

861 # iterate over each of the date checks now 

862 for date_check in all_date_checks: 

863 seen_data = set() 

864 uclass, lookup, field, unique_for = date_check 

865 for form in valid_forms: 

866 # see if we have data for both fields 

867 if ( 

868 form.cleaned_data 

869 and form.cleaned_data[field] is not None 

870 and form.cleaned_data[unique_for] is not None 

871 ): 

872 # if it's a date lookup we need to get the data for all the fields 

873 if lookup == "date": 

874 date = form.cleaned_data[unique_for] 

875 date_data = (date.year, date.month, date.day) 

876 # otherwise it's just the attribute on the date/datetime 

877 # object 

878 else: 

879 date_data = (getattr(form.cleaned_data[unique_for], lookup),) 

880 data = (form.cleaned_data[field],) + date_data 

881 # if we've already seen it then we have a uniqueness failure 

882 if data in seen_data: 

883 # poke error messages into the right places and mark 

884 # the form as invalid 

885 errors.append(self.get_date_error_message(date_check)) 

886 form._errors[NON_FIELD_ERRORS] = self.error_class( 

887 [self.get_form_error()], 

888 renderer=self.renderer, 

889 ) 

890 # Remove the data from the cleaned_data dict since it 

891 # was invalid. 

892 del form.cleaned_data[field] 

893 # mark the data as seen 

894 seen_data.add(data) 

895 

896 if errors: 

897 raise ValidationError(errors) 

898 

899 def get_unique_error_message(self, unique_check): 

900 if len(unique_check) == 1: 

901 return gettext("Please correct the duplicate data for %(field)s.") % { 

902 "field": unique_check[0], 

903 } 

904 else: 

905 return gettext( 

906 "Please correct the duplicate data for %(field)s, which must be unique." 

907 ) % { 

908 "field": get_text_list(unique_check, _("and")), 

909 } 

910 

911 def get_date_error_message(self, date_check): 

912 return gettext( 

913 "Please correct the duplicate data for %(field_name)s " 

914 "which must be unique for the %(lookup)s in %(date_field)s." 

915 ) % { 

916 "field_name": date_check[2], 

917 "date_field": date_check[3], 

918 "lookup": str(date_check[1]), 

919 } 

920 

921 def get_form_error(self): 

922 return gettext("Please correct the duplicate values below.") 

923 

924 def save_existing_objects(self, commit=True): 

925 self.changed_objects = [] 

926 self.deleted_objects = [] 

927 if not self.initial_forms: 

928 return [] 

929 

930 saved_instances = [] 

931 forms_to_delete = self.deleted_forms 

932 for form in self.initial_forms: 

933 obj = form.instance 

934 # If the pk is None, it means either: 

935 # 1. The object is an unexpected empty model, created by invalid 

936 # POST data such as an object outside the formset's queryset. 

937 # 2. The object was already deleted from the database. 

938 if not obj._is_pk_set(): 

939 continue 

940 if form in forms_to_delete: 

941 self.deleted_objects.append(obj) 

942 self.delete_existing(obj, commit=commit) 

943 elif form.has_changed(): 

944 self.changed_objects.append((obj, form.changed_data)) 

945 saved_instances.append(self.save_existing(form, obj, commit=commit)) 

946 if not commit: 

947 self.saved_forms.append(form) 

948 return saved_instances 

949 

950 def save_new_objects(self, commit=True): 

951 self.new_objects = [] 

952 for form in self.extra_forms: 

953 if not form.has_changed(): 

954 continue 

955 # If someone has marked an add form for deletion, don't save the 

956 # object. 

957 if self.can_delete and self._should_delete_form(form): 

958 continue 

959 self.new_objects.append(self.save_new(form, commit=commit)) 

960 if not commit: 

961 self.saved_forms.append(form) 

962 return self.new_objects 

963 

964 def add_fields(self, form, index): 

965 """Add a hidden field for the object's primary key.""" 

966 from django.db.models import AutoField, ForeignKey, OneToOneField 

967 

968 self._pk_field = pk = self.model._meta.pk 

969 # If a pk isn't editable, then it won't be on the form, so we need to 

970 # add it here so we can tell which object is which when we get the 

971 # data back. Generally, pk.editable should be false, but for some 

972 # reason, auto_created pk fields and AutoField's editable attribute is 

973 # True, so check for that as well. 

974 

975 def pk_is_not_editable(pk): 

976 return ( 

977 (not pk.editable) 

978 or (pk.auto_created or isinstance(pk, AutoField)) 

979 or ( 

980 pk.remote_field 

981 and pk.remote_field.parent_link 

982 and pk_is_not_editable(pk.remote_field.model._meta.pk) 

983 ) 

984 ) 

985 

986 if pk_is_not_editable(pk) or pk.name not in form.fields: 

987 if form.is_bound: 

988 # If we're adding the related instance, ignore its primary key 

989 # as it could be an auto-generated default which isn't actually 

990 # in the database. 

991 pk_value = None if form.instance._state.adding else form.instance.pk 

992 else: 

993 try: 

994 if index is not None: 

995 pk_value = self.get_queryset()[index].pk 

996 else: 

997 pk_value = None 

998 except IndexError: 

999 pk_value = None 

1000 if isinstance(pk, (ForeignKey, OneToOneField)): 

1001 qs = pk.remote_field.model._default_manager.get_queryset() 

1002 else: 

1003 qs = self.model._default_manager.get_queryset() 

1004 qs = qs.using(form.instance._state.db) 

1005 if form._meta.widgets: 

1006 widget = form._meta.widgets.get(self._pk_field.name, HiddenInput) 

1007 else: 

1008 widget = HiddenInput 

1009 form.fields[self._pk_field.name] = ModelChoiceField( 

1010 qs, initial=pk_value, required=False, widget=widget 

1011 ) 

1012 super().add_fields(form, index) 

1013 

1014 

1015def modelformset_factory( 

1016 model, 

1017 form=ModelForm, 

1018 formfield_callback=None, 

1019 formset=BaseModelFormSet, 

1020 extra=1, 

1021 can_delete=False, 

1022 can_order=False, 

1023 max_num=None, 

1024 fields=None, 

1025 exclude=None, 

1026 widgets=None, 

1027 validate_max=False, 

1028 localized_fields=None, 

1029 labels=None, 

1030 help_texts=None, 

1031 error_messages=None, 

1032 min_num=None, 

1033 validate_min=False, 

1034 field_classes=None, 

1035 absolute_max=None, 

1036 can_delete_extra=True, 

1037 renderer=None, 

1038 edit_only=False, 

1039): 

1040 """Return a FormSet class for the given Django model class.""" 

1041 meta = getattr(form, "Meta", None) 

1042 if ( 

1043 getattr(meta, "fields", fields) is None 

1044 and getattr(meta, "exclude", exclude) is None 

1045 ): 

1046 raise ImproperlyConfigured( 

1047 "Calling modelformset_factory without defining 'fields' or " 

1048 "'exclude' explicitly is prohibited." 

1049 ) 

1050 

1051 form = modelform_factory( 

1052 model, 

1053 form=form, 

1054 fields=fields, 

1055 exclude=exclude, 

1056 formfield_callback=formfield_callback, 

1057 widgets=widgets, 

1058 localized_fields=localized_fields, 

1059 labels=labels, 

1060 help_texts=help_texts, 

1061 error_messages=error_messages, 

1062 field_classes=field_classes, 

1063 ) 

1064 FormSet = formset_factory( 

1065 form, 

1066 formset, 

1067 extra=extra, 

1068 min_num=min_num, 

1069 max_num=max_num, 

1070 can_order=can_order, 

1071 can_delete=can_delete, 

1072 validate_min=validate_min, 

1073 validate_max=validate_max, 

1074 absolute_max=absolute_max, 

1075 can_delete_extra=can_delete_extra, 

1076 renderer=renderer, 

1077 ) 

1078 FormSet.model = model 

1079 FormSet.edit_only = edit_only 

1080 return FormSet 

1081 

1082 

1083# InlineFormSets ############################################################# 

1084 

1085 

1086class BaseInlineFormSet(BaseModelFormSet): 

1087 """A formset for child objects related to a parent.""" 

1088 

1089 def __init__( 

1090 self, 

1091 data=None, 

1092 files=None, 

1093 instance=None, 

1094 save_as_new=False, 

1095 prefix=None, 

1096 queryset=None, 

1097 **kwargs, 

1098 ): 

1099 if instance is None: 

1100 self.instance = self.fk.remote_field.model() 

1101 else: 

1102 self.instance = instance 

1103 self.save_as_new = save_as_new 

1104 if queryset is None: 

1105 queryset = self.model._default_manager 

1106 if self.instance._is_pk_set(): 

1107 qs = queryset.filter(**{self.fk.name: self.instance}) 

1108 else: 

1109 qs = queryset.none() 

1110 self.unique_fields = {self.fk.name} 

1111 super().__init__(data, files, prefix=prefix, queryset=qs, **kwargs) 

1112 

1113 # Add the generated field to form._meta.fields if it's defined to make 

1114 # sure validation isn't skipped on that field. 

1115 if self.form._meta.fields and self.fk.name not in self.form._meta.fields: 

1116 if isinstance(self.form._meta.fields, tuple): 

1117 self.form._meta.fields = list(self.form._meta.fields) 

1118 self.form._meta.fields.append(self.fk.name) 

1119 

1120 def initial_form_count(self): 

1121 if self.save_as_new: 

1122 return 0 

1123 return super().initial_form_count() 

1124 

1125 def _construct_form(self, i, **kwargs): 

1126 form = super()._construct_form(i, **kwargs) 

1127 if self.save_as_new: 

1128 mutable = getattr(form.data, "_mutable", None) 

1129 # Allow modifying an immutable QueryDict. 

1130 if mutable is not None: 

1131 form.data._mutable = True 

1132 # Remove the primary key from the form's data, we are only 

1133 # creating new instances 

1134 form.data[form.add_prefix(self._pk_field.name)] = None 

1135 # Remove the foreign key from the form's data 

1136 form.data[form.add_prefix(self.fk.name)] = None 

1137 if mutable is not None: 

1138 form.data._mutable = mutable 

1139 

1140 # Set the fk value here so that the form can do its validation. 

1141 fk_value = self.instance.pk 

1142 if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: 

1143 fk_value = getattr(self.instance, self.fk.remote_field.field_name) 

1144 fk_value = getattr(fk_value, "pk", fk_value) 

1145 setattr(form.instance, self.fk.attname, fk_value) 

1146 return form 

1147 

1148 @classmethod 

1149 def get_default_prefix(cls): 

1150 return cls.fk.remote_field.get_accessor_name(model=cls.model).replace("+", "") 

1151 

1152 def save_new(self, form, commit=True): 

1153 # Ensure the latest copy of the related instance is present on each 

1154 # form (it may have been saved after the formset was originally 

1155 # instantiated). 

1156 setattr(form.instance, self.fk.name, self.instance) 

1157 return super().save_new(form, commit=commit) 

1158 

1159 def add_fields(self, form, index): 

1160 super().add_fields(form, index) 

1161 if self._pk_field == self.fk: 

1162 name = self._pk_field.name 

1163 kwargs = {"pk_field": True} 

1164 else: 

1165 # The foreign key field might not be on the form, so we poke at the 

1166 # Model field to get the label, since we need that for error messages. 

1167 name = self.fk.name 

1168 kwargs = { 

1169 "label": getattr( 

1170 form.fields.get(name), "label", capfirst(self.fk.verbose_name) 

1171 ) 

1172 } 

1173 

1174 # The InlineForeignKeyField assumes that the foreign key relation is 

1175 # based on the parent model's pk. If this isn't the case, set to_field 

1176 # to correctly resolve the initial form value. 

1177 if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: 

1178 kwargs["to_field"] = self.fk.remote_field.field_name 

1179 

1180 # If we're adding a new object, ignore a parent's auto-generated key 

1181 # as it will be regenerated on the save request. 

1182 if self.instance._state.adding: 

1183 if kwargs.get("to_field") is not None: 

1184 to_field = self.instance._meta.get_field(kwargs["to_field"]) 

1185 else: 

1186 to_field = self.instance._meta.pk 

1187 

1188 if to_field.has_default() and ( 

1189 # Don't ignore a parent's auto-generated key if it's not the 

1190 # parent model's pk and form data is provided. 

1191 to_field.attname == self.fk.remote_field.model._meta.pk.name 

1192 or not form.data 

1193 ): 

1194 setattr(self.instance, to_field.attname, None) 

1195 

1196 form.fields[name] = InlineForeignKeyField(self.instance, **kwargs) 

1197 

1198 def get_unique_error_message(self, unique_check): 

1199 unique_check = [field for field in unique_check if field != self.fk.name] 

1200 return super().get_unique_error_message(unique_check) 

1201 

1202 

1203def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False): 

1204 """ 

1205 Find and return the ForeignKey from model to parent if there is one 

1206 (return None if can_fail is True and no such field exists). If fk_name is 

1207 provided, assume it is the name of the ForeignKey field. Unless can_fail is 

1208 True, raise an exception if there isn't a ForeignKey from model to 

1209 parent_model. 

1210 """ 

1211 # avoid circular import 

1212 from django.db.models import ForeignKey 

1213 

1214 opts = model._meta 

1215 if fk_name: 

1216 fks_to_parent = [f for f in opts.fields if f.name == fk_name] 

1217 if len(fks_to_parent) == 1: 

1218 fk = fks_to_parent[0] 

1219 all_parents = (*parent_model._meta.all_parents, parent_model) 

1220 if ( 

1221 not isinstance(fk, ForeignKey) 

1222 or ( 

1223 # ForeignKey to proxy models. 

1224 fk.remote_field.model._meta.proxy 

1225 and fk.remote_field.model._meta.proxy_for_model not in all_parents 

1226 ) 

1227 or ( 

1228 # ForeignKey to concrete models. 

1229 not fk.remote_field.model._meta.proxy 

1230 and fk.remote_field.model != parent_model 

1231 and fk.remote_field.model not in all_parents 

1232 ) 

1233 ): 

1234 raise ValueError( 

1235 "fk_name '%s' is not a ForeignKey to '%s'." 

1236 % (fk_name, parent_model._meta.label) 

1237 ) 

1238 elif not fks_to_parent: 

1239 raise ValueError( 

1240 "'%s' has no field named '%s'." % (model._meta.label, fk_name) 

1241 ) 

1242 else: 

1243 # Try to discover what the ForeignKey from model to parent_model is 

1244 all_parents = (*parent_model._meta.all_parents, parent_model) 

1245 fks_to_parent = [ 

1246 f 

1247 for f in opts.fields 

1248 if isinstance(f, ForeignKey) 

1249 and ( 

1250 f.remote_field.model == parent_model 

1251 or f.remote_field.model in all_parents 

1252 or ( 

1253 f.remote_field.model._meta.proxy 

1254 and f.remote_field.model._meta.proxy_for_model in all_parents 

1255 ) 

1256 ) 

1257 ] 

1258 if len(fks_to_parent) == 1: 

1259 fk = fks_to_parent[0] 

1260 elif not fks_to_parent: 

1261 if can_fail: 

1262 return 

1263 raise ValueError( 

1264 "'%s' has no ForeignKey to '%s'." 

1265 % ( 

1266 model._meta.label, 

1267 parent_model._meta.label, 

1268 ) 

1269 ) 

1270 else: 

1271 raise ValueError( 

1272 "'%s' has more than one ForeignKey to '%s'. You must specify " 

1273 "a 'fk_name' attribute." 

1274 % ( 

1275 model._meta.label, 

1276 parent_model._meta.label, 

1277 ) 

1278 ) 

1279 return fk 

1280 

1281 

1282def inlineformset_factory( 

1283 parent_model, 

1284 model, 

1285 form=ModelForm, 

1286 formset=BaseInlineFormSet, 

1287 fk_name=None, 

1288 fields=None, 

1289 exclude=None, 

1290 extra=3, 

1291 can_order=False, 

1292 can_delete=True, 

1293 max_num=None, 

1294 formfield_callback=None, 

1295 widgets=None, 

1296 validate_max=False, 

1297 localized_fields=None, 

1298 labels=None, 

1299 help_texts=None, 

1300 error_messages=None, 

1301 min_num=None, 

1302 validate_min=False, 

1303 field_classes=None, 

1304 absolute_max=None, 

1305 can_delete_extra=True, 

1306 renderer=None, 

1307 edit_only=False, 

1308): 

1309 """ 

1310 Return an ``InlineFormSet`` for the given kwargs. 

1311 

1312 ``fk_name`` must be provided if ``model`` has more than one ``ForeignKey`` 

1313 to ``parent_model``. 

1314 """ 

1315 fk = _get_foreign_key(parent_model, model, fk_name=fk_name) 

1316 # enforce a max_num=1 when the foreign key to the parent model is unique. 

1317 if fk.unique: 

1318 max_num = 1 

1319 kwargs = { 

1320 "form": form, 

1321 "formfield_callback": formfield_callback, 

1322 "formset": formset, 

1323 "extra": extra, 

1324 "can_delete": can_delete, 

1325 "can_order": can_order, 

1326 "fields": fields, 

1327 "exclude": exclude, 

1328 "min_num": min_num, 

1329 "max_num": max_num, 

1330 "widgets": widgets, 

1331 "validate_min": validate_min, 

1332 "validate_max": validate_max, 

1333 "localized_fields": localized_fields, 

1334 "labels": labels, 

1335 "help_texts": help_texts, 

1336 "error_messages": error_messages, 

1337 "field_classes": field_classes, 

1338 "absolute_max": absolute_max, 

1339 "can_delete_extra": can_delete_extra, 

1340 "renderer": renderer, 

1341 "edit_only": edit_only, 

1342 } 

1343 FormSet = modelformset_factory(model, **kwargs) 

1344 FormSet.fk = fk 

1345 return FormSet 

1346 

1347 

1348# Fields ##################################################################### 

1349 

1350 

1351class InlineForeignKeyField(Field): 

1352 """ 

1353 A basic integer field that deals with validating the given value to a 

1354 given parent instance in an inline. 

1355 """ 

1356 

1357 widget = HiddenInput 

1358 default_error_messages = { 

1359 "invalid_choice": _("The inline value did not match the parent instance."), 

1360 } 

1361 

1362 def __init__(self, parent_instance, *args, pk_field=False, to_field=None, **kwargs): 

1363 self.parent_instance = parent_instance 

1364 self.pk_field = pk_field 

1365 self.to_field = to_field 

1366 if self.parent_instance is not None: 

1367 if self.to_field: 

1368 kwargs["initial"] = getattr(self.parent_instance, self.to_field) 

1369 else: 

1370 kwargs["initial"] = self.parent_instance.pk 

1371 kwargs["required"] = False 

1372 super().__init__(*args, **kwargs) 

1373 

1374 def clean(self, value): 

1375 if value in self.empty_values: 

1376 if self.pk_field: 

1377 return None 

1378 # if there is no value act as we did before. 

1379 return self.parent_instance 

1380 # ensure the we compare the values as equal types. 

1381 if self.to_field: 

1382 orig = getattr(self.parent_instance, self.to_field) 

1383 else: 

1384 orig = self.parent_instance.pk 

1385 if str(value) != str(orig): 

1386 raise ValidationError( 

1387 self.error_messages["invalid_choice"], code="invalid_choice" 

1388 ) 

1389 return self.parent_instance 

1390 

1391 def has_changed(self, initial, data): 

1392 return False 

1393 

1394 

1395class ModelChoiceIteratorValue: 

1396 def __init__(self, value, instance): 

1397 self.value = value 

1398 self.instance = instance 

1399 

1400 def __str__(self): 

1401 return str(self.value) 

1402 

1403 def __hash__(self): 

1404 return hash(self.value) 

1405 

1406 def __eq__(self, other): 

1407 if isinstance(other, ModelChoiceIteratorValue): 

1408 other = other.value 

1409 return self.value == other 

1410 

1411 

1412class ModelChoiceIterator(BaseChoiceIterator): 

1413 def __init__(self, field): 

1414 self.field = field 

1415 self.queryset = field.queryset 

1416 

1417 def __iter__(self): 

1418 if self.field.empty_label is not None: 

1419 yield ("", self.field.empty_label) 

1420 queryset = self.queryset 

1421 # Can't use iterator() when queryset uses prefetch_related() 

1422 if not queryset._prefetch_related_lookups: 

1423 queryset = queryset.iterator() 

1424 for obj in queryset: 

1425 yield self.choice(obj) 

1426 

1427 def __len__(self): 

1428 # count() adds a query but uses less memory since the QuerySet results 

1429 # won't be cached. In most cases, the choices will only be iterated on, 

1430 # and __len__() won't be called. 

1431 return self.queryset.count() + (1 if self.field.empty_label is not None else 0) 

1432 

1433 def __bool__(self): 

1434 return self.field.empty_label is not None or self.queryset.exists() 

1435 

1436 def choice(self, obj): 

1437 return ( 

1438 ModelChoiceIteratorValue(self.field.prepare_value(obj), obj), 

1439 self.field.label_from_instance(obj), 

1440 ) 

1441 

1442 

1443class ModelChoiceField(ChoiceField): 

1444 """A ChoiceField whose choices are a model QuerySet.""" 

1445 

1446 # This class is a subclass of ChoiceField for purity, but it doesn't 

1447 # actually use any of ChoiceField's implementation. 

1448 default_error_messages = { 

1449 "invalid_choice": _( 

1450 "Select a valid choice. That choice is not one of the available choices." 

1451 ), 

1452 } 

1453 iterator = ModelChoiceIterator 

1454 

1455 def __init__( 

1456 self, 

1457 queryset, 

1458 *, 

1459 empty_label="---------", 

1460 required=True, 

1461 widget=None, 

1462 label=None, 

1463 initial=None, 

1464 help_text="", 

1465 to_field_name=None, 

1466 limit_choices_to=None, 

1467 blank=False, 

1468 **kwargs, 

1469 ): 

1470 # Call Field instead of ChoiceField __init__() because we don't need 

1471 # ChoiceField.__init__(). 

1472 Field.__init__( 

1473 self, 

1474 required=required, 

1475 widget=widget, 

1476 label=label, 

1477 initial=initial, 

1478 help_text=help_text, 

1479 **kwargs, 

1480 ) 

1481 if (required and initial is not None) or ( 

1482 isinstance(self.widget, RadioSelect) and not blank 

1483 ): 

1484 self.empty_label = None 

1485 else: 

1486 self.empty_label = empty_label 

1487 self.queryset = queryset 

1488 self.limit_choices_to = limit_choices_to # limit the queryset later. 

1489 self.to_field_name = to_field_name 

1490 

1491 def validate_no_null_characters(self, value): 

1492 non_null_character_validator = ProhibitNullCharactersValidator() 

1493 return non_null_character_validator(value) 

1494 

1495 def get_limit_choices_to(self): 

1496 """ 

1497 Return ``limit_choices_to`` for this form field. 

1498 

1499 If it is a callable, invoke it and return the result. 

1500 """ 

1501 if callable(self.limit_choices_to): 

1502 return self.limit_choices_to() 

1503 return self.limit_choices_to 

1504 

1505 def __deepcopy__(self, memo): 

1506 result = super(ChoiceField, self).__deepcopy__(memo) 

1507 # Need to force a new ModelChoiceIterator to be created, bug #11183 

1508 if self.queryset is not None: 

1509 result.queryset = self.queryset.all() 

1510 return result 

1511 

1512 def _get_queryset(self): 

1513 return self._queryset 

1514 

1515 def _set_queryset(self, queryset): 

1516 self._queryset = None if queryset is None else queryset.all() 

1517 self.widget.choices = self.choices 

1518 

1519 queryset = property(_get_queryset, _set_queryset) 

1520 

1521 # this method will be used to create object labels by the QuerySetIterator. 

1522 # Override it to customize the label. 

1523 def label_from_instance(self, obj): 

1524 """ 

1525 Convert objects into strings and generate the labels for the choices 

1526 presented by this object. Subclasses can override this method to 

1527 customize the display of the choices. 

1528 """ 

1529 return str(obj) 

1530 

1531 def _get_choices(self): 

1532 # If self._choices is set, then somebody must have manually set 

1533 # the property self.choices. In this case, just return self._choices. 

1534 if hasattr(self, "_choices"): 

1535 return self._choices 

1536 

1537 # Otherwise, execute the QuerySet in self.queryset to determine the 

1538 # choices dynamically. Return a fresh ModelChoiceIterator that has not been 

1539 # consumed. Note that we're instantiating a new ModelChoiceIterator *each* 

1540 # time _get_choices() is called (and, thus, each time self.choices is 

1541 # accessed) so that we can ensure the QuerySet has not been consumed. This 

1542 # construct might look complicated but it allows for lazy evaluation of 

1543 # the queryset. 

1544 return self.iterator(self) 

1545 

1546 choices = property(_get_choices, ChoiceField.choices.fset) 

1547 

1548 def prepare_value(self, value): 

1549 if hasattr(value, "_meta"): 

1550 if self.to_field_name: 

1551 return value.serializable_value(self.to_field_name) 

1552 else: 

1553 return value.pk 

1554 return super().prepare_value(value) 

1555 

1556 def to_python(self, value): 

1557 if value in self.empty_values: 

1558 return None 

1559 self.validate_no_null_characters(value) 

1560 try: 

1561 key = self.to_field_name or "pk" 

1562 if isinstance(value, self.queryset.model): 

1563 value = getattr(value, key) 

1564 value = self.queryset.get(**{key: value}) 

1565 except (ValueError, TypeError, self.queryset.model.DoesNotExist): 

1566 raise ValidationError( 

1567 self.error_messages["invalid_choice"], 

1568 code="invalid_choice", 

1569 params={"value": value}, 

1570 ) 

1571 return value 

1572 

1573 def validate(self, value): 

1574 return Field.validate(self, value) 

1575 

1576 def has_changed(self, initial, data): 

1577 if self.disabled: 

1578 return False 

1579 initial_value = initial if initial is not None else "" 

1580 data_value = data if data is not None else "" 

1581 return str(self.prepare_value(initial_value)) != str(data_value) 

1582 

1583 

1584class ModelMultipleChoiceField(ModelChoiceField): 

1585 """A MultipleChoiceField whose choices are a model QuerySet.""" 

1586 

1587 widget = SelectMultiple 

1588 hidden_widget = MultipleHiddenInput 

1589 default_error_messages = { 

1590 "invalid_list": _("Enter a list of values."), 

1591 "invalid_choice": _( 

1592 "Select a valid choice. %(value)s is not one of the available choices." 

1593 ), 

1594 "invalid_pk_value": _("“%(pk)s” is not a valid value."), 

1595 } 

1596 

1597 def __init__(self, queryset, **kwargs): 

1598 super().__init__(queryset, empty_label=None, **kwargs) 

1599 

1600 def to_python(self, value): 

1601 if not value: 

1602 return [] 

1603 return list(self._check_values(value)) 

1604 

1605 def clean(self, value): 

1606 value = self.prepare_value(value) 

1607 if self.required and not value: 

1608 raise ValidationError(self.error_messages["required"], code="required") 

1609 elif not self.required and not value: 

1610 return self.queryset.none() 

1611 if not isinstance(value, (list, tuple)): 

1612 raise ValidationError( 

1613 self.error_messages["invalid_list"], 

1614 code="invalid_list", 

1615 ) 

1616 qs = self._check_values(value) 

1617 # Since this overrides the inherited ModelChoiceField.clean 

1618 # we run custom validators here 

1619 self.run_validators(value) 

1620 return qs 

1621 

1622 def _check_values(self, value): 

1623 """ 

1624 Given a list of possible PK values, return a QuerySet of the 

1625 corresponding objects. Raise a ValidationError if a given value is 

1626 invalid (not a valid PK, not in the queryset, etc.) 

1627 """ 

1628 key = self.to_field_name or "pk" 

1629 # deduplicate given values to avoid creating many querysets or 

1630 # requiring the database backend deduplicate efficiently. 

1631 try: 

1632 value = frozenset(value) 

1633 except TypeError: 

1634 # list of lists isn't hashable, for example 

1635 raise ValidationError( 

1636 self.error_messages["invalid_list"], 

1637 code="invalid_list", 

1638 ) 

1639 for pk in value: 

1640 self.validate_no_null_characters(pk) 

1641 try: 

1642 self.queryset.filter(**{key: pk}) 

1643 except (ValueError, TypeError): 

1644 raise ValidationError( 

1645 self.error_messages["invalid_pk_value"], 

1646 code="invalid_pk_value", 

1647 params={"pk": pk}, 

1648 ) 

1649 qs = self.queryset.filter(**{"%s__in" % key: value}) 

1650 pks = {str(getattr(o, key)) for o in qs} 

1651 for val in value: 

1652 if str(val) not in pks: 

1653 raise ValidationError( 

1654 self.error_messages["invalid_choice"], 

1655 code="invalid_choice", 

1656 params={"value": val}, 

1657 ) 

1658 return qs 

1659 

1660 def prepare_value(self, value): 

1661 if ( 

1662 hasattr(value, "__iter__") 

1663 and not isinstance(value, str) 

1664 and not hasattr(value, "_meta") 

1665 ): 

1666 prepare_value = super().prepare_value 

1667 return [prepare_value(v) for v in value] 

1668 return super().prepare_value(value) 

1669 

1670 def has_changed(self, initial, data): 

1671 if self.disabled: 

1672 return False 

1673 if initial is None: 

1674 initial = [] 

1675 if data is None: 

1676 data = [] 

1677 if len(initial) != len(data): 

1678 return True 

1679 initial_set = {str(value) for value in self.prepare_value(initial)} 

1680 data_set = {str(value) for value in data} 

1681 return data_set != initial_set 

1682 

1683 

1684def modelform_defines_fields(form_class): 

1685 return hasattr(form_class, "_meta") and ( 

1686 form_class._meta.fields is not None or form_class._meta.exclude is not None 

1687 )