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) 76 77ALL_FIELDS = '__all__' 78 79 80# BaseSerializer 81# -------------- 82 83class BaseSerializer(Field): 84 """ 85 The BaseSerializer class provides a minimal class which may be used 86 for writing custom serializer implementations. 87 88 Note that we strongly restrict the ordering of operations/properties 89 that may be used on the serializer in order to enforce correct usage. 90 91 In particular, if a `data=` argument is passed then: 92 93 .is_valid() - Available. 94 .initial_data - Available. 95 .validated_data - Only available after calling `is_valid()` 96 .errors - Only available after calling `is_valid()` 97 .data - Only available after calling `is_valid()` 98 99 If a `data=` argument is not passed then: 100 101 .is_valid() - Not available. 102 .initial_data - Not available. 103 .validated_data - Not available. 104 .errors - Not available. 105 .data - Available. 106 """ 107 108 def __init__(self, instance=None, data=empty, **kwargs): 109 self.instance = instance 110 if data is not empty: 111 self.initial_data = data 112 self.partial = kwargs.pop('partial', False) 113 self._context = kwargs.pop('context', {}) 114 kwargs.pop('many', None) 115 super().__init__(**kwargs) 116 117 def __new__(cls, *args, **kwargs): 118 # We override this method in order to automatically create 119 # `ListSerializer` classes instead when `many=True` is set. 120 if kwargs.pop('many', False): 121 return cls.many_init(*args, **kwargs) 122 return super().__new__(cls, *args, **kwargs) 123 124 # Allow type checkers to make serializers generic. 125 def __class_getitem__(cls, *args, **kwargs): 126 return cls 127 128 @classmethod 129 def many_init(cls, *args, **kwargs): 130 """ 131 This method implements the creation of a `ListSerializer` parent 132 class when `many=True` is used. You can customize it if you need to 133 control which keyword arguments are passed to the parent, and 134 which are passed to the child. 135 136 Note that we're over-cautious in passing most arguments to both parent 137 and child classes in order to try to cover the general case. If you're 138 overriding this method you'll probably want something much simpler, eg: 139 140 @classmethod 141 def many_init(cls, *args, **kwargs): 142 kwargs['child'] = cls() 143 return CustomListSerializer(*args, **kwargs) 144 """ 145 allow_empty = kwargs.pop('allow_empty', None) 146 child_serializer = cls(*args, **kwargs) 147 list_kwargs = { 148 'child': child_serializer, 149 } 150 if allow_empty is not None: 151 list_kwargs['allow_empty'] = allow_empty 152 list_kwargs.update({ 153 key: value for key, value in kwargs.items() 154 if key in LIST_SERIALIZER_KWARGS 155 }) 156 meta = getattr(cls, 'Meta', None) 157 list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer) 158 return list_serializer_class(*args, **list_kwargs) 159 160 def to_internal_value(self, data): 161 raise NotImplementedError('`to_internal_value()` must be implemented.') 162 163 def to_representation(self, instance): 164 raise NotImplementedError('`to_representation()` must be implemented.') 165 166 def update(self, instance, validated_data): 167 raise NotImplementedError('`update()` must be implemented.') 168 169 def create(self, validated_data): 170 raise NotImplementedError('`create()` must be implemented.') 171 172 def save(self, **kwargs): 173 assert hasattr(self, '_errors'), ( 174 'You must call `.is_valid()` before calling `.save()`.' 175 ) 176 177 assert not self.errors, ( 178 'You cannot call `.save()` on a serializer with invalid data.' 179 ) 180 181 # Guard against incorrect use of `serializer.save(commit=False)` 182 assert 'commit' not in kwargs, ( 183 "'commit' is not a valid keyword argument to the 'save()' method. " 184 "If you need to access data before committing to the database then " 185 "inspect 'serializer.validated_data' instead. " 186 "You can also pass additional keyword arguments to 'save()' if you " 187 "need to set extra attributes on the saved model instance. " 188 "For example: 'serializer.save(owner=request.user)'.'" 189 ) 190 191 assert not hasattr(self, '_data'), ( 192 "You cannot call `.save()` after accessing `serializer.data`." 193 "If you need to access data before committing to the database then " 194 "inspect 'serializer.validated_data' instead. " 195 ) 196 197 validated_data = {**self.validated_data, **kwargs} 198 199 if self.instance is not None: 200 self.instance = self.update(self.instance, validated_data) 201 assert self.instance is not None, ( 202 '`update()` did not return an object instance.' 203 ) 204 else: 205 self.instance = self.create(validated_data) 206 assert self.instance is not None, ( 207 '`create()` did not return an object instance.' 208 ) 209 210 return self.instance 211 212 def is_valid(self, raise_exception=False): 213 assert hasattr(self, 'initial_data'), ( 214 'Cannot call `.is_valid()` as no `data=` keyword argument was ' 215 'passed when instantiating the serializer instance.' 216 ) 217 218 if not hasattr(self, '_validated_data'): 219 try: 220 self._validated_data = self.run_validation(self.initial_data) 221 except ValidationError as exc: 222 self._validated_data = {} 223 self._errors = exc.detail 224 else: 225 self._errors = {} 226 227 if self._errors and raise_exception: 228 raise ValidationError(self.errors) 229 230 return not bool(self._errors) 231 232 @property 233 def data(self): 234 if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'): 235 msg = ( 236 'When a serializer is passed a `data` keyword argument you ' 237 'must call `.is_valid()` before attempting to access the ' 238 'serialized `.data` representation.\n' 239 'You should either call `.is_valid()` first, ' 240 'or access `.initial_data` instead.' 241 ) 242 raise AssertionError(msg) 243 244 if not hasattr(self, '_data'): 245 if self.instance is not None and not getattr(self, '_errors', None): 246 self._data = self.to_representation(self.instance) 247 elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None): 248 self._data = self.to_representation(self.validated_data) 249 else: 250 self._data = self.get_initial() 251 return self._data 252 253 @property 254 def errors(self): 255 if not hasattr(self, '_errors'): 256 msg = 'You must call `.is_valid()` before accessing `.errors`.' 257 raise AssertionError(msg) 258 return self._errors 259 260 @property 261 def validated_data(self): 262 if not hasattr(self, '_validated_data'): 263 msg = 'You must call `.is_valid()` before accessing `.validated_data`.' 264 raise AssertionError(msg) 265 return self._validated_data 266 267 268# Serializer & ListSerializer classes 269# ----------------------------------- 270 271class SerializerMetaclass(type): 272 """ 273 This metaclass sets a dictionary named `_declared_fields` on the class. 274 275 Any instances of `Field` included as attributes on either the class 276 or on any of its superclasses will be include in the 277 `_declared_fields` dictionary. 278 """ 279 280 @classmethod 281 def _get_declared_fields(cls, bases, attrs): 282 fields = [(field_name, attrs.pop(field_name)) 283 for field_name, obj in list(attrs.items()) 284 if isinstance(obj, Field)] 285 fields.sort(key=lambda x: x[1]._creation_counter) 286 287 # Ensures a base class field doesn't override cls attrs, and maintains 288 # field precedence when inheriting multiple parents. e.g. if there is a 289 # class C(A, B), and A and B both define 'field', use 'field' from A. 290 known = set(attrs) 291 292 def visit(name): 293 known.add(name) 294 return name 295 296 base_fields = [ 297 (visit(name), f) 298 for base in bases if hasattr(base, '_declared_fields') 299 for name, f in base._declared_fields.items() if name not in known 300 ] 301 302 return OrderedDict(base_fields + fields) 303 304 def __new__(cls, name, bases, attrs): 305 attrs['_declared_fields'] = cls._get_declared_fields(bases, attrs) 306 return super().__new__(cls, name, bases, attrs) 307 308 309def as_serializer_error(exc): 310 assert isinstance(exc, (ValidationError, DjangoValidationError)) 311 312 if isinstance(exc, DjangoValidationError): 313 detail = get_error_detail(exc) 314 else: 315 detail = exc.detail 316 317 if isinstance(detail, Mapping): 318 # If errors may be a dict we use the standard {key: list of values}. 319 # Here we ensure that all the values are *lists* of errors. 320 return { 321 key: value if isinstance(value, (list, Mapping)) else [value] 322 for key, value in detail.items() 323 } 324 elif isinstance(detail, list): 325 # Errors raised as a list are non-field errors. 326 return { 327 api_settings.NON_FIELD_ERRORS_KEY: detail 328 } 329 # Errors raised as a string are non-field errors. 330 return { 331 api_settings.NON_FIELD_ERRORS_KEY: [detail] 332 } 333 334 335class Serializer(BaseSerializer, metaclass=SerializerMetaclass): 336 default_error_messages = { 337 'invalid': _('Invalid data. Expected a dictionary, but got {datatype}.') 338 } 339 340 @cached_property 341 def fields(self): 342 """ 343 A dictionary of {field_name: field_instance}. 344 """ 345 # `fields` is evaluated lazily. We do this to ensure that we don't 346 # have issues importing modules that use ModelSerializers as fields, 347 # even if Django's app-loading stage has not yet run. 348 fields = BindingDict(self) 349 for key, value in self.get_fields().items(): 350 fields[key] = value 351 return fields 352 353 @property 354 def _writable_fields(self): 355 for field in self.fields.values(): 356 if not field.read_only: 357 yield field 358 359 @property 360 def _readable_fields(self): 361 for field in self.fields.values(): 362 if not field.write_only: 363 yield field 364 365 def get_fields(self): 366 """ 367 Returns a dictionary of {field_name: field_instance}. 368 """ 369 # Every new serializer is created with a clone of the field instances. 370 # This allows users to dynamically modify the fields on a serializer 371 # instance without affecting every other serializer instance. 372 return copy.deepcopy(self._declared_fields) 373 374 def get_validators(self): 375 """ 376 Returns a list of validator callables. 377 """ 378 # Used by the lazily-evaluated `validators` property. 379 meta = getattr(self, 'Meta', None) 380 validators = getattr(meta, 'validators', None) 381 return list(validators) if validators else [] 382 383 def get_initial(self): 384 if hasattr(self, 'initial_data'): 385 # initial_data may not be a valid type 386 if not isinstance(self.initial_data, Mapping): 387 return OrderedDict() 388 389 return OrderedDict([ 390 (field_name, field.get_value(self.initial_data)) 391 for field_name, field in self.fields.items() 392 if (field.get_value(self.initial_data) is not empty) and 393 not field.read_only 394 ]) 395 396 return OrderedDict([ 397 (field.field_name, field.get_initial()) 398 for field in self.fields.values() 399 if not field.read_only 400 ]) 401 402 def get_value(self, dictionary): 403 # We override the default field access in order to support 404 # nested HTML forms. 405 if html.is_html_input(dictionary): 406 return html.parse_html_dict(dictionary, prefix=self.field_name) or empty 407 return dictionary.get(self.field_name, empty) 408 409 def run_validation(self, data=empty): 410 """ 411 We override the default `run_validation`, because the validation 412 performed by validators and the `.validate()` method should 413 be coerced into an error dictionary with a 'non_fields_error' key. 414 """ 415 (is_empty_value, data) = self.validate_empty_values(data) 416 if is_empty_value: 417 return data 418 419 value = self.to_internal_value(data) 420 try: 421 self.run_validators(value) 422 value = self.validate(value) 423 assert value is not None, '.validate() should return the validated data' 424 except (ValidationError, DjangoValidationError) as exc: 425 raise ValidationError(detail=as_serializer_error(exc)) 426 427 return value 428 429 def _read_only_defaults(self): 430 fields = [ 431 field for field in self.fields.values() 432 if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source) 433 ] 434 435 defaults = OrderedDict() 436 for field in fields: 437 try: 438 default = field.get_default() 439 except SkipField: 440 continue 441 defaults[field.source] = default 442 443 return defaults 444 445 def run_validators(self, value): 446 """ 447 Add read_only fields with defaults to value before running validators. 448 """ 449 if isinstance(value, dict): 450 to_validate = self._read_only_defaults() 451 to_validate.update(value) 452 else: 453 to_validate = value 454 super().run_validators(to_validate) 455 456 def to_internal_value(self, data): 457 """ 458 Dict of native values <- Dict of primitive datatypes. 459 """ 460 if not isinstance(data, Mapping): 461 message = self.error_messages['invalid'].format( 462 datatype=type(data).__name__ 463 ) 464 raise ValidationError({ 465 api_settings.NON_FIELD_ERRORS_KEY: [message] 466 }, code='invalid') 467 468 ret = OrderedDict() 469 errors = OrderedDict() 470 fields = self._writable_fields 471 472 for field in fields: 473 validate_method = getattr(self, 'validate_' + field.field_name, None) 474 primitive_value = field.get_value(data) 475 try: 476 validated_value = field.run_validation(primitive_value) 477 if validate_method is not None: 478 validated_value = validate_method(validated_value) 479 except ValidationError as exc: 480 errors[field.field_name] = exc.detail 481 except DjangoValidationError as exc: 482 errors[field.field_name] = get_error_detail(exc) 483 except SkipField: 484 pass 485 else: 486 set_value(ret, field.source_attrs, validated_value) 487 488 if errors: 489 raise ValidationError(errors) 490 491 return ret 492 493 def to_representation(self, instance): 494 """ 495 Object instance -> Dict of primitive datatypes. 496 """ 497 ret = OrderedDict() 498 fields = self._readable_fields 499 500 for field in fields: 501 try: 502 attribute = field.get_attribute(instance) 503 except SkipField: 504 continue 505 506 # We skip `to_representation` for `None` values so that fields do 507 # not have to explicitly deal with that case. 508 # 509 # For related fields with `use_pk_only_optimization` we need to 510 # resolve the pk value. 511 check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute 512 if check_for_none is None: 513 ret[field.field_name] = None 514 else: 515 ret[field.field_name] = field.to_representation(attribute) 516 517 return ret 518 519 def validate(self, attrs): 520 return attrs 521 522 def __repr__(self): 523 return representation.serializer_repr(self, indent=1) 524 525 # The following are used for accessing `BoundField` instances on the 526 # serializer, for the purposes of presenting a form-like API onto the 527 # field values and field errors. 528 529 def __iter__(self): 530 for field in self.fields.values(): 531 yield self[field.field_name] 532 533 def __getitem__(self, key): 534 field = self.fields[key] 535 value = self.data.get(key) 536 error = self.errors.get(key) if hasattr(self, '_errors') else None 537 if isinstance(field, Serializer): 538 return NestedBoundField(field, value, error) 539 if isinstance(field, JSONField): 540 return JSONBoundField(field, value, error) 541 return BoundField(field, value, error) 542 543 # Include a backlink to the serializer class on return objects. 544 # Allows renderers such as HTMLFormRenderer to get the full field info. 545 546 @property 547 def data(self): 548 ret = super().data 549 return ReturnDict(ret, serializer=self) 550 551 @property 552 def errors(self): 553 ret = super().errors 554 if isinstance(ret, list) and len(ret) == 1 and getattr(ret[0], 'code', None) == 'null': 555 # Edge case. Provide a more descriptive error than 556 # "this field may not be null", when no data is passed. 557 detail = ErrorDetail('No data provided', code='null') 558 ret = {api_settings.NON_FIELD_ERRORS_KEY: [detail]} 559 return ReturnDict(ret, serializer=self) 560 561 562# There's some replication of `ListField` here, 563# but that's probably better than obfuscating the call hierarchy. 564 565class ListSerializer(BaseSerializer): 566 child = None 567 many = True 568 569 default_error_messages = { 570 'not_a_list': _('Expected a list of items but got type "{input_type}".'), 571 'empty': _('This list may not be empty.') 572 } 573 574 def __init__(self, *args, **kwargs): 575 self.child = kwargs.pop('child', copy.deepcopy(self.child)) 576 self.allow_empty = kwargs.pop('allow_empty', True) 577 assert self.child is not None, '`child` is a required argument.' 578 assert not inspect.isclass(self.child), '`child` has not been instantiated.' 579 super().__init__(*args, **kwargs) 580 self.child.bind(field_name='', parent=self) 581 582 def get_initial(self): 583 if hasattr(self, 'initial_data'): 584 return self.to_representation(self.initial_data) 585 return [] 586 587 def get_value(self, dictionary): 588 """ 589 Given the input dictionary, return the field value. 590 """ 591 # We override the default field access in order to support 592 # lists in HTML forms. 593 if html.is_html_input(dictionary): 594 return html.parse_html_list(dictionary, prefix=self.field_name, default=empty) 595 return dictionary.get(self.field_name, empty) 596 597 def run_validation(self, data=empty): 598 """ 599 We override the default `run_validation`, because the validation 600 performed by validators and the `.validate()` method should 601 be coerced into an error dictionary with a 'non_fields_error' key. 602 """ 603 (is_empty_value, data) = self.validate_empty_values(data) 604 if is_empty_value: 605 return data 606 607 value = self.to_internal_value(data) 608 try: 609 self.run_validators(value) 610 value = self.validate(value) 611 assert value is not None, '.validate() should return the validated data' 612 except (ValidationError, DjangoValidationError) as exc: 613 raise ValidationError(detail=as_serializer_error(exc)) 614 615 return value 616 617 def to_internal_value(self, data): 618 """ 619 List of dicts of native values <- List of dicts of primitive datatypes. 620 """ 621 if html.is_html_input(data): 622 data = html.parse_html_list(data, default=[]) 623 624 if not isinstance(data, list): 625 message = self.error_messages['not_a_list'].format( 626 input_type=type(data).__name__ 627 ) 628 raise ValidationError({ 629 api_settings.NON_FIELD_ERRORS_KEY: [message] 630 }, code='not_a_list') 631 632 if not self.allow_empty and len(data) == 0: 633 message = self.error_messages['empty'] 634 raise ValidationError({ 635 api_settings.NON_FIELD_ERRORS_KEY: [message] 636 }, code='empty') 637 638 ret = [] 639 errors = [] 640 641 for item in data: 642 try: 643 validated = self.child.run_validation(item) 644 except ValidationError as exc: 645 errors.append(exc.detail) 646 else: 647 ret.append(validated) 648 errors.append({}) 649 650 if any(errors): 651 raise ValidationError(errors) 652 653 return ret 654 655 def to_representation(self, data): 656 """ 657 List of object instances -> List of dicts of primitive datatypes. 658 """ 659 # Dealing with nested relationships, data can be a Manager, 660 # so, first get a queryset from the Manager if needed 661 iterable = data.all() if isinstance(data, models.Manager) else data 662 663 return [ 664 self.child.to_representation(item) for item in iterable 665 ] 666 667 def validate(self, attrs): 668 return attrs 669 670 def update(self, instance, validated_data): 671 raise NotImplementedError( 672 "Serializers with many=True do not support multiple update by " 673 "default, only multiple create. For updates it is unclear how to " 674 "deal with insertions and deletions. If you need to support " 675 "multiple update, use a `ListSerializer` class and override " 676 "`.update()` so you can specify the behavior exactly." 677 ) 678 679 def create(self, validated_data): 680 return [ 681 self.child.create(attrs) for attrs in validated_data 682 ] 683 684 def save(self, **kwargs): 685 """ 686 Save and return a list of object instances. 687 """ 688 # Guard against incorrect use of `serializer.save(commit=False)` 689 assert 'commit' not in kwargs, ( 690 "'commit' is not a valid keyword argument to the 'save()' method. " 691 "If you need to access data before committing to the database then " 692 "inspect 'serializer.validated_data' instead. " 693 "You can also pass additional keyword arguments to 'save()' if you " 694 "need to set extra attributes on the saved model instance. " 695 "For example: 'serializer.save(owner=request.user)'.'" 696 ) 697 698 validated_data = [ 699 {**attrs, **kwargs} for attrs in self.validated_data 700 ] 701 702 if self.instance is not None: 703 self.instance = self.update(self.instance, validated_data) 704 assert self.instance is not None, ( 705 '`update()` did not return an object instance.' 706 ) 707 else: 708 self.instance = self.create(validated_data) 709 assert self.instance is not None, ( 710 '`create()` did not return an object instance.' 711 ) 712 713 return self.instance 714 715 def is_valid(self, raise_exception=False): 716 # This implementation is the same as the default, 717 # except that we use lists, rather than dicts, as the empty case. 718 assert hasattr(self, 'initial_data'), ( 719 'Cannot call `.is_valid()` as no `data=` keyword argument was ' 720 'passed when instantiating the serializer instance.' 721 ) 722 723 if not hasattr(self, '_validated_data'): 724 try: 725 self._validated_data = self.run_validation(self.initial_data) 726 except ValidationError as exc: 727 self._validated_data = [] 728 self._errors = exc.detail 729 else: 730 self._errors = [] 731 732 if self._errors and raise_exception: 733 raise ValidationError(self.errors) 734 735 return not bool(self._errors) 736 737 def __repr__(self): 738 return representation.list_repr(self, indent=1) 739 740 # Include a backlink to the serializer class on return objects. 741 # Allows renderers such as HTMLFormRenderer to get the full field info. 742 743 @property 744 def data(self): 745 ret = super().data 746 return ReturnList(ret, serializer=self) 747 748 @property 749 def errors(self): 750 ret = super().errors 751 if isinstance(ret, list) and len(ret) == 1 and getattr(ret[0], 'code', None) == 'null': 752 # Edge case. Provide a more descriptive error than 753 # "this field may not be null", when no data is passed. 754 detail = ErrorDetail('No data provided', code='null') 755 ret = {api_settings.NON_FIELD_ERRORS_KEY: [detail]} 756 if isinstance(ret, dict): 757 return ReturnDict(ret, serializer=self) 758 return ReturnList(ret, serializer=self) 759 760 761# ModelSerializer & HyperlinkedModelSerializer 762# -------------------------------------------- 763 764def raise_errors_on_nested_writes(method_name, serializer, validated_data): 765 """ 766 Give explicit errors when users attempt to pass writable nested data. 767 768 If we don't do this explicitly they'd get a less helpful error when 769 calling `.save()` on the serializer. 770 771 We don't *automatically* support these sorts of nested writes because 772 there are too many ambiguities to define a default behavior. 773 774 Eg. Suppose we have a `UserSerializer` with a nested profile. How should 775 we handle the case of an update, where the `profile` relationship does 776 not exist? Any of the following might be valid: 777 778 * Raise an application error. 779 * Silently ignore the nested part of the update. 780 * Automatically create a profile instance. 781 """ 782 ModelClass = serializer.Meta.model 783 model_field_info = model_meta.get_field_info(ModelClass) 784 785 # Ensure we don't have a writable nested field. For example: 786 # 787 # class UserSerializer(ModelSerializer): 788 # ... 789 # profile = ProfileSerializer() 790 assert not any( 791 isinstance(field, BaseSerializer) and 792 (field.source in validated_data) and 793 (field.source in model_field_info.relations) and 794 isinstance(validated_data[field.source], (list, dict)) 795 for field in serializer._writable_fields 796 ), ( 797 'The `.{method_name}()` method does not support writable nested ' 798 'fields by default.\nWrite an explicit `.{method_name}()` method for ' 799 'serializer `{module}.{class_name}`, or set `read_only=True` on ' 800 'nested serializer fields.'.format( 801 method_name=method_name, 802 module=serializer.__class__.__module__, 803 class_name=serializer.__class__.__name__ 804 ) 805 ) 806 807 # Ensure we don't have a writable dotted-source field. For example: 808 # 809 # class UserSerializer(ModelSerializer): 810 # ... 811 # address = serializer.CharField('profile.address') 812 # 813 # Though, non-relational fields (e.g., JSONField) are acceptable. For example: 814 # 815 # class NonRelationalPersonModel(models.Model): 816 # profile = JSONField() 817 # 818 # class UserSerializer(ModelSerializer): 819 # ... 820 # address = serializer.CharField('profile.address') 821 assert not any( 822 len(field.source_attrs) > 1 and 823 (field.source_attrs[0] in validated_data) and 824 (field.source_attrs[0] in model_field_info.relations) and 825 isinstance(validated_data[field.source_attrs[0]], (list, dict)) 826 for field in serializer._writable_fields 827 ), ( 828 'The `.{method_name}()` method does not support writable dotted-source ' 829 'fields by default.\nWrite an explicit `.{method_name}()` method for ' 830 'serializer `{module}.{class_name}`, or set `read_only=True` on ' 831 'dotted-source serializer fields.'.format( 832 method_name=method_name, 833 module=serializer.__class__.__module__, 834 class_name=serializer.__class__.__name__ 835 ) 836 ) 837 838 839class ModelSerializer(Serializer): 840 """ 841 A `ModelSerializer` is just a regular `Serializer`, except that: 842 843 * A set of default fields are automatically populated. 844 * A set of default validators are automatically populated. 845 * Default `.create()` and `.update()` implementations are provided. 846 847 The process of automatically determining a set of serializer fields 848 based on the model fields is reasonably complex, but you almost certainly 849 don't need to dig into the implementation. 850 851 If the `ModelSerializer` class *doesn't* generate the set of fields that 852 you need you should either declare the extra/differing fields explicitly on 853 the serializer class, or simply use a `Serializer` class. 854 """ 855 serializer_field_mapping = { 856 models.AutoField: IntegerField, 857 models.BigIntegerField: IntegerField, 858 models.BooleanField: BooleanField, 859 models.CharField: CharField, 860 models.CommaSeparatedIntegerField: CharField, 861 models.DateField: DateField, 862 models.DateTimeField: DateTimeField, 863 models.DecimalField: DecimalField, 864 models.DurationField: DurationField, 865 models.EmailField: EmailField, 866 models.Field: ModelField, 867 models.FileField: FileField, 868 models.FloatField: FloatField, 869 models.ImageField: ImageField, 870 models.IntegerField: IntegerField, 871 models.NullBooleanField: BooleanField, 872 models.PositiveIntegerField: IntegerField, 873 models.PositiveSmallIntegerField: IntegerField, 874 models.SlugField: SlugField, 875 models.SmallIntegerField: IntegerField, 876 models.TextField: CharField, 877 models.TimeField: TimeField, 878 models.URLField: URLField, 879 models.UUIDField: UUIDField, 880 models.GenericIPAddressField: IPAddressField, 881 models.FilePathField: FilePathField, 882 } 883 if hasattr(models, 'JSONField'): 884 serializer_field_mapping[models.JSONField] = JSONField 885 if postgres_fields: 886 serializer_field_mapping[postgres_fields.HStoreField] = HStoreField 887 serializer_field_mapping[postgres_fields.ArrayField] = ListField 888 serializer_field_mapping[postgres_fields.JSONField] = JSONField 889 serializer_related_field = PrimaryKeyRelatedField 890 serializer_related_to_field = SlugRelatedField 891 serializer_url_field = HyperlinkedIdentityField 892 serializer_choice_field = ChoiceField 893 894 # The field name for hyperlinked identity fields. Defaults to 'url'. 895 # You can modify this using the API setting. 896 # 897 # Note that if you instead need modify this on a per-serializer basis, 898 # you'll also need to ensure you update the `create` method on any generic 899 # views, to correctly handle the 'Location' response header for 900 # "HTTP 201 Created" responses. 901 url_field_name = None 902 903 # Default `create` and `update` behavior... 904 def create(self, validated_data): 905 """ 906 We have a bit of extra checking around this in order to provide 907 descriptive messages when something goes wrong, but this method is 908 essentially just: 909 910 return ExampleModel.objects.create(**validated_data) 911 912 If there are many to many fields present on the instance then they 913 cannot be set until the model is instantiated, in which case the 914 implementation is like so: 915 916 example_relationship = validated_data.pop('example_relationship') 917 instance = ExampleModel.objects.create(**validated_data) 918 instance.example_relationship = example_relationship 919 return instance 920 921 The default implementation also does not handle nested relationships. 922 If you want to support writable nested relationships you'll need 923 to write an explicit `.create()` method. 924 """ 925 raise_errors_on_nested_writes('create', self, validated_data) 926 927 ModelClass = self.Meta.model 928 929 # Remove many-to-many relationships from validated_data. 930 # They are not valid arguments to the default `.create()` method, 931 # as they require that the instance has already been saved. 932 info = model_meta.get_field_info(ModelClass) 933 many_to_many = {} 934 for field_name, relation_info in info.relations.items(): 935 if relation_info.to_many and (field_name in validated_data): 936 many_to_many[field_name] = validated_data.pop(field_name) 937 938 try: 939 instance = ModelClass._default_manager.create(**validated_data) 940 except TypeError: 941 tb = traceback.format_exc() 942 msg = ( 943 'Got a `TypeError` when calling `%s.%s.create()`. ' 944 'This may be because you have a writable field on the ' 945 'serializer class that is not a valid argument to ' 946 '`%s.%s.create()`. You may need to make the field ' 947 'read-only, or override the %s.create() method to handle ' 948 'this correctly.\nOriginal exception was:\n %s' % 949 ( 950 ModelClass.__name__, 951 ModelClass._default_manager.name, 952 ModelClass.__name__, 953 ModelClass._default_manager.name, 954 self.__class__.__name__, 955 tb 956 ) 957 ) 958 raise TypeError(msg) 959 960 # Save many-to-many relationships after the instance is created. 961 if many_to_many: 962 for field_name, value in many_to_many.items(): 963 field = getattr(instance, field_name) 964 field.set(value) 965 966 return instance 967 968 def update(self, instance, validated_data): 969 raise_errors_on_nested_writes('update', self, validated_data) 970 info = model_meta.get_field_info(instance) 971 972 # Simply set each attribute on the instance, and then save it. 973 # Note that unlike `.create()` we don't need to treat many-to-many 974 # relationships as being a special case. During updates we already 975 # have an instance pk for the relationships to be associated with. 976 m2m_fields = [] 977 for attr, value in validated_data.items(): 978 if attr in info.relations and info.relations[attr].to_many: 979 m2m_fields.append((attr, value)) 980 else: 981 setattr(instance, attr, value) 982 983 instance.save() 984 985 # Note that many-to-many fields are set after updating instance. 986 # Setting m2m fields triggers signals which could potentially change 987 # updated instance and we do not want it to collide with .update() 988 for attr, value in m2m_fields: 989 field = getattr(instance, attr) 990 field.set(value) 991 992 return instance 993 994 # Determine the fields to apply... 995 996 def get_fields(self): 997 """ 998 Return the dict of field names -> field instances that should be 999 used for `self.fields` when instantiating the serializer. 1000 """ 1001 if self.url_field_name is None: 1002 self.url_field_name = api_settings.URL_FIELD_NAME 1003 1004 assert hasattr(self, 'Meta'), ( 1005 'Class {serializer_class} missing "Meta" attribute'.format( 1006 serializer_class=self.__class__.__name__ 1007 ) 1008 ) 1009 assert hasattr(self.Meta, 'model'), ( 1010 'Class {serializer_class} missing "Meta.model" attribute'.format( 1011 serializer_class=self.__class__.__name__ 1012 ) 1013 ) 1014 if model_meta.is_abstract_model(self.Meta.model): 1015 raise ValueError( 1016 'Cannot use ModelSerializer with Abstract Models.' 1017 ) 1018 1019 declared_fields = copy.deepcopy(self._declared_fields) 1020 model = getattr(self.Meta, 'model') 1021 depth = getattr(self.Meta, 'depth', 0) 1022 1023 if depth is not None: 1024 assert depth >= 0, "'depth' may not be negative." 1025 assert depth <= 10, "'depth' may not be greater than 10." 1026 1027 # Retrieve metadata about fields & relationships on the model class. 1028 info = model_meta.get_field_info(model) 1029 field_names = self.get_field_names(declared_fields, info) 1030 1031 # Determine any extra field arguments and hidden fields that 1032 # should be included 1033 extra_kwargs = self.get_extra_kwargs() 1034 extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs( 1035 field_names, declared_fields, extra_kwargs 1036 ) 1037 1038 # Determine the fields that should be included on the serializer. 1039 fields = OrderedDict() 1040 1041 for field_name in field_names: 1042 # If the field is explicitly declared on the class then use that. 1043 if field_name in declared_fields: 1044 fields[field_name] = declared_fields[field_name] 1045 continue 1046 1047 extra_field_kwargs = extra_kwargs.get(field_name, {}) 1048 source = extra_field_kwargs.get('source', '*') 1049 if source == '*': 1050 source = field_name 1051 1052 # Determine the serializer field class and keyword arguments. 1053 field_class, field_kwargs = self.build_field( 1054 source, info, model, depth 1055 ) 1056 1057 # Include any kwargs defined in `Meta.extra_kwargs` 1058 field_kwargs = self.include_extra_kwargs( 1059 field_kwargs, extra_field_kwargs 1060 ) 1061 1062 # Create the serializer field. 1063 fields[field_name] = field_class(**field_kwargs) 1064 1065 # Add in any hidden fields. 1066 fields.update(hidden_fields) 1067 1068 return fields 1069 1070 # Methods for determining the set of field names to include... 1071 1072 def get_field_names(self, declared_fields, info): 1073 """ 1074 Returns the list of all field names that should be created when 1075 instantiating this serializer class. This is based on the default 1076 set of fields, but also takes into account the `Meta.fields` or 1077 `Meta.exclude` options if they have been specified. 1078 """ 1079 fields = getattr(self.Meta, 'fields', None) 1080 exclude = getattr(self.Meta, 'exclude', None) 1081 1082 if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)): 1083 raise TypeError( 1084 'The `fields` option must be a list or tuple or "__all__". ' 1085 'Got %s.' % type(fields).__name__ 1086 ) 1087 1088 if exclude and not isinstance(exclude, (list, tuple)): 1089 raise TypeError( 1090 'The `exclude` option must be a list or tuple. Got %s.' % 1091 type(exclude).__name__ 1092 ) 1093 1094 assert not (fields and exclude), ( 1095 "Cannot set both 'fields' and 'exclude' options on " 1096 "serializer {serializer_class}.".format( 1097 serializer_class=self.__class__.__name__ 1098 ) 1099 ) 1100 1101 assert not (fields is None and exclude is None), ( 1102 "Creating a ModelSerializer without either the 'fields' attribute " 1103 "or the 'exclude' attribute has been deprecated since 3.3.0, " 1104 "and is now disallowed. Add an explicit fields = '__all__' to the " 1105 "{serializer_class} serializer.".format( 1106 serializer_class=self.__class__.__name__ 1107 ), 1108 ) 1109 1110 if fields == ALL_FIELDS: 1111 fields = None 1112 1113 if fields is not None: 1114 # Ensure that all declared fields have also been included in the 1115 # `Meta.fields` option. 1116 1117 # Do not require any fields that are declared in a parent class, 1118 # in order to allow serializer subclasses to only include 1119 # a subset of fields. 1120 required_field_names = set(declared_fields) 1121 for cls in self.__class__.__bases__: 1122 required_field_names -= set(getattr(cls, '_declared_fields', [])) 1123 1124 for field_name in required_field_names: 1125 assert field_name in fields, ( 1126 "The field '{field_name}' was declared on serializer " 1127 "{serializer_class}, but has not been included in the " 1128 "'fields' option.".format( 1129 field_name=field_name, 1130 serializer_class=self.__class__.__name__ 1131 ) 1132 ) 1133 return fields 1134 1135 # Use the default set of field names if `Meta.fields` is not specified. 1136 fields = self.get_default_field_names(declared_fields, info) 1137 1138 if exclude is not None: 1139 # If `Meta.exclude` is included, then remove those fields. 1140 for field_name in exclude: 1141 assert field_name not in self._declared_fields, ( 1142 "Cannot both declare the field '{field_name}' and include " 1143 "it in the {serializer_class} 'exclude' option. Remove the " 1144 "field or, if inherited from a parent serializer, disable " 1145 "with `{field_name} = None`." 1146 .format( 1147 field_name=field_name, 1148 serializer_class=self.__class__.__name__ 1149 ) 1150 ) 1151 1152 assert field_name in fields, ( 1153 "The field '{field_name}' was included on serializer " 1154 "{serializer_class} in the 'exclude' option, but does " 1155 "not match any model field.".format( 1156 field_name=field_name, 1157 serializer_class=self.__class__.__name__ 1158 ) 1159 ) 1160 fields.remove(field_name) 1161 1162 return fields 1163 1164 def get_default_field_names(self, declared_fields, model_info): 1165 """ 1166 Return the default list of field names that will be used if the 1167 `Meta.fields` option is not specified. 1168 """ 1169 return ( 1170 [model_info.pk.name] + 1171 list(declared_fields) + 1172 list(model_info.fields) + 1173 list(model_info.forward_relations) 1174 ) 1175 1176 # Methods for constructing serializer fields... 1177 1178 def build_field(self, field_name, info, model_class, nested_depth): 1179 """ 1180 Return a two tuple of (cls, kwargs) to build a serializer field with. 1181 """ 1182 if field_name in info.fields_and_pk: 1183 model_field = info.fields_and_pk[field_name] 1184 return self.build_standard_field(field_name, model_field) 1185 1186 elif field_name in info.relations: 1187 relation_info = info.relations[field_name] 1188 if not nested_depth: 1189 return self.build_relational_field(field_name, relation_info) 1190 else: 1191 return self.build_nested_field(field_name, relation_info, nested_depth) 1192 1193 elif hasattr(model_class, field_name): 1194 return self.build_property_field(field_name, model_class) 1195 1196 elif field_name == self.url_field_name: 1197 return self.build_url_field(field_name, model_class) 1198 1199 return self.build_unknown_field(field_name, model_class) 1200 1201 def build_standard_field(self, field_name, model_field): 1202 """ 1203 Create regular model fields. 1204 """ 1205 field_mapping = ClassLookupDict(self.serializer_field_mapping) 1206 1207 field_class = field_mapping[model_field] 1208 field_kwargs = get_field_kwargs(field_name, model_field) 1209 1210 # Special case to handle when a OneToOneField is also the primary key 1211 if model_field.one_to_one and model_field.primary_key: 1212 field_class = self.serializer_related_field 1213 field_kwargs['queryset'] = model_field.related_model.objects 1214 1215 if 'choices' in field_kwargs: 1216 # Fields with choices get coerced into `ChoiceField` 1217 # instead of using their regular typed field. 1218 field_class = self.serializer_choice_field 1219 # Some model fields may introduce kwargs that would not be valid 1220 # for the choice field. We need to strip these out. 1221 # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES) 1222 valid_kwargs = { 1223 'read_only', 'write_only', 1224 'required', 'default', 'initial', 'source', 1225 'label', 'help_text', 'style', 1226 'error_messages', 'validators', 'allow_null', 'allow_blank', 1227 'choices' 1228 } 1229 for key in list(field_kwargs): 1230 if key not in valid_kwargs: 1231 field_kwargs.pop(key) 1232 1233 if not issubclass(field_class, ModelField): 1234 # `model_field` is only valid for the fallback case of 1235 # `ModelField`, which is used when no other typed field 1236 # matched to the model field. 1237 field_kwargs.pop('model_field', None) 1238 1239 if not issubclass(field_class, CharField) and not issubclass(field_class, ChoiceField): 1240 # `allow_blank` is only valid for textual fields. 1241 field_kwargs.pop('allow_blank', None) 1242 1243 is_django_jsonfield = hasattr(models, 'JSONField') and isinstance(model_field, models.JSONField) 1244 if (postgres_fields and isinstance(model_field, postgres_fields.JSONField)) or is_django_jsonfield: 1245 # Populate the `encoder` argument of `JSONField` instances generated 1246 # for the model `JSONField`. 1247 field_kwargs['encoder'] = getattr(model_field, 'encoder', None) 1248 if is_django_jsonfield: 1249 field_kwargs['decoder'] = getattr(model_field, 'decoder', None) 1250 1251 if postgres_fields and isinstance(model_field, postgres_fields.ArrayField): 1252 # Populate the `child` argument on `ListField` instances generated 1253 # for the PostgreSQL specific `ArrayField`. 1254 child_model_field = model_field.base_field 1255 child_field_class, child_field_kwargs = self.build_standard_field( 1256 'child', child_model_field 1257 ) 1258 field_kwargs['child'] = child_field_class(**child_field_kwargs) 1259 1260 return field_class, field_kwargs 1261 1262 def build_relational_field(self, field_name, relation_info): 1263 """ 1264 Create fields for forward and reverse relationships. 1265 """ 1266 field_class = self.serializer_related_field 1267 field_kwargs = get_relation_kwargs(field_name, relation_info) 1268 1269 to_field = field_kwargs.pop('to_field', None) 1270 if to_field and not relation_info.reverse and not relation_info.related_model._meta.get_field(to_field).primary_key: 1271 field_kwargs['slug_field'] = to_field 1272 field_class = self.serializer_related_to_field 1273 1274 # `view_name` is only valid for hyperlinked relationships. 1275 if not issubclass(field_class, HyperlinkedRelatedField): 1276 field_kwargs.pop('view_name', None) 1277 1278 return field_class, field_kwargs 1279 1280 def build_nested_field(self, field_name, relation_info, nested_depth): 1281 """ 1282 Create nested fields for forward and reverse relationships. 1283 """ 1284 class NestedSerializer(ModelSerializer): 1285 class Meta: 1286 model = relation_info.related_model 1287 depth = nested_depth - 1 1288 fields = '__all__' 1289 1290 field_class = NestedSerializer 1291 field_kwargs = get_nested_relation_kwargs(relation_info) 1292 1293 return field_class, field_kwargs 1294 1295 def build_property_field(self, field_name, model_class): 1296 """ 1297 Create a read only field for model methods and properties. 1298 """ 1299 field_class = ReadOnlyField 1300 field_kwargs = {} 1301 1302 return field_class, field_kwargs 1303 1304 def build_url_field(self, field_name, model_class): 1305 """ 1306 Create a field representing the object's own URL. 1307 """ 1308 field_class = self.serializer_url_field 1309 field_kwargs = get_url_kwargs(model_class) 1310 1311 return field_class, field_kwargs 1312 1313 def build_unknown_field(self, field_name, model_class): 1314 """ 1315 Raise an error on any unknown fields. 1316 """ 1317 raise ImproperlyConfigured( 1318 'Field name `%s` is not valid for model `%s`.' % 1319 (field_name, model_class.__name__) 1320 ) 1321 1322 def include_extra_kwargs(self, kwargs, extra_kwargs): 1323 """ 1324 Include any 'extra_kwargs' that have been included for this field, 1325 possibly removing any incompatible existing keyword arguments. 1326 """ 1327 if extra_kwargs.get('read_only', False): 1328 for attr in [ 1329 'required', 'default', 'allow_blank', 'allow_null', 1330 'min_length', 'max_length', 'min_value', 'max_value', 1331 'validators', 'queryset' 1332 ]: 1333 kwargs.pop(attr, None) 1334 1335 if extra_kwargs.get('default') and kwargs.get('required') is False: 1336 kwargs.pop('required') 1337 1338 if extra_kwargs.get('read_only', kwargs.get('read_only', False)): 1339 extra_kwargs.pop('required', None) # Read only fields should always omit the 'required' argument. 1340 1341 kwargs.update(extra_kwargs) 1342 1343 return kwargs 1344 1345 # Methods for determining additional keyword arguments to apply... 1346 1347 def get_extra_kwargs(self): 1348 """ 1349 Return a dictionary mapping field names to a dictionary of 1350 additional keyword arguments. 1351 """ 1352 extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {})) 1353 1354 read_only_fields = getattr(self.Meta, 'read_only_fields', None) 1355 if read_only_fields is not None: 1356 if not isinstance(read_only_fields, (list, tuple)): 1357 raise TypeError( 1358 'The `read_only_fields` option must be a list or tuple. ' 1359 'Got %s.' % type(read_only_fields).__name__ 1360 ) 1361 for field_name in read_only_fields: 1362 kwargs = extra_kwargs.get(field_name, {}) 1363 kwargs['read_only'] = True 1364 extra_kwargs[field_name] = kwargs 1365 1366 else: 1367 # Guard against the possible misspelling `readonly_fields` (used 1368 # by the Django admin and others). 1369 assert not hasattr(self.Meta, 'readonly_fields'), ( 1370 'Serializer `%s.%s` has field `readonly_fields`; ' 1371 'the correct spelling for the option is `read_only_fields`.' % 1372 (self.__class__.__module__, self.__class__.__name__) 1373 ) 1374 1375 return extra_kwargs 1376 1377 def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs): 1378 """ 1379 Return any additional field options that need to be included as a 1380 result of uniqueness constraints on the model. This is returned as 1381 a two-tuple of: 1382 1383 ('dict of updated extra kwargs', 'mapping of hidden fields') 1384 """ 1385 if getattr(self.Meta, 'validators', None) is not None: 1386 return (extra_kwargs, {}) 1387 1388 model = getattr(self.Meta, 'model') 1389 model_fields = self._get_model_fields( 1390 field_names, declared_fields, extra_kwargs 1391 ) 1392 1393 # Determine if we need any additional `HiddenField` or extra keyword 1394 # arguments to deal with `unique_for` dates that are required to 1395 # be in the input data in order to validate it. 1396 unique_constraint_names = set() 1397 1398 for model_field in model_fields.values(): 1399 # Include each of the `unique_for_*` field names. 1400 unique_constraint_names |= {model_field.unique_for_date, model_field.unique_for_month, 1401 model_field.unique_for_year} 1402 1403 unique_constraint_names -= {None} 1404 1405 # Include each of the `unique_together` field names, 1406 # so long as all the field names are included on the serializer. 1407 for parent_class in [model] + list(model._meta.parents): 1408 for unique_together_list in parent_class._meta.unique_together: 1409 if set(field_names).issuperset(unique_together_list): 1410 unique_constraint_names |= set(unique_together_list) 1411 1412 # Now we have all the field names that have uniqueness constraints 1413 # applied, we can add the extra 'required=...' or 'default=...' 1414 # arguments that are appropriate to these fields, or add a `HiddenField` for it. 1415 hidden_fields = {} 1416 uniqueness_extra_kwargs = {} 1417 1418 for unique_constraint_name in unique_constraint_names: 1419 # Get the model field that is referred too. 1420 unique_constraint_field = model._meta.get_field(unique_constraint_name) 1421 1422 if getattr(unique_constraint_field, 'auto_now_add', None): 1423 default = CreateOnlyDefault(timezone.now) 1424 elif getattr(unique_constraint_field, 'auto_now', None): 1425 default = timezone.now 1426 elif unique_constraint_field.has_default(): 1427 default = unique_constraint_field.default 1428 else: 1429 default = empty 1430 1431 if unique_constraint_name in model_fields: 1432 # The corresponding field is present in the serializer 1433 if default is empty: 1434 uniqueness_extra_kwargs[unique_constraint_name] = {'required': True} 1435 else: 1436 uniqueness_extra_kwargs[unique_constraint_name] = {'default': default} 1437 elif default is not empty: 1438 # The corresponding field is not present in the 1439 # serializer. We have a default to use for it, so 1440 # add in a hidden field that populates it. 1441 hidden_fields[unique_constraint_name] = HiddenField(default=default) 1442 1443 # Update `extra_kwargs` with any new options. 1444 for key, value in uniqueness_extra_kwargs.items(): 1445 if key in extra_kwargs: 1446 value.update(extra_kwargs[key]) 1447 extra_kwargs[key] = value 1448 1449 return extra_kwargs, hidden_fields 1450 1451 def _get_model_fields(self, field_names, declared_fields, extra_kwargs): 1452 """ 1453 Returns all the model fields that are being mapped to by fields 1454 on the serializer class. 1455 Returned as a dict of 'model field name' -> 'model field'. 1456 Used internally by `get_uniqueness_field_options`. 1457 """ 1458 model = getattr(self.Meta, 'model') 1459 model_fields = {} 1460 1461 for field_name in field_names: 1462 if field_name in declared_fields: 1463 # If the field is declared on the serializer 1464 field = declared_fields[field_name] 1465 source = field.source or field_name 1466 else: 1467 try: 1468 source = extra_kwargs[field_name]['source'] 1469 except KeyError: 1470 source = field_name 1471 1472 if '.' in source or source == '*': 1473 # Model fields will always have a simple source mapping, 1474 # they can't be nested attribute lookups. 1475 continue 1476 1477 try: 1478 field = model._meta.get_field(source) 1479 if isinstance(field, DjangoModelField): 1480 model_fields[source] = field 1481 except FieldDoesNotExist: 1482 pass 1483 1484 return model_fields 1485 1486 # Determine the validators to apply... 1487 1488 def get_validators(self): 1489 """ 1490 Determine the set of validators to use when instantiating serializer. 1491 """ 1492 # If the validators have been declared explicitly then use that. 1493 validators = getattr(getattr(self, 'Meta', None), 'validators', None) 1494 if validators is not None: 1495 return list(validators) 1496 1497 # Otherwise use the default set of validators. 1498 return ( 1499 self.get_unique_together_validators() + 1500 self.get_unique_for_date_validators() 1501 ) 1502 1503 def get_unique_together_validators(self): 1504 """ 1505 Determine a default set of validators for any unique_together constraints. 1506 """ 1507 model_class_inheritance_tree = ( 1508 [self.Meta.model] + 1509 list(self.Meta.model._meta.parents) 1510 ) 1511 1512 # The field names we're passing though here only include fields 1513 # which may map onto a model field. Any dotted field name lookups 1514 # cannot map to a field, and must be a traversal, so we're not 1515 # including those. 1516 field_sources = OrderedDict( 1517 (field.field_name, field.source) for field in self._writable_fields 1518 if (field.source != '*') and ('.' not in field.source) 1519 ) 1520 1521 # Special Case: Add read_only fields with defaults. 1522 field_sources.update(OrderedDict( 1523 (field.field_name, field.source) for field in self.fields.values() 1524 if (field.read_only) and (field.default != empty) and (field.source != '*') and ('.' not in field.source) 1525 )) 1526 1527 # Invert so we can find the serializer field names that correspond to 1528 # the model field names in the unique_together sets. This also allows 1529 # us to check that multiple fields don't map to the same source. 1530 source_map = defaultdict(list) 1531 for name, source in field_sources.items(): 1532 source_map[source].append(name) 1533 1534 # Note that we make sure to check `unique_together` both on the 1535 # base model class, but also on any parent classes. 1536 validators = [] 1537 for parent_class in model_class_inheritance_tree: 1538 for unique_together in parent_class._meta.unique_together: 1539 # Skip if serializer does not map to all unique together sources 1540 if not set(source_map).issuperset(unique_together): 1541 continue 1542 1543 for source in unique_together: 1544 assert len(source_map[source]) == 1, ( 1545 "Unable to create `UniqueTogetherValidator` for " 1546 "`{model}.{field}` as `{serializer}` has multiple " 1547 "fields ({fields}) that map to this model field. " 1548 "Either remove the extra fields, or override " 1549 "`Meta.validators` with a `UniqueTogetherValidator` " 1550 "using the desired field names." 1551 .format( 1552 model=self.Meta.model.__name__, 1553 serializer=self.__class__.__name__, 1554 field=source, 1555 fields=', '.join(source_map[source]), 1556 ) 1557 ) 1558 1559 field_names = tuple(source_map[f][0] for f in unique_together) 1560 validator = UniqueTogetherValidator( 1561 queryset=parent_class._default_manager, 1562 fields=field_names 1563 ) 1564 validators.append(validator) 1565 return validators 1566 1567 def get_unique_for_date_validators(self): 1568 """ 1569 Determine a default set of validators for the following constraints: 1570 1571 * unique_for_date 1572 * unique_for_month 1573 * unique_for_year 1574 """ 1575 info = model_meta.get_field_info(self.Meta.model) 1576 default_manager = self.Meta.model._default_manager 1577 field_names = [field.source for field in self.fields.values()] 1578 1579 validators = [] 1580 1581 for field_name, field in info.fields_and_pk.items(): 1582 if field.unique_for_date and field_name in field_names: 1583 validator = UniqueForDateValidator( 1584 queryset=default_manager, 1585 field=field_name, 1586 date_field=field.unique_for_date 1587 ) 1588 validators.append(validator) 1589 1590 if field.unique_for_month and field_name in field_names: 1591 validator = UniqueForMonthValidator( 1592 queryset=default_manager, 1593 field=field_name, 1594 date_field=field.unique_for_month 1595 ) 1596 validators.append(validator) 1597 1598 if field.unique_for_year and field_name in field_names: 1599 validator = UniqueForYearValidator( 1600 queryset=default_manager, 1601 field=field_name, 1602 date_field=field.unique_for_year 1603 ) 1604 validators.append(validator) 1605 1606 return validators 1607 1608 1609class HyperlinkedModelSerializer(ModelSerializer): 1610 """ 1611 A type of `ModelSerializer` that uses hyperlinked relationships instead 1612 of primary key relationships. Specifically: 1613 1614 * A 'url' field is included instead of the 'id' field. 1615 * Relationships to other instances are hyperlinks, instead of primary keys. 1616 """ 1617 serializer_related_field = HyperlinkedRelatedField 1618 1619 def get_default_field_names(self, declared_fields, model_info): 1620 """ 1621 Return the default list of field names that will be used if the 1622 `Meta.fields` option is not specified. 1623 """ 1624 return ( 1625 [self.url_field_name] + 1626 list(declared_fields) + 1627 list(model_info.fields) + 1628 list(model_info.forward_relations) 1629 ) 1630 1631 def build_nested_field(self, field_name, relation_info, nested_depth): 1632 """ 1633 Create nested fields for forward and reverse relationships. 1634 """ 1635 class NestedSerializer(HyperlinkedModelSerializer): 1636 class Meta: 1637 model = relation_info.related_model 1638 depth = nested_depth - 1 1639 fields = '__all__' 1640 1641 field_class = NestedSerializer 1642 field_kwargs = get_nested_relation_kwargs(relation_info) 1643 1644 return field_class, field_kwargs 1645