Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/rest_framework/serializers.py: 73%

676 statements  

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

1""" 

2Serializers and ModelSerializers are similar to Forms and ModelForms. 

3Unlike forms, they are not constrained to dealing with HTML output, and 

4form encoded input. 

5 

6Serialization in REST framework is a two-phase process: 

7 

81. Serializers marshal between complex types like model instances, and 

9python primitives. 

102. The process of marshalling between python primitives and request and 

11response content is handled by parsers and renderers. 

12""" 

13import copy 

14import inspect 

15import traceback 

16from collections import OrderedDict, defaultdict 

17from collections.abc import Mapping 

18 

19from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured 

20from django.core.exceptions import ValidationError as DjangoValidationError 

21from django.db import models 

22from django.db.models.fields import Field as DjangoModelField 

23from django.utils import timezone 

24from django.utils.functional import cached_property 

25from django.utils.translation import gettext_lazy as _ 

26 

27from rest_framework.compat import postgres_fields 

28from rest_framework.exceptions import ErrorDetail, ValidationError 

29from rest_framework.fields import get_error_detail, set_value 

30from rest_framework.settings import api_settings 

31from rest_framework.utils import html, model_meta, representation 

32from rest_framework.utils.field_mapping import ( 

33 ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs, 

34 get_relation_kwargs, get_url_kwargs 

35) 

36from rest_framework.utils.serializer_helpers import ( 

37 BindingDict, BoundField, JSONBoundField, NestedBoundField, ReturnDict, 

38 ReturnList 

39) 

40from rest_framework.validators import ( 

41 UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator, 

42 UniqueTogetherValidator 

43) 

44 

45# Note: We do the following so that users of the framework can use this style: 

46# 

47# example_field = serializers.CharField(...) 

48# 

49# This helps keep the separation between model fields, form fields, and 

50# serializer fields more explicit. 

51from rest_framework.fields import ( # NOQA # isort:skip 

52 BooleanField, CharField, ChoiceField, DateField, DateTimeField, DecimalField, 

53 DictField, DurationField, EmailField, Field, FileField, FilePathField, FloatField, 

54 HiddenField, HStoreField, IPAddressField, ImageField, IntegerField, JSONField, 

55 ListField, ModelField, MultipleChoiceField, NullBooleanField, ReadOnlyField, 

56 RegexField, SerializerMethodField, SlugField, TimeField, URLField, UUIDField, 

57) 

58from rest_framework.relations import ( # NOQA # isort:skip 

59 HyperlinkedIdentityField, HyperlinkedRelatedField, ManyRelatedField, 

60 PrimaryKeyRelatedField, RelatedField, SlugRelatedField, StringRelatedField, 

61) 

62 

63# Non-field imports, but public API 

64from rest_framework.fields import ( # NOQA # isort:skip 

65 CreateOnlyDefault, CurrentUserDefault, SkipField, empty 

66) 

67from rest_framework.relations import Hyperlink, PKOnlyObject # NOQA # isort:skip 

68 

69# We assume that 'validators' are intended for the child serializer, 

70# rather than the parent serializer. 

71LIST_SERIALIZER_KWARGS = ( 

72 'read_only', 'write_only', 'required', 'default', 'initial', 'source', 

73 'label', 'help_text', 'style', 'error_messages', 'allow_empty', 

74 'instance', 'data', 'partial', 'context', 'allow_null', 

75 'max_length', 'min_length' 

76) 

77 

78ALL_FIELDS = '__all__' 

79 

80 

81# BaseSerializer 

82# -------------- 

83 

84class BaseSerializer(Field): 

85 """ 

86 The BaseSerializer class provides a minimal class which may be used 

87 for writing custom serializer implementations. 

88 

89 Note that we strongly restrict the ordering of operations/properties 

90 that may be used on the serializer in order to enforce correct usage. 

91 

92 In particular, if a `data=` argument is passed then: 

93 

94 .is_valid() - Available. 

95 .initial_data - Available. 

96 .validated_data - Only available after calling `is_valid()` 

97 .errors - Only available after calling `is_valid()` 

98 .data - Only available after calling `is_valid()` 

99 

100 If a `data=` argument is not passed then: 

101 

102 .is_valid() - Not available. 

103 .initial_data - Not available. 

104 .validated_data - Not available. 

105 .errors - Not available. 

106 .data - Available. 

107 """ 

108 

109 def __init__(self, instance=None, data=empty, **kwargs): 

110 self.instance = instance 

111 if data is not empty: 

112 self.initial_data = data 

113 self.partial = kwargs.pop('partial', False) 

114 self._context = kwargs.pop('context', {}) 

115 kwargs.pop('many', None) 

116 super().__init__(**kwargs) 

117 

118 def __new__(cls, *args, **kwargs): 

119 # We override this method in order to automatically create 

120 # `ListSerializer` classes instead when `many=True` is set. 

121 if kwargs.pop('many', False): 

122 return cls.many_init(*args, **kwargs) 

123 return super().__new__(cls, *args, **kwargs) 

124 

125 # Allow type checkers to make serializers generic. 

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

127 return cls 

128 

129 @classmethod 

130 def many_init(cls, *args, **kwargs): 

131 """ 

132 This method implements the creation of a `ListSerializer` parent 

133 class when `many=True` is used. You can customize it if you need to 

134 control which keyword arguments are passed to the parent, and 

135 which are passed to the child. 

136 

137 Note that we're over-cautious in passing most arguments to both parent 

138 and child classes in order to try to cover the general case. If you're 

139 overriding this method you'll probably want something much simpler, eg: 

140 

141 @classmethod 

142 def many_init(cls, *args, **kwargs): 

143 kwargs['child'] = cls() 

144 return CustomListSerializer(*args, **kwargs) 

145 """ 

146 allow_empty = kwargs.pop('allow_empty', None) 

147 max_length = kwargs.pop('max_length', None) 

148 min_length = kwargs.pop('min_length', None) 

149 child_serializer = cls(*args, **kwargs) 

150 list_kwargs = { 

151 'child': child_serializer, 

152 } 

153 if allow_empty is not None: 153 ↛ 154line 153 didn't jump to line 154, because the condition on line 153 was never true

154 list_kwargs['allow_empty'] = allow_empty 

155 if max_length is not None: 155 ↛ 156line 155 didn't jump to line 156, because the condition on line 155 was never true

156 list_kwargs['max_length'] = max_length 

157 if min_length is not None: 157 ↛ 158line 157 didn't jump to line 158, because the condition on line 157 was never true

158 list_kwargs['min_length'] = min_length 

159 list_kwargs.update({ 

160 key: value for key, value in kwargs.items() 

161 if key in LIST_SERIALIZER_KWARGS 

162 }) 

163 meta = getattr(cls, 'Meta', None) 

164 list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer) 

165 return list_serializer_class(*args, **list_kwargs) 

166 

167 def to_internal_value(self, data): 

168 raise NotImplementedError('`to_internal_value()` must be implemented.') 

169 

170 def to_representation(self, instance): 

171 raise NotImplementedError('`to_representation()` must be implemented.') 

172 

173 def update(self, instance, validated_data): 

174 raise NotImplementedError('`update()` must be implemented.') 

175 

176 def create(self, validated_data): 

177 raise NotImplementedError('`create()` must be implemented.') 

178 

179 def save(self, **kwargs): 

180 assert hasattr(self, '_errors'), ( 

181 'You must call `.is_valid()` before calling `.save()`.' 

182 ) 

183 

184 assert not self.errors, ( 

185 'You cannot call `.save()` on a serializer with invalid data.' 

186 ) 

187 

188 # Guard against incorrect use of `serializer.save(commit=False)` 

189 assert 'commit' not in kwargs, ( 

190 "'commit' is not a valid keyword argument to the 'save()' method. " 

191 "If you need to access data before committing to the database then " 

192 "inspect 'serializer.validated_data' instead. " 

193 "You can also pass additional keyword arguments to 'save()' if you " 

194 "need to set extra attributes on the saved model instance. " 

195 "For example: 'serializer.save(owner=request.user)'.'" 

196 ) 

197 

198 assert not hasattr(self, '_data'), ( 

199 "You cannot call `.save()` after accessing `serializer.data`." 

200 "If you need to access data before committing to the database then " 

201 "inspect 'serializer.validated_data' instead. " 

202 ) 

203 

204 validated_data = {**self.validated_data, **kwargs} 

205 

206 if self.instance is not None: 

207 self.instance = self.update(self.instance, validated_data) 

208 assert self.instance is not None, ( 

209 '`update()` did not return an object instance.' 

210 ) 

211 else: 

212 self.instance = self.create(validated_data) 

213 assert self.instance is not None, ( 

214 '`create()` did not return an object instance.' 

215 ) 

216 

217 return self.instance 

218 

219 def is_valid(self, raise_exception=False): 

220 assert hasattr(self, 'initial_data'), ( 

221 'Cannot call `.is_valid()` as no `data=` keyword argument was ' 

222 'passed when instantiating the serializer instance.' 

223 ) 

224 

225 if not hasattr(self, '_validated_data'): 225 ↛ 234line 225 didn't jump to line 234, because the condition on line 225 was never false

226 try: 

227 self._validated_data = self.run_validation(self.initial_data) 

228 except ValidationError as exc: 

229 self._validated_data = {} 

230 self._errors = exc.detail 

231 else: 

232 self._errors = {} 

233 

234 if self._errors and raise_exception: 

235 raise ValidationError(self.errors) 

236 

237 return not bool(self._errors) 

238 

239 @property 

240 def data(self): 

241 if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'): 241 ↛ 242line 241 didn't jump to line 242

242 msg = ( 

243 'When a serializer is passed a `data` keyword argument you ' 

244 'must call `.is_valid()` before attempting to access the ' 

245 'serialized `.data` representation.\n' 

246 'You should either call `.is_valid()` first, ' 

247 'or access `.initial_data` instead.' 

248 ) 

249 raise AssertionError(msg) 

250 

251 if not hasattr(self, '_data'): 

252 if self.instance is not None and not getattr(self, '_errors', None): 252 ↛ 254line 252 didn't jump to line 254, because the condition on line 252 was never false

253 self._data = self.to_representation(self.instance) 

254 elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None): 

255 self._data = self.to_representation(self.validated_data) 

256 else: 

257 self._data = self.get_initial() 

258 return self._data 

259 

260 @property 

261 def errors(self): 

262 if not hasattr(self, '_errors'): 262 ↛ 263line 262 didn't jump to line 263, because the condition on line 262 was never true

263 msg = 'You must call `.is_valid()` before accessing `.errors`.' 

264 raise AssertionError(msg) 

265 return self._errors 

266 

267 @property 

268 def validated_data(self): 

269 if not hasattr(self, '_validated_data'): 269 ↛ 270line 269 didn't jump to line 270, because the condition on line 269 was never true

270 msg = 'You must call `.is_valid()` before accessing `.validated_data`.' 

271 raise AssertionError(msg) 

272 return self._validated_data 

273 

274 

275# Serializer & ListSerializer classes 

276# ----------------------------------- 

277 

278class SerializerMetaclass(type): 

279 """ 

280 This metaclass sets a dictionary named `_declared_fields` on the class. 

281 

282 Any instances of `Field` included as attributes on either the class 

283 or on any of its superclasses will be include in the 

284 `_declared_fields` dictionary. 

285 """ 

286 

287 @classmethod 

288 def _get_declared_fields(cls, bases, attrs): 

289 fields = [(field_name, attrs.pop(field_name)) 

290 for field_name, obj in list(attrs.items()) 

291 if isinstance(obj, Field)] 

292 fields.sort(key=lambda x: x[1]._creation_counter) 

293 

294 # Ensures a base class field doesn't override cls attrs, and maintains 

295 # field precedence when inheriting multiple parents. e.g. if there is a 

296 # class C(A, B), and A and B both define 'field', use 'field' from A. 

297 known = set(attrs) 

298 

299 def visit(name): 

300 known.add(name) 

301 return name 

302 

303 base_fields = [ 

304 (visit(name), f) 

305 for base in bases if hasattr(base, '_declared_fields') 

306 for name, f in base._declared_fields.items() if name not in known 

307 ] 

308 

309 return OrderedDict(base_fields + fields) 

310 

311 def __new__(cls, name, bases, attrs): 

312 attrs['_declared_fields'] = cls._get_declared_fields(bases, attrs) 

313 return super().__new__(cls, name, bases, attrs) 

314 

315 

316def as_serializer_error(exc): 

317 assert isinstance(exc, (ValidationError, DjangoValidationError)) 

318 

319 if isinstance(exc, DjangoValidationError): 319 ↛ 320line 319 didn't jump to line 320, because the condition on line 319 was never true

320 detail = get_error_detail(exc) 

321 else: 

322 detail = exc.detail 

323 

324 if isinstance(detail, Mapping): 

325 # If errors may be a dict we use the standard {key: list of values}. 

326 # Here we ensure that all the values are *lists* of errors. 

327 return { 

328 key: value if isinstance(value, (list, Mapping)) else [value] 

329 for key, value in detail.items() 

330 } 

331 elif isinstance(detail, list): 331 ↛ 337line 331 didn't jump to line 337, because the condition on line 331 was never false

332 # Errors raised as a list are non-field errors. 

333 return { 

334 api_settings.NON_FIELD_ERRORS_KEY: detail 

335 } 

336 # Errors raised as a string are non-field errors. 

337 return { 

338 api_settings.NON_FIELD_ERRORS_KEY: [detail] 

339 } 

340 

341 

342class Serializer(BaseSerializer, metaclass=SerializerMetaclass): 

343 default_error_messages = { 

344 'invalid': _('Invalid data. Expected a dictionary, but got {datatype}.') 

345 } 

346 

347 @cached_property 

348 def fields(self): 

349 """ 

350 A dictionary of {field_name: field_instance}. 

351 """ 

352 # `fields` is evaluated lazily. We do this to ensure that we don't 

353 # have issues importing modules that use ModelSerializers as fields, 

354 # even if Django's app-loading stage has not yet run. 

355 fields = BindingDict(self) 

356 for key, value in self.get_fields().items(): 

357 fields[key] = value 

358 return fields 

359 

360 @property 

361 def _writable_fields(self): 

362 for field in self.fields.values(): 

363 if not field.read_only: 

364 yield field 

365 

366 @property 

367 def _readable_fields(self): 

368 for field in self.fields.values(): 

369 if not field.write_only: 

370 yield field 

371 

372 def get_fields(self): 

373 """ 

374 Returns a dictionary of {field_name: field_instance}. 

375 """ 

376 # Every new serializer is created with a clone of the field instances. 

377 # This allows users to dynamically modify the fields on a serializer 

378 # instance without affecting every other serializer instance. 

379 return copy.deepcopy(self._declared_fields) 

380 

381 def get_validators(self): 

382 """ 

383 Returns a list of validator callables. 

384 """ 

385 # Used by the lazily-evaluated `validators` property. 

386 meta = getattr(self, 'Meta', None) 

387 validators = getattr(meta, 'validators', None) 

388 return list(validators) if validators else [] 

389 

390 def get_initial(self): 

391 if hasattr(self, 'initial_data'): 

392 # initial_data may not be a valid type 

393 if not isinstance(self.initial_data, Mapping): 393 ↛ 394line 393 didn't jump to line 394, because the condition on line 393 was never true

394 return OrderedDict() 

395 

396 return OrderedDict([ 

397 (field_name, field.get_value(self.initial_data)) 

398 for field_name, field in self.fields.items() 

399 if (field.get_value(self.initial_data) is not empty) and 

400 not field.read_only 

401 ]) 

402 

403 return OrderedDict([ 

404 (field.field_name, field.get_initial()) 

405 for field in self.fields.values() 

406 if not field.read_only 

407 ]) 

408 

409 def get_value(self, dictionary): 

410 # We override the default field access in order to support 

411 # nested HTML forms. 

412 if html.is_html_input(dictionary): 

413 return html.parse_html_dict(dictionary, prefix=self.field_name) or empty 

414 return dictionary.get(self.field_name, empty) 

415 

416 def run_validation(self, data=empty): 

417 """ 

418 We override the default `run_validation`, because the validation 

419 performed by validators and the `.validate()` method should 

420 be coerced into an error dictionary with a 'non_fields_error' key. 

421 """ 

422 (is_empty_value, data) = self.validate_empty_values(data) 

423 if is_empty_value: 423 ↛ 424line 423 didn't jump to line 424, because the condition on line 423 was never true

424 return data 

425 

426 value = self.to_internal_value(data) 

427 try: 

428 self.run_validators(value) 

429 value = self.validate(value) 

430 assert value is not None, '.validate() should return the validated data' 

431 except (ValidationError, DjangoValidationError) as exc: 

432 raise ValidationError(detail=as_serializer_error(exc)) 

433 

434 return value 

435 

436 def _read_only_defaults(self): 

437 fields = [ 

438 field for field in self.fields.values() 

439 if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source) 

440 ] 

441 

442 defaults = OrderedDict() 

443 for field in fields: 443 ↛ 444line 443 didn't jump to line 444, because the loop on line 443 never started

444 try: 

445 default = field.get_default() 

446 except SkipField: 

447 continue 

448 defaults[field.source] = default 

449 

450 return defaults 

451 

452 def run_validators(self, value): 

453 """ 

454 Add read_only fields with defaults to value before running validators. 

455 """ 

456 if isinstance(value, dict): 456 ↛ 460line 456 didn't jump to line 460, because the condition on line 456 was never false

457 to_validate = self._read_only_defaults() 

458 to_validate.update(value) 

459 else: 

460 to_validate = value 

461 super().run_validators(to_validate) 

462 

463 def to_internal_value(self, data): 

464 """ 

465 Dict of native values <- Dict of primitive datatypes. 

466 """ 

467 if not isinstance(data, Mapping): 467 ↛ 468line 467 didn't jump to line 468, because the condition on line 467 was never true

468 message = self.error_messages['invalid'].format( 

469 datatype=type(data).__name__ 

470 ) 

471 raise ValidationError({ 

472 api_settings.NON_FIELD_ERRORS_KEY: [message] 

473 }, code='invalid') 

474 

475 ret = OrderedDict() 

476 errors = OrderedDict() 

477 fields = self._writable_fields 

478 

479 for field in fields: 

480 validate_method = getattr(self, 'validate_' + field.field_name, None) 

481 primitive_value = field.get_value(data) 

482 try: 

483 validated_value = field.run_validation(primitive_value) 

484 if validate_method is not None: 

485 validated_value = validate_method(validated_value) 

486 except ValidationError as exc: 

487 errors[field.field_name] = exc.detail 

488 except DjangoValidationError as exc: 488 ↛ 489line 488 didn't jump to line 489, because the exception caught by line 488 didn't happen

489 errors[field.field_name] = get_error_detail(exc) 

490 except SkipField: 

491 pass 

492 else: 

493 set_value(ret, field.source_attrs, validated_value) 

494 

495 if errors: 

496 raise ValidationError(errors) 

497 

498 return ret 

499 

500 def to_representation(self, instance): 

501 """ 

502 Object instance -> Dict of primitive datatypes. 

503 """ 

504 ret = OrderedDict() 

505 fields = self._readable_fields 

506 

507 for field in fields: 

508 try: 

509 attribute = field.get_attribute(instance) 

510 except SkipField: 

511 continue 

512 

513 # We skip `to_representation` for `None` values so that fields do 

514 # not have to explicitly deal with that case. 

515 # 

516 # For related fields with `use_pk_only_optimization` we need to 

517 # resolve the pk value. 

518 check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute 

519 if check_for_none is None: 

520 ret[field.field_name] = None 

521 else: 

522 ret[field.field_name] = field.to_representation(attribute) 

523 

524 return ret 

525 

526 def validate(self, attrs): 

527 return attrs 

528 

529 def __repr__(self): 

530 return representation.serializer_repr(self, indent=1) 

531 

532 # The following are used for accessing `BoundField` instances on the 

533 # serializer, for the purposes of presenting a form-like API onto the 

534 # field values and field errors. 

535 

536 def __iter__(self): 

537 for field in self.fields.values(): 

538 yield self[field.field_name] 

539 

540 def __getitem__(self, key): 

541 field = self.fields[key] 

542 value = self.data.get(key) 

543 error = self.errors.get(key) if hasattr(self, '_errors') else None 

544 if isinstance(field, Serializer): 

545 return NestedBoundField(field, value, error) 

546 if isinstance(field, JSONField): 

547 return JSONBoundField(field, value, error) 

548 return BoundField(field, value, error) 

549 

550 # Include a backlink to the serializer class on return objects. 

551 # Allows renderers such as HTMLFormRenderer to get the full field info. 

552 

553 @property 

554 def data(self): 

555 ret = super().data 

556 return ReturnDict(ret, serializer=self) 

557 

558 @property 

559 def errors(self): 

560 ret = super().errors 

561 if isinstance(ret, list) and len(ret) == 1 and getattr(ret[0], 'code', None) == 'null': 561 ↛ 564line 561 didn't jump to line 564, because the condition on line 561 was never true

562 # Edge case. Provide a more descriptive error than 

563 # "this field may not be null", when no data is passed. 

564 detail = ErrorDetail('No data provided', code='null') 

565 ret = {api_settings.NON_FIELD_ERRORS_KEY: [detail]} 

566 return ReturnDict(ret, serializer=self) 

567 

568 

569# There's some replication of `ListField` here, 

570# but that's probably better than obfuscating the call hierarchy. 

571 

572class ListSerializer(BaseSerializer): 

573 child = None 

574 many = True 

575 

576 default_error_messages = { 

577 'not_a_list': _('Expected a list of items but got type "{input_type}".'), 

578 'empty': _('This list may not be empty.'), 

579 'max_length': _('Ensure this field has no more than {max_length} elements.'), 

580 'min_length': _('Ensure this field has at least {min_length} elements.') 

581 } 

582 

583 def __init__(self, *args, **kwargs): 

584 self.child = kwargs.pop('child', copy.deepcopy(self.child)) 

585 self.allow_empty = kwargs.pop('allow_empty', True) 

586 self.max_length = kwargs.pop('max_length', None) 

587 self.min_length = kwargs.pop('min_length', None) 

588 assert self.child is not None, '`child` is a required argument.' 

589 assert not inspect.isclass(self.child), '`child` has not been instantiated.' 

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

591 self.child.bind(field_name='', parent=self) 

592 

593 def get_initial(self): 

594 if hasattr(self, 'initial_data'): 

595 return self.to_representation(self.initial_data) 

596 return [] 

597 

598 def get_value(self, dictionary): 

599 """ 

600 Given the input dictionary, return the field value. 

601 """ 

602 # We override the default field access in order to support 

603 # lists in HTML forms. 

604 if html.is_html_input(dictionary): 

605 return html.parse_html_list(dictionary, prefix=self.field_name, default=empty) 

606 return dictionary.get(self.field_name, empty) 

607 

608 def run_validation(self, data=empty): 

609 """ 

610 We override the default `run_validation`, because the validation 

611 performed by validators and the `.validate()` method should 

612 be coerced into an error dictionary with a 'non_fields_error' key. 

613 """ 

614 (is_empty_value, data) = self.validate_empty_values(data) 

615 if is_empty_value: 615 ↛ 616line 615 didn't jump to line 616, because the condition on line 615 was never true

616 return data 

617 

618 value = self.to_internal_value(data) 

619 try: 

620 self.run_validators(value) 

621 value = self.validate(value) 

622 assert value is not None, '.validate() should return the validated data' 

623 except (ValidationError, DjangoValidationError) as exc: 

624 raise ValidationError(detail=as_serializer_error(exc)) 

625 

626 return value 

627 

628 def to_internal_value(self, data): 

629 """ 

630 List of dicts of native values <- List of dicts of primitive datatypes. 

631 """ 

632 if html.is_html_input(data): 632 ↛ 633line 632 didn't jump to line 633, because the condition on line 632 was never true

633 data = html.parse_html_list(data, default=[]) 

634 

635 if not isinstance(data, list): 635 ↛ 636line 635 didn't jump to line 636, because the condition on line 635 was never true

636 message = self.error_messages['not_a_list'].format( 

637 input_type=type(data).__name__ 

638 ) 

639 raise ValidationError({ 

640 api_settings.NON_FIELD_ERRORS_KEY: [message] 

641 }, code='not_a_list') 

642 

643 if not self.allow_empty and len(data) == 0: 643 ↛ 644line 643 didn't jump to line 644, because the condition on line 643 was never true

644 message = self.error_messages['empty'] 

645 raise ValidationError({ 

646 api_settings.NON_FIELD_ERRORS_KEY: [message] 

647 }, code='empty') 

648 

649 if self.max_length is not None and len(data) > self.max_length: 649 ↛ 650line 649 didn't jump to line 650, because the condition on line 649 was never true

650 message = self.error_messages['max_length'].format(max_length=self.max_length) 

651 raise ValidationError({ 

652 api_settings.NON_FIELD_ERRORS_KEY: [message] 

653 }, code='max_length') 

654 

655 if self.min_length is not None and len(data) < self.min_length: 655 ↛ 656line 655 didn't jump to line 656, because the condition on line 655 was never true

656 message = self.error_messages['min_length'].format(min_length=self.min_length) 

657 raise ValidationError({ 

658 api_settings.NON_FIELD_ERRORS_KEY: [message] 

659 }, code='min_length') 

660 

661 ret = [] 

662 errors = [] 

663 

664 for item in data: 

665 try: 

666 validated = self.child.run_validation(item) 

667 except ValidationError as exc: 

668 errors.append(exc.detail) 

669 else: 

670 ret.append(validated) 

671 errors.append({}) 

672 

673 if any(errors): 673 ↛ 674line 673 didn't jump to line 674, because the condition on line 673 was never true

674 raise ValidationError(errors) 

675 

676 return ret 

677 

678 def to_representation(self, data): 

679 """ 

680 List of object instances -> List of dicts of primitive datatypes. 

681 """ 

682 # Dealing with nested relationships, data can be a Manager, 

683 # so, first get a queryset from the Manager if needed 

684 iterable = data.all() if isinstance(data, models.Manager) else data 

685 

686 return [ 

687 self.child.to_representation(item) for item in iterable 

688 ] 

689 

690 def validate(self, attrs): 

691 return attrs 

692 

693 def update(self, instance, validated_data): 

694 raise NotImplementedError( 

695 "Serializers with many=True do not support multiple update by " 

696 "default, only multiple create. For updates it is unclear how to " 

697 "deal with insertions and deletions. If you need to support " 

698 "multiple update, use a `ListSerializer` class and override " 

699 "`.update()` so you can specify the behavior exactly." 

700 ) 

701 

702 def create(self, validated_data): 

703 return [ 

704 self.child.create(attrs) for attrs in validated_data 

705 ] 

706 

707 def save(self, **kwargs): 

708 """ 

709 Save and return a list of object instances. 

710 """ 

711 # Guard against incorrect use of `serializer.save(commit=False)` 

712 assert 'commit' not in kwargs, ( 

713 "'commit' is not a valid keyword argument to the 'save()' method. " 

714 "If you need to access data before committing to the database then " 

715 "inspect 'serializer.validated_data' instead. " 

716 "You can also pass additional keyword arguments to 'save()' if you " 

717 "need to set extra attributes on the saved model instance. " 

718 "For example: 'serializer.save(owner=request.user)'.'" 

719 ) 

720 

721 validated_data = [ 

722 {**attrs, **kwargs} for attrs in self.validated_data 

723 ] 

724 

725 if self.instance is not None: 

726 self.instance = self.update(self.instance, validated_data) 

727 assert self.instance is not None, ( 

728 '`update()` did not return an object instance.' 

729 ) 

730 else: 

731 self.instance = self.create(validated_data) 

732 assert self.instance is not None, ( 

733 '`create()` did not return an object instance.' 

734 ) 

735 

736 return self.instance 

737 

738 def is_valid(self, raise_exception=False): 

739 # This implementation is the same as the default, 

740 # except that we use lists, rather than dicts, as the empty case. 

741 assert hasattr(self, 'initial_data'), ( 

742 'Cannot call `.is_valid()` as no `data=` keyword argument was ' 

743 'passed when instantiating the serializer instance.' 

744 ) 

745 

746 if not hasattr(self, '_validated_data'): 

747 try: 

748 self._validated_data = self.run_validation(self.initial_data) 

749 except ValidationError as exc: 

750 self._validated_data = [] 

751 self._errors = exc.detail 

752 else: 

753 self._errors = [] 

754 

755 if self._errors and raise_exception: 

756 raise ValidationError(self.errors) 

757 

758 return not bool(self._errors) 

759 

760 def __repr__(self): 

761 return representation.list_repr(self, indent=1) 

762 

763 # Include a backlink to the serializer class on return objects. 

764 # Allows renderers such as HTMLFormRenderer to get the full field info. 

765 

766 @property 

767 def data(self): 

768 ret = super().data 

769 return ReturnList(ret, serializer=self) 

770 

771 @property 

772 def errors(self): 

773 ret = super().errors 

774 if isinstance(ret, list) and len(ret) == 1 and getattr(ret[0], 'code', None) == 'null': 

775 # Edge case. Provide a more descriptive error than 

776 # "this field may not be null", when no data is passed. 

777 detail = ErrorDetail('No data provided', code='null') 

778 ret = {api_settings.NON_FIELD_ERRORS_KEY: [detail]} 

779 if isinstance(ret, dict): 

780 return ReturnDict(ret, serializer=self) 

781 return ReturnList(ret, serializer=self) 

782 

783 

784# ModelSerializer & HyperlinkedModelSerializer 

785# -------------------------------------------- 

786 

787def raise_errors_on_nested_writes(method_name, serializer, validated_data): 

788 """ 

789 Give explicit errors when users attempt to pass writable nested data. 

790 

791 If we don't do this explicitly they'd get a less helpful error when 

792 calling `.save()` on the serializer. 

793 

794 We don't *automatically* support these sorts of nested writes because 

795 there are too many ambiguities to define a default behavior. 

796 

797 Eg. Suppose we have a `UserSerializer` with a nested profile. How should 

798 we handle the case of an update, where the `profile` relationship does 

799 not exist? Any of the following might be valid: 

800 

801 * Raise an application error. 

802 * Silently ignore the nested part of the update. 

803 * Automatically create a profile instance. 

804 """ 

805 ModelClass = serializer.Meta.model 

806 model_field_info = model_meta.get_field_info(ModelClass) 

807 

808 # Ensure we don't have a writable nested field. For example: 

809 # 

810 # class UserSerializer(ModelSerializer): 

811 # ... 

812 # profile = ProfileSerializer() 

813 assert not any( 

814 isinstance(field, BaseSerializer) and 

815 (field.source in validated_data) and 

816 (field.source in model_field_info.relations) and 

817 isinstance(validated_data[field.source], (list, dict)) 

818 for field in serializer._writable_fields 

819 ), ( 

820 'The `.{method_name}()` method does not support writable nested ' 

821 'fields by default.\nWrite an explicit `.{method_name}()` method for ' 

822 'serializer `{module}.{class_name}`, or set `read_only=True` on ' 

823 'nested serializer fields.'.format( 

824 method_name=method_name, 

825 module=serializer.__class__.__module__, 

826 class_name=serializer.__class__.__name__ 

827 ) 

828 ) 

829 

830 # Ensure we don't have a writable dotted-source field. For example: 

831 # 

832 # class UserSerializer(ModelSerializer): 

833 # ... 

834 # address = serializer.CharField('profile.address') 

835 # 

836 # Though, non-relational fields (e.g., JSONField) are acceptable. For example: 

837 # 

838 # class NonRelationalPersonModel(models.Model): 

839 # profile = JSONField() 

840 # 

841 # class UserSerializer(ModelSerializer): 

842 # ... 

843 # address = serializer.CharField('profile.address') 

844 assert not any( 

845 len(field.source_attrs) > 1 and 

846 (field.source_attrs[0] in validated_data) and 

847 (field.source_attrs[0] in model_field_info.relations) and 

848 isinstance(validated_data[field.source_attrs[0]], (list, dict)) 

849 for field in serializer._writable_fields 

850 ), ( 

851 'The `.{method_name}()` method does not support writable dotted-source ' 

852 'fields by default.\nWrite an explicit `.{method_name}()` method for ' 

853 'serializer `{module}.{class_name}`, or set `read_only=True` on ' 

854 'dotted-source serializer fields.'.format( 

855 method_name=method_name, 

856 module=serializer.__class__.__module__, 

857 class_name=serializer.__class__.__name__ 

858 ) 

859 ) 

860 

861 

862class ModelSerializer(Serializer): 

863 """ 

864 A `ModelSerializer` is just a regular `Serializer`, except that: 

865 

866 * A set of default fields are automatically populated. 

867 * A set of default validators are automatically populated. 

868 * Default `.create()` and `.update()` implementations are provided. 

869 

870 The process of automatically determining a set of serializer fields 

871 based on the model fields is reasonably complex, but you almost certainly 

872 don't need to dig into the implementation. 

873 

874 If the `ModelSerializer` class *doesn't* generate the set of fields that 

875 you need you should either declare the extra/differing fields explicitly on 

876 the serializer class, or simply use a `Serializer` class. 

877 """ 

878 serializer_field_mapping = { 

879 models.AutoField: IntegerField, 

880 models.BigIntegerField: IntegerField, 

881 models.BooleanField: BooleanField, 

882 models.CharField: CharField, 

883 models.CommaSeparatedIntegerField: CharField, 

884 models.DateField: DateField, 

885 models.DateTimeField: DateTimeField, 

886 models.DecimalField: DecimalField, 

887 models.DurationField: DurationField, 

888 models.EmailField: EmailField, 

889 models.Field: ModelField, 

890 models.FileField: FileField, 

891 models.FloatField: FloatField, 

892 models.ImageField: ImageField, 

893 models.IntegerField: IntegerField, 

894 models.NullBooleanField: BooleanField, 

895 models.PositiveIntegerField: IntegerField, 

896 models.PositiveSmallIntegerField: IntegerField, 

897 models.SlugField: SlugField, 

898 models.SmallIntegerField: IntegerField, 

899 models.TextField: CharField, 

900 models.TimeField: TimeField, 

901 models.URLField: URLField, 

902 models.UUIDField: UUIDField, 

903 models.GenericIPAddressField: IPAddressField, 

904 models.FilePathField: FilePathField, 

905 } 

906 if hasattr(models, 'JSONField'): 906 ↛ 908line 906 didn't jump to line 908, because the condition on line 906 was never false

907 serializer_field_mapping[models.JSONField] = JSONField 

908 if postgres_fields: 908 ↛ 912line 908 didn't jump to line 912, because the condition on line 908 was never false

909 serializer_field_mapping[postgres_fields.HStoreField] = HStoreField 

910 serializer_field_mapping[postgres_fields.ArrayField] = ListField 

911 serializer_field_mapping[postgres_fields.JSONField] = JSONField 

912 serializer_related_field = PrimaryKeyRelatedField 

913 serializer_related_to_field = SlugRelatedField 

914 serializer_url_field = HyperlinkedIdentityField 

915 serializer_choice_field = ChoiceField 

916 

917 # The field name for hyperlinked identity fields. Defaults to 'url'. 

918 # You can modify this using the API setting. 

919 # 

920 # Note that if you instead need modify this on a per-serializer basis, 

921 # you'll also need to ensure you update the `create` method on any generic 

922 # views, to correctly handle the 'Location' response header for 

923 # "HTTP 201 Created" responses. 

924 url_field_name = None 

925 

926 # Default `create` and `update` behavior... 

927 def create(self, validated_data): 

928 """ 

929 We have a bit of extra checking around this in order to provide 

930 descriptive messages when something goes wrong, but this method is 

931 essentially just: 

932 

933 return ExampleModel.objects.create(**validated_data) 

934 

935 If there are many to many fields present on the instance then they 

936 cannot be set until the model is instantiated, in which case the 

937 implementation is like so: 

938 

939 example_relationship = validated_data.pop('example_relationship') 

940 instance = ExampleModel.objects.create(**validated_data) 

941 instance.example_relationship = example_relationship 

942 return instance 

943 

944 The default implementation also does not handle nested relationships. 

945 If you want to support writable nested relationships you'll need 

946 to write an explicit `.create()` method. 

947 """ 

948 raise_errors_on_nested_writes('create', self, validated_data) 

949 

950 ModelClass = self.Meta.model 

951 

952 # Remove many-to-many relationships from validated_data. 

953 # They are not valid arguments to the default `.create()` method, 

954 # as they require that the instance has already been saved. 

955 info = model_meta.get_field_info(ModelClass) 

956 many_to_many = {} 

957 for field_name, relation_info in info.relations.items(): 

958 if relation_info.to_many and (field_name in validated_data): 

959 many_to_many[field_name] = validated_data.pop(field_name) 

960 

961 try: 

962 instance = ModelClass._default_manager.create(**validated_data) 

963 except TypeError: 

964 tb = traceback.format_exc() 

965 msg = ( 

966 'Got a `TypeError` when calling `%s.%s.create()`. ' 

967 'This may be because you have a writable field on the ' 

968 'serializer class that is not a valid argument to ' 

969 '`%s.%s.create()`. You may need to make the field ' 

970 'read-only, or override the %s.create() method to handle ' 

971 'this correctly.\nOriginal exception was:\n %s' % 

972 ( 

973 ModelClass.__name__, 

974 ModelClass._default_manager.name, 

975 ModelClass.__name__, 

976 ModelClass._default_manager.name, 

977 self.__class__.__name__, 

978 tb 

979 ) 

980 ) 

981 raise TypeError(msg) 

982 

983 # Save many-to-many relationships after the instance is created. 

984 if many_to_many: 

985 for field_name, value in many_to_many.items(): 

986 field = getattr(instance, field_name) 

987 field.set(value) 

988 

989 return instance 

990 

991 def update(self, instance, validated_data): 

992 raise_errors_on_nested_writes('update', self, validated_data) 

993 info = model_meta.get_field_info(instance) 

994 

995 # Simply set each attribute on the instance, and then save it. 

996 # Note that unlike `.create()` we don't need to treat many-to-many 

997 # relationships as being a special case. During updates we already 

998 # have an instance pk for the relationships to be associated with. 

999 m2m_fields = [] 

1000 for attr, value in validated_data.items(): 

1001 if attr in info.relations and info.relations[attr].to_many: 

1002 m2m_fields.append((attr, value)) 

1003 else: 

1004 setattr(instance, attr, value) 

1005 

1006 instance.save() 

1007 

1008 # Note that many-to-many fields are set after updating instance. 

1009 # Setting m2m fields triggers signals which could potentially change 

1010 # updated instance and we do not want it to collide with .update() 

1011 for attr, value in m2m_fields: 

1012 field = getattr(instance, attr) 

1013 field.set(value) 

1014 

1015 return instance 

1016 

1017 # Determine the fields to apply... 

1018 

1019 def get_fields(self): 

1020 """ 

1021 Return the dict of field names -> field instances that should be 

1022 used for `self.fields` when instantiating the serializer. 

1023 """ 

1024 if self.url_field_name is None: 1024 ↛ 1027line 1024 didn't jump to line 1027, because the condition on line 1024 was never false

1025 self.url_field_name = api_settings.URL_FIELD_NAME 

1026 

1027 assert hasattr(self, 'Meta'), ( 

1028 'Class {serializer_class} missing "Meta" attribute'.format( 

1029 serializer_class=self.__class__.__name__ 

1030 ) 

1031 ) 

1032 assert hasattr(self.Meta, 'model'), ( 

1033 'Class {serializer_class} missing "Meta.model" attribute'.format( 

1034 serializer_class=self.__class__.__name__ 

1035 ) 

1036 ) 

1037 if model_meta.is_abstract_model(self.Meta.model): 1037 ↛ 1038line 1037 didn't jump to line 1038, because the condition on line 1037 was never true

1038 raise ValueError( 

1039 'Cannot use ModelSerializer with Abstract Models.' 

1040 ) 

1041 

1042 declared_fields = copy.deepcopy(self._declared_fields) 

1043 model = getattr(self.Meta, 'model') 

1044 depth = getattr(self.Meta, 'depth', 0) 

1045 

1046 if depth is not None: 1046 ↛ 1051line 1046 didn't jump to line 1051, because the condition on line 1046 was never false

1047 assert depth >= 0, "'depth' may not be negative." 

1048 assert depth <= 10, "'depth' may not be greater than 10." 

1049 

1050 # Retrieve metadata about fields & relationships on the model class. 

1051 info = model_meta.get_field_info(model) 

1052 field_names = self.get_field_names(declared_fields, info) 

1053 

1054 # Determine any extra field arguments and hidden fields that 

1055 # should be included 

1056 extra_kwargs = self.get_extra_kwargs() 

1057 extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs( 

1058 field_names, declared_fields, extra_kwargs 

1059 ) 

1060 

1061 # Determine the fields that should be included on the serializer. 

1062 fields = OrderedDict() 

1063 

1064 for field_name in field_names: 

1065 # If the field is explicitly declared on the class then use that. 

1066 if field_name in declared_fields: 

1067 fields[field_name] = declared_fields[field_name] 

1068 continue 

1069 

1070 extra_field_kwargs = extra_kwargs.get(field_name, {}) 

1071 source = extra_field_kwargs.get('source', '*') 

1072 if source == '*': 1072 ↛ 1076line 1072 didn't jump to line 1076, because the condition on line 1072 was never false

1073 source = field_name 

1074 

1075 # Determine the serializer field class and keyword arguments. 

1076 field_class, field_kwargs = self.build_field( 

1077 source, info, model, depth 

1078 ) 

1079 

1080 # Include any kwargs defined in `Meta.extra_kwargs` 

1081 field_kwargs = self.include_extra_kwargs( 

1082 field_kwargs, extra_field_kwargs 

1083 ) 

1084 

1085 # Create the serializer field. 

1086 fields[field_name] = field_class(**field_kwargs) 

1087 

1088 # Add in any hidden fields. 

1089 fields.update(hidden_fields) 

1090 

1091 return fields 

1092 

1093 # Methods for determining the set of field names to include... 

1094 

1095 def get_field_names(self, declared_fields, info): 

1096 """ 

1097 Returns the list of all field names that should be created when 

1098 instantiating this serializer class. This is based on the default 

1099 set of fields, but also takes into account the `Meta.fields` or 

1100 `Meta.exclude` options if they have been specified. 

1101 """ 

1102 fields = getattr(self.Meta, 'fields', None) 

1103 exclude = getattr(self.Meta, 'exclude', None) 

1104 

1105 if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)): 1105 ↛ 1106line 1105 didn't jump to line 1106, because the condition on line 1105 was never true

1106 raise TypeError( 

1107 'The `fields` option must be a list or tuple or "__all__". ' 

1108 'Got %s.' % type(fields).__name__ 

1109 ) 

1110 

1111 if exclude and not isinstance(exclude, (list, tuple)): 1111 ↛ 1112line 1111 didn't jump to line 1112, because the condition on line 1111 was never true

1112 raise TypeError( 

1113 'The `exclude` option must be a list or tuple. Got %s.' % 

1114 type(exclude).__name__ 

1115 ) 

1116 

1117 assert not (fields and exclude), ( 

1118 "Cannot set both 'fields' and 'exclude' options on " 

1119 "serializer {serializer_class}.".format( 

1120 serializer_class=self.__class__.__name__ 

1121 ) 

1122 ) 

1123 

1124 assert not (fields is None and exclude is None), ( 

1125 "Creating a ModelSerializer without either the 'fields' attribute " 

1126 "or the 'exclude' attribute has been deprecated since 3.3.0, " 

1127 "and is now disallowed. Add an explicit fields = '__all__' to the " 

1128 "{serializer_class} serializer.".format( 

1129 serializer_class=self.__class__.__name__ 

1130 ), 

1131 ) 

1132 

1133 if fields == ALL_FIELDS: 1133 ↛ 1134line 1133 didn't jump to line 1134, because the condition on line 1133 was never true

1134 fields = None 

1135 

1136 if fields is not None: 1136 ↛ 1159line 1136 didn't jump to line 1159, because the condition on line 1136 was never false

1137 # Ensure that all declared fields have also been included in the 

1138 # `Meta.fields` option. 

1139 

1140 # Do not require any fields that are declared in a parent class, 

1141 # in order to allow serializer subclasses to only include 

1142 # a subset of fields. 

1143 required_field_names = set(declared_fields) 

1144 for cls in self.__class__.__bases__: 

1145 required_field_names -= set(getattr(cls, '_declared_fields', [])) 

1146 

1147 for field_name in required_field_names: 

1148 assert field_name in fields, ( 

1149 "The field '{field_name}' was declared on serializer " 

1150 "{serializer_class}, but has not been included in the " 

1151 "'fields' option.".format( 

1152 field_name=field_name, 

1153 serializer_class=self.__class__.__name__ 

1154 ) 

1155 ) 

1156 return fields 

1157 

1158 # Use the default set of field names if `Meta.fields` is not specified. 

1159 fields = self.get_default_field_names(declared_fields, info) 

1160 

1161 if exclude is not None: 

1162 # If `Meta.exclude` is included, then remove those fields. 

1163 for field_name in exclude: 

1164 assert field_name not in self._declared_fields, ( 

1165 "Cannot both declare the field '{field_name}' and include " 

1166 "it in the {serializer_class} 'exclude' option. Remove the " 

1167 "field or, if inherited from a parent serializer, disable " 

1168 "with `{field_name} = None`." 

1169 .format( 

1170 field_name=field_name, 

1171 serializer_class=self.__class__.__name__ 

1172 ) 

1173 ) 

1174 

1175 assert field_name in fields, ( 

1176 "The field '{field_name}' was included on serializer " 

1177 "{serializer_class} in the 'exclude' option, but does " 

1178 "not match any model field.".format( 

1179 field_name=field_name, 

1180 serializer_class=self.__class__.__name__ 

1181 ) 

1182 ) 

1183 fields.remove(field_name) 

1184 

1185 return fields 

1186 

1187 def get_default_field_names(self, declared_fields, model_info): 

1188 """ 

1189 Return the default list of field names that will be used if the 

1190 `Meta.fields` option is not specified. 

1191 """ 

1192 return ( 

1193 [model_info.pk.name] + 

1194 list(declared_fields) + 

1195 list(model_info.fields) + 

1196 list(model_info.forward_relations) 

1197 ) 

1198 

1199 # Methods for constructing serializer fields... 

1200 

1201 def build_field(self, field_name, info, model_class, nested_depth): 

1202 """ 

1203 Return a two tuple of (cls, kwargs) to build a serializer field with. 

1204 """ 

1205 if field_name in info.fields_and_pk: 

1206 model_field = info.fields_and_pk[field_name] 

1207 return self.build_standard_field(field_name, model_field) 

1208 

1209 elif field_name in info.relations: 1209 ↛ 1216line 1209 didn't jump to line 1216, because the condition on line 1209 was never false

1210 relation_info = info.relations[field_name] 

1211 if not nested_depth: 1211 ↛ 1214line 1211 didn't jump to line 1214, because the condition on line 1211 was never false

1212 return self.build_relational_field(field_name, relation_info) 

1213 else: 

1214 return self.build_nested_field(field_name, relation_info, nested_depth) 

1215 

1216 elif hasattr(model_class, field_name): 

1217 return self.build_property_field(field_name, model_class) 

1218 

1219 elif field_name == self.url_field_name: 

1220 return self.build_url_field(field_name, model_class) 

1221 

1222 return self.build_unknown_field(field_name, model_class) 

1223 

1224 def build_standard_field(self, field_name, model_field): 

1225 """ 

1226 Create regular model fields. 

1227 """ 

1228 field_mapping = ClassLookupDict(self.serializer_field_mapping) 

1229 

1230 field_class = field_mapping[model_field] 

1231 field_kwargs = get_field_kwargs(field_name, model_field) 

1232 

1233 # Special case to handle when a OneToOneField is also the primary key 

1234 if model_field.one_to_one and model_field.primary_key: 1234 ↛ 1235line 1234 didn't jump to line 1235, because the condition on line 1234 was never true

1235 field_class = self.serializer_related_field 

1236 field_kwargs['queryset'] = model_field.related_model.objects 

1237 

1238 if 'choices' in field_kwargs: 

1239 # Fields with choices get coerced into `ChoiceField` 

1240 # instead of using their regular typed field. 

1241 field_class = self.serializer_choice_field 

1242 # Some model fields may introduce kwargs that would not be valid 

1243 # for the choice field. We need to strip these out. 

1244 # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES) 

1245 valid_kwargs = { 

1246 'read_only', 'write_only', 

1247 'required', 'default', 'initial', 'source', 

1248 'label', 'help_text', 'style', 

1249 'error_messages', 'validators', 'allow_null', 'allow_blank', 

1250 'choices' 

1251 } 

1252 for key in list(field_kwargs): 

1253 if key not in valid_kwargs: 

1254 field_kwargs.pop(key) 

1255 

1256 if not issubclass(field_class, ModelField): 1256 ↛ 1262line 1256 didn't jump to line 1262, because the condition on line 1256 was never false

1257 # `model_field` is only valid for the fallback case of 

1258 # `ModelField`, which is used when no other typed field 

1259 # matched to the model field. 

1260 field_kwargs.pop('model_field', None) 

1261 

1262 if not issubclass(field_class, CharField) and not issubclass(field_class, ChoiceField): 

1263 # `allow_blank` is only valid for textual fields. 

1264 field_kwargs.pop('allow_blank', None) 

1265 

1266 is_django_jsonfield = hasattr(models, 'JSONField') and isinstance(model_field, models.JSONField) 

1267 if (postgres_fields and isinstance(model_field, postgres_fields.JSONField)) or is_django_jsonfield: 

1268 # Populate the `encoder` argument of `JSONField` instances generated 

1269 # for the model `JSONField`. 

1270 field_kwargs['encoder'] = getattr(model_field, 'encoder', None) 

1271 if is_django_jsonfield: 1271 ↛ 1274line 1271 didn't jump to line 1274, because the condition on line 1271 was never false

1272 field_kwargs['decoder'] = getattr(model_field, 'decoder', None) 

1273 

1274 if postgres_fields and isinstance(model_field, postgres_fields.ArrayField): 1274 ↛ 1277line 1274 didn't jump to line 1277, because the condition on line 1274 was never true

1275 # Populate the `child` argument on `ListField` instances generated 

1276 # for the PostgreSQL specific `ArrayField`. 

1277 child_model_field = model_field.base_field 

1278 child_field_class, child_field_kwargs = self.build_standard_field( 

1279 'child', child_model_field 

1280 ) 

1281 field_kwargs['child'] = child_field_class(**child_field_kwargs) 

1282 

1283 return field_class, field_kwargs 

1284 

1285 def build_relational_field(self, field_name, relation_info): 

1286 """ 

1287 Create fields for forward and reverse relationships. 

1288 """ 

1289 field_class = self.serializer_related_field 

1290 field_kwargs = get_relation_kwargs(field_name, relation_info) 

1291 

1292 to_field = field_kwargs.pop('to_field', None) 

1293 if to_field and not relation_info.reverse and not relation_info.related_model._meta.get_field(to_field).primary_key: 1293 ↛ 1294line 1293 didn't jump to line 1294, because the condition on line 1293 was never true

1294 field_kwargs['slug_field'] = to_field 

1295 field_class = self.serializer_related_to_field 

1296 

1297 # `view_name` is only valid for hyperlinked relationships. 

1298 if not issubclass(field_class, HyperlinkedRelatedField): 1298 ↛ 1301line 1298 didn't jump to line 1301, because the condition on line 1298 was never false

1299 field_kwargs.pop('view_name', None) 

1300 

1301 return field_class, field_kwargs 

1302 

1303 def build_nested_field(self, field_name, relation_info, nested_depth): 

1304 """ 

1305 Create nested fields for forward and reverse relationships. 

1306 """ 

1307 class NestedSerializer(ModelSerializer): 

1308 class Meta: 

1309 model = relation_info.related_model 

1310 depth = nested_depth - 1 

1311 fields = '__all__' 

1312 

1313 field_class = NestedSerializer 

1314 field_kwargs = get_nested_relation_kwargs(relation_info) 

1315 

1316 return field_class, field_kwargs 

1317 

1318 def build_property_field(self, field_name, model_class): 

1319 """ 

1320 Create a read only field for model methods and properties. 

1321 """ 

1322 field_class = ReadOnlyField 

1323 field_kwargs = {} 

1324 

1325 return field_class, field_kwargs 

1326 

1327 def build_url_field(self, field_name, model_class): 

1328 """ 

1329 Create a field representing the object's own URL. 

1330 """ 

1331 field_class = self.serializer_url_field 

1332 field_kwargs = get_url_kwargs(model_class) 

1333 

1334 return field_class, field_kwargs 

1335 

1336 def build_unknown_field(self, field_name, model_class): 

1337 """ 

1338 Raise an error on any unknown fields. 

1339 """ 

1340 raise ImproperlyConfigured( 

1341 'Field name `%s` is not valid for model `%s`.' % 

1342 (field_name, model_class.__name__) 

1343 ) 

1344 

1345 def include_extra_kwargs(self, kwargs, extra_kwargs): 

1346 """ 

1347 Include any 'extra_kwargs' that have been included for this field, 

1348 possibly removing any incompatible existing keyword arguments. 

1349 """ 

1350 if extra_kwargs.get('read_only', False): 

1351 for attr in [ 

1352 'required', 'default', 'allow_blank', 'min_length', 

1353 'max_length', 'min_value', 'max_value', 'validators', 'queryset' 

1354 ]: 

1355 kwargs.pop(attr, None) 

1356 

1357 if extra_kwargs.get('default') and kwargs.get('required') is False: 1357 ↛ 1358line 1357 didn't jump to line 1358, because the condition on line 1357 was never true

1358 kwargs.pop('required') 

1359 

1360 if extra_kwargs.get('read_only', kwargs.get('read_only', False)): 

1361 extra_kwargs.pop('required', None) # Read only fields should always omit the 'required' argument. 

1362 

1363 kwargs.update(extra_kwargs) 

1364 

1365 return kwargs 

1366 

1367 # Methods for determining additional keyword arguments to apply... 

1368 

1369 def get_extra_kwargs(self): 

1370 """ 

1371 Return a dictionary mapping field names to a dictionary of 

1372 additional keyword arguments. 

1373 """ 

1374 extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {})) 

1375 

1376 read_only_fields = getattr(self.Meta, 'read_only_fields', None) 

1377 if read_only_fields is not None: 

1378 if not isinstance(read_only_fields, (list, tuple)): 1378 ↛ 1379line 1378 didn't jump to line 1379, because the condition on line 1378 was never true

1379 raise TypeError( 

1380 'The `read_only_fields` option must be a list or tuple. ' 

1381 'Got %s.' % type(read_only_fields).__name__ 

1382 ) 

1383 for field_name in read_only_fields: 

1384 kwargs = extra_kwargs.get(field_name, {}) 

1385 kwargs['read_only'] = True 

1386 extra_kwargs[field_name] = kwargs 

1387 

1388 else: 

1389 # Guard against the possible misspelling `readonly_fields` (used 

1390 # by the Django admin and others). 

1391 assert not hasattr(self.Meta, 'readonly_fields'), ( 

1392 'Serializer `%s.%s` has field `readonly_fields`; ' 

1393 'the correct spelling for the option is `read_only_fields`.' % 

1394 (self.__class__.__module__, self.__class__.__name__) 

1395 ) 

1396 

1397 return extra_kwargs 

1398 

1399 def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs): 

1400 """ 

1401 Return any additional field options that need to be included as a 

1402 result of uniqueness constraints on the model. This is returned as 

1403 a two-tuple of: 

1404 

1405 ('dict of updated extra kwargs', 'mapping of hidden fields') 

1406 """ 

1407 if getattr(self.Meta, 'validators', None) is not None: 1407 ↛ 1408line 1407 didn't jump to line 1408, because the condition on line 1407 was never true

1408 return (extra_kwargs, {}) 

1409 

1410 model = getattr(self.Meta, 'model') 

1411 model_fields = self._get_model_fields( 

1412 field_names, declared_fields, extra_kwargs 

1413 ) 

1414 

1415 # Determine if we need any additional `HiddenField` or extra keyword 

1416 # arguments to deal with `unique_for` dates that are required to 

1417 # be in the input data in order to validate it. 

1418 unique_constraint_names = set() 

1419 

1420 for model_field in model_fields.values(): 

1421 # Include each of the `unique_for_*` field names. 

1422 unique_constraint_names |= {model_field.unique_for_date, model_field.unique_for_month, 

1423 model_field.unique_for_year} 

1424 

1425 unique_constraint_names -= {None} 

1426 

1427 # Include each of the `unique_together` field names, 

1428 # so long as all the field names are included on the serializer. 

1429 for parent_class in [model] + list(model._meta.parents): 

1430 for unique_together_list in parent_class._meta.unique_together: 

1431 if set(field_names).issuperset(unique_together_list): 

1432 unique_constraint_names |= set(unique_together_list) 

1433 

1434 # Now we have all the field names that have uniqueness constraints 

1435 # applied, we can add the extra 'required=...' or 'default=...' 

1436 # arguments that are appropriate to these fields, or add a `HiddenField` for it. 

1437 hidden_fields = {} 

1438 uniqueness_extra_kwargs = {} 

1439 

1440 for unique_constraint_name in unique_constraint_names: 

1441 # Get the model field that is referred too. 

1442 unique_constraint_field = model._meta.get_field(unique_constraint_name) 

1443 

1444 if getattr(unique_constraint_field, 'auto_now_add', None): 1444 ↛ 1445line 1444 didn't jump to line 1445, because the condition on line 1444 was never true

1445 default = CreateOnlyDefault(timezone.now) 

1446 elif getattr(unique_constraint_field, 'auto_now', None): 1446 ↛ 1447line 1446 didn't jump to line 1447, because the condition on line 1446 was never true

1447 default = timezone.now 

1448 elif unique_constraint_field.has_default(): 1448 ↛ 1449line 1448 didn't jump to line 1449, because the condition on line 1448 was never true

1449 default = unique_constraint_field.default 

1450 else: 

1451 default = empty 

1452 

1453 if unique_constraint_name in model_fields: 1453 ↛ 1459line 1453 didn't jump to line 1459, because the condition on line 1453 was never false

1454 # The corresponding field is present in the serializer 

1455 if default is empty: 1455 ↛ 1458line 1455 didn't jump to line 1458, because the condition on line 1455 was never false

1456 uniqueness_extra_kwargs[unique_constraint_name] = {'required': True} 

1457 else: 

1458 uniqueness_extra_kwargs[unique_constraint_name] = {'default': default} 

1459 elif default is not empty: 

1460 # The corresponding field is not present in the 

1461 # serializer. We have a default to use for it, so 

1462 # add in a hidden field that populates it. 

1463 hidden_fields[unique_constraint_name] = HiddenField(default=default) 

1464 

1465 # Update `extra_kwargs` with any new options. 

1466 for key, value in uniqueness_extra_kwargs.items(): 

1467 if key in extra_kwargs: 

1468 value.update(extra_kwargs[key]) 

1469 extra_kwargs[key] = value 

1470 

1471 return extra_kwargs, hidden_fields 

1472 

1473 def _get_model_fields(self, field_names, declared_fields, extra_kwargs): 

1474 """ 

1475 Returns all the model fields that are being mapped to by fields 

1476 on the serializer class. 

1477 Returned as a dict of 'model field name' -> 'model field'. 

1478 Used internally by `get_uniqueness_field_options`. 

1479 """ 

1480 model = getattr(self.Meta, 'model') 

1481 model_fields = {} 

1482 

1483 for field_name in field_names: 

1484 if field_name in declared_fields: 

1485 # If the field is declared on the serializer 

1486 field = declared_fields[field_name] 

1487 source = field.source or field_name 

1488 else: 

1489 try: 

1490 source = extra_kwargs[field_name]['source'] 

1491 except KeyError: 

1492 source = field_name 

1493 

1494 if '.' in source or source == '*': 

1495 # Model fields will always have a simple source mapping, 

1496 # they can't be nested attribute lookups. 

1497 continue 

1498 

1499 try: 

1500 field = model._meta.get_field(source) 

1501 if isinstance(field, DjangoModelField): 

1502 model_fields[source] = field 

1503 except FieldDoesNotExist: 

1504 pass 

1505 

1506 return model_fields 

1507 

1508 # Determine the validators to apply... 

1509 

1510 def get_validators(self): 

1511 """ 

1512 Determine the set of validators to use when instantiating serializer. 

1513 """ 

1514 # If the validators have been declared explicitly then use that. 

1515 validators = getattr(getattr(self, 'Meta', None), 'validators', None) 

1516 if validators is not None: 1516 ↛ 1517line 1516 didn't jump to line 1517, because the condition on line 1516 was never true

1517 return list(validators) 

1518 

1519 # Otherwise use the default set of validators. 

1520 return ( 

1521 self.get_unique_together_validators() + 

1522 self.get_unique_for_date_validators() 

1523 ) 

1524 

1525 def get_unique_together_validators(self): 

1526 """ 

1527 Determine a default set of validators for any unique_together constraints. 

1528 """ 

1529 model_class_inheritance_tree = ( 

1530 [self.Meta.model] + 

1531 list(self.Meta.model._meta.parents) 

1532 ) 

1533 

1534 # The field names we're passing though here only include fields 

1535 # which may map onto a model field. Any dotted field name lookups 

1536 # cannot map to a field, and must be a traversal, so we're not 

1537 # including those. 

1538 field_sources = OrderedDict( 

1539 (field.field_name, field.source) for field in self._writable_fields 

1540 if (field.source != '*') and ('.' not in field.source) 

1541 ) 

1542 

1543 # Special Case: Add read_only fields with defaults. 

1544 field_sources.update(OrderedDict( 

1545 (field.field_name, field.source) for field in self.fields.values() 

1546 if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source) 

1547 )) 

1548 

1549 # Invert so we can find the serializer field names that correspond to 

1550 # the model field names in the unique_together sets. This also allows 

1551 # us to check that multiple fields don't map to the same source. 

1552 source_map = defaultdict(list) 

1553 for name, source in field_sources.items(): 

1554 source_map[source].append(name) 

1555 

1556 # Note that we make sure to check `unique_together` both on the 

1557 # base model class, but also on any parent classes. 

1558 validators = [] 

1559 for parent_class in model_class_inheritance_tree: 

1560 for unique_together in parent_class._meta.unique_together: 

1561 # Skip if serializer does not map to all unique together sources 

1562 if not set(source_map).issuperset(unique_together): 1562 ↛ 1565line 1562 didn't jump to line 1565, because the condition on line 1562 was never false

1563 continue 

1564 

1565 for source in unique_together: 

1566 assert len(source_map[source]) == 1, ( 

1567 "Unable to create `UniqueTogetherValidator` for " 

1568 "`{model}.{field}` as `{serializer}` has multiple " 

1569 "fields ({fields}) that map to this model field. " 

1570 "Either remove the extra fields, or override " 

1571 "`Meta.validators` with a `UniqueTogetherValidator` " 

1572 "using the desired field names." 

1573 .format( 

1574 model=self.Meta.model.__name__, 

1575 serializer=self.__class__.__name__, 

1576 field=source, 

1577 fields=', '.join(source_map[source]), 

1578 ) 

1579 ) 

1580 

1581 field_names = tuple(source_map[f][0] for f in unique_together) 

1582 validator = UniqueTogetherValidator( 

1583 queryset=parent_class._default_manager, 

1584 fields=field_names 

1585 ) 

1586 validators.append(validator) 

1587 return validators 

1588 

1589 def get_unique_for_date_validators(self): 

1590 """ 

1591 Determine a default set of validators for the following constraints: 

1592 

1593 * unique_for_date 

1594 * unique_for_month 

1595 * unique_for_year 

1596 """ 

1597 info = model_meta.get_field_info(self.Meta.model) 

1598 default_manager = self.Meta.model._default_manager 

1599 field_names = [field.source for field in self.fields.values()] 

1600 

1601 validators = [] 

1602 

1603 for field_name, field in info.fields_and_pk.items(): 

1604 if field.unique_for_date and field_name in field_names: 1604 ↛ 1605line 1604 didn't jump to line 1605, because the condition on line 1604 was never true

1605 validator = UniqueForDateValidator( 

1606 queryset=default_manager, 

1607 field=field_name, 

1608 date_field=field.unique_for_date 

1609 ) 

1610 validators.append(validator) 

1611 

1612 if field.unique_for_month and field_name in field_names: 1612 ↛ 1613line 1612 didn't jump to line 1613, because the condition on line 1612 was never true

1613 validator = UniqueForMonthValidator( 

1614 queryset=default_manager, 

1615 field=field_name, 

1616 date_field=field.unique_for_month 

1617 ) 

1618 validators.append(validator) 

1619 

1620 if field.unique_for_year and field_name in field_names: 1620 ↛ 1621line 1620 didn't jump to line 1621, because the condition on line 1620 was never true

1621 validator = UniqueForYearValidator( 

1622 queryset=default_manager, 

1623 field=field_name, 

1624 date_field=field.unique_for_year 

1625 ) 

1626 validators.append(validator) 

1627 

1628 return validators 

1629 

1630 

1631class HyperlinkedModelSerializer(ModelSerializer): 

1632 """ 

1633 A type of `ModelSerializer` that uses hyperlinked relationships instead 

1634 of primary key relationships. Specifically: 

1635 

1636 * A 'url' field is included instead of the 'id' field. 

1637 * Relationships to other instances are hyperlinks, instead of primary keys. 

1638 """ 

1639 serializer_related_field = HyperlinkedRelatedField 

1640 

1641 def get_default_field_names(self, declared_fields, model_info): 

1642 """ 

1643 Return the default list of field names that will be used if the 

1644 `Meta.fields` option is not specified. 

1645 """ 

1646 return ( 

1647 [self.url_field_name] + 

1648 list(declared_fields) + 

1649 list(model_info.fields) + 

1650 list(model_info.forward_relations) 

1651 ) 

1652 

1653 def build_nested_field(self, field_name, relation_info, nested_depth): 

1654 """ 

1655 Create nested fields for forward and reverse relationships. 

1656 """ 

1657 class NestedSerializer(HyperlinkedModelSerializer): 

1658 class Meta: 

1659 model = relation_info.related_model 

1660 depth = nested_depth - 1 

1661 fields = '__all__' 

1662 

1663 field_class = NestedSerializer 

1664 field_kwargs = get_nested_relation_kwargs(relation_info) 

1665 

1666 return field_class, field_kwargs