U
    ڲg                    @   s|  d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m
Z
mZ ddl	mZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZmZ ddlmZ ddl m!Z! ddl"m#Z#m$Z$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5m6Z6m7Z7 ddlm8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mZmAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZS ddlTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[ ddlm\Z\m]Z]m^Z^m_Z_ ddlTm`Z`maZa dZbdZcdZdG dd deZeG dd defZgdd  ZhG d!d" d"eeegd#ZiG d$d% d%eeZjd&d' ZkG d(d) d)eiZlG d*d+ d+elZmdS ),a  
Serializers and ModelSerializers are similar to Forms and ModelForms.
Unlike forms, they are not constrained to dealing with HTML output, and
form encoded input.

Serialization in REST framework is a two-phase process:

1. Serializers marshal between complex types like model instances, and
python primitives.
2. The process of marshalling between python primitives and request and
response content is handled by parsers and renderers.
    N)defaultdict)Mapping)FieldDoesNotExistImproperlyConfigured)ValidationError)models)Field)timezone)cached_property)gettext_lazy)postgres_fields)ErrorDetailr   )get_error_detail)api_settings)html
model_metarepresentation)ClassLookupDictget_field_kwargsget_nested_relation_kwargsget_relation_kwargsget_url_kwargs)BindingDict
BoundFieldJSONBoundFieldNestedBoundField
ReturnDict
ReturnList)UniqueForDateValidatorUniqueForMonthValidatorUniqueForYearValidatorUniqueTogetherValidator)BooleanField	CharFieldChoiceField	DateFieldDateTimeFieldDecimalField	DictFieldDurationField
EmailFieldr   	FileFieldFilePathField
FloatFieldHiddenFieldHStoreFieldIPAddressField
ImageFieldIntegerField	JSONField	ListField
ModelFieldMultipleChoiceFieldReadOnlyField
RegexFieldSerializerMethodField	SlugField	TimeFieldURLField	UUIDField)HyperlinkedIdentityFieldHyperlinkedRelatedFieldManyRelatedFieldPrimaryKeyRelatedFieldRelatedFieldSlugRelatedFieldStringRelatedField)CreateOnlyDefaultCurrentUserDefault	SkipFieldempty)	HyperlinkPKOnlyObject)	read_only
write_onlyrequireddefaultinitialsourcelabel	help_textstyleerror_messagesallow_emptyinstancedatapartialcontext
allow_null
max_length
min_length)rU   r\   r[   __all__c                       s   e Zd ZdZdef fdd	Z fddZdd Zed	d
 Z	dd Z
dd Zdd Zdd Zdd ZddddZedd Zedd Zedd Z  ZS )BaseSerializera  
    The BaseSerializer class provides a minimal class which may be used
    for writing custom serializer implementations.

    Note that we strongly restrict the ordering of operations/properties
    that may be used on the serializer in order to enforce correct usage.

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

    .is_valid() - Available.
    .initial_data - Available.
    .validated_data - Only available after calling `is_valid()`
    .errors - Only available after calling `is_valid()`
    .data - Only available after calling `is_valid()`

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

    .is_valid() - Not available.
    .initial_data - Not available.
    .validated_data - Not available.
    .errors - Not available.
    .data - Available.
    Nc                    sN   || _ |tk	r|| _|dd| _|di | _|dd  t jf | d S )NrX   FrY   many)rV   rH   initial_datapoprX   _contextsuper__init__)selfrV   rW   kwargs	__class__ >/tmp/pip-unpacked-wheel-11h17kvo/rest_framework/serializers.pyrd   p   s    zBaseSerializer.__init__c                    s,   | ddr| j||S t j| f||S )Nr_   F)ra   	many_initrc   __new__clsargsrf   rg   ri   rj   rl   y   s    zBaseSerializer.__new__c                 O   s   | S Nri   rm   ri   ri   rj   __class_getitem__   s    z BaseSerializer.__class_getitem__c                 O   sr   i }t D ] }||d}|dk	r|||< q| |||d< |dd | D  t| dd}t|dt}|||S )a  
        This method implements the creation of a `ListSerializer` parent
        class when `many=True` is used. You can customize it if you need to
        control which keyword arguments are passed to the parent, and
        which are passed to the child.

        Note that we're over-cautious in passing most arguments to both parent
        and child classes in order to try to cover the general case. If you're
        overriding this method you'll probably want something much simpler, eg:

        @classmethod
        def many_init(cls, *args, **kwargs):
            kwargs['child'] = cls()
            return CustomListSerializer(*args, **kwargs)
        Nchildc                 S   s   i | ]\}}|t kr||qS ri   )LIST_SERIALIZER_KWARGS.0keyvalueri   ri   rj   
<dictcomp>   s    z,BaseSerializer.many_init.<locals>.<dictcomp>Metalist_serializer_class)LIST_SERIALIZER_KWARGS_REMOVEra   updateitemsgetattrListSerializer)rn   ro   rf   Zlist_kwargsrv   rw   metarz   ri   ri   rj   rk      s    

zBaseSerializer.many_initc                 C   s   t dd S )Nz*`to_internal_value()` must be implemented.NotImplementedErrorre   rW   ri   ri   rj   to_internal_value   s    z BaseSerializer.to_internal_valuec                 C   s   t dd S )Nz*`to_representation()` must be implemented.r   )re   rV   ri   ri   rj   to_representation   s    z BaseSerializer.to_representationc                 C   s   t dd S )Nz`update()` must be implemented.r   re   rV   validated_datari   ri   rj   r|      s    zBaseSerializer.updatec                 C   s   t dd S )Nz`create()` must be implemented.r   re   r   ri   ri   rj   create   s    zBaseSerializer.createc                 K   s   t | dstd| jr tdd|ks0tdt | drBtd| j|}| jd k	rz| | j|| _| jd k	stdn| || _| jd k	std	| jS )
N_errorsz5You must call `.is_valid()` before calling `.save()`.z<You cannot call `.save()` on a serializer with invalid data.commit`  'commit' is not a valid keyword argument to the 'save()' method. If you need to access data before committing to the database then inspect 'serializer.validated_data' instead. You can also pass additional keyword arguments to 'save()' if you need to set extra attributes on the saved model instance. For example: 'serializer.save(owner=request.user)'.'_datazYou cannot call `.save()` after accessing `serializer.data`.If you need to access data before committing to the database then inspect 'serializer.validated_data' instead. -`update()` did not return an object instance.-`create()` did not return an object instance.)hasattrAssertionErrorerrorsr   rV   r|   r   re   rf   r   ri   ri   rj   save   s.    
	

zBaseSerializer.saveFraise_exceptionc             
   C   s   t | dstdt | dsfz| | j| _W n0 tk
r^ } zi | _|j| _W 5 d }~X Y nX i | _| jrz|rzt| jt	| j S Nr`   zoCannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance._validated_data
r   r   run_validationr`   r   r   detailr   r   boolre   r   excri   ri   rj   is_valid   s    


zBaseSerializer.is_validc                 C   s   t | dr t | ds d}t|t | ds| jd k	rPt| dd sP| | j| _n0t | drvt| dd sv| | j| _n
|  | _| jS )Nr`   r   zWhen a serializer is passed a `data` keyword argument you must call `.is_valid()` before attempting to access the serialized `.data` representation.
You should either call `.is_valid()` first, or access `.initial_data` instead.r   r   )r   r   rV   r~   r   r   r   get_initialre   msgri   ri   rj   rW      s    

zBaseSerializer.datac                 C   s   t | dsd}t|| jS )Nr   z7You must call `.is_valid()` before accessing `.errors`.)r   r   r   r   ri   ri   rj   r      s    
zBaseSerializer.errorsc                 C   s   t | dsd}t|| jS )Nr   z?You must call `.is_valid()` before accessing `.validated_data`.)r   r   r   r   ri   ri   rj   r     s    
zBaseSerializer.validated_data)__name__
__module____qualname____doc__rH   rd   rl   rq   classmethodrk   r   r   r|   r   r   r   propertyrW   r   r   __classcell__ri   ri   rg   rj   r^   W   s$   	
(

r^   c                       s,   e Zd ZdZedd Z fddZ  ZS )SerializerMetaclassz
    This metaclass sets a dictionary named `_declared_fields` on the class.

    Any instances of `Field` included as attributes on either the class
    or on any of its superclasses will be include in the
    `_declared_fields` dictionary.
    c                    s^    fddt   D }|jdd d t fddfdd|D }t|| S )	Nc                    s(   g | ] \}}t |tr| |fqS ri   )
isinstancer   ra   )ru   
field_nameobj)attrsri   rj   
<listcomp>  s   
z<SerializerMetaclass._get_declared_fields.<locals>.<listcomp>c                 S   s
   | d j S )N   )Z_creation_counter)xri   ri   rj   <lambda>       z:SerializerMetaclass._get_declared_fields.<locals>.<lambda>)rv   c                    s     |  | S rp   )add)name)knownri   rj   visit'  s    
z7SerializerMetaclass._get_declared_fields.<locals>.visitc                    s>   g | ]6}t |d r|j D ]\}}| kr||fqqS )_declared_fields)r   r   r}   )ru   baser   f)r   r   ri   rj   r   +  s    
  )listr}   sortsetdict)rn   basesr   fieldsZbase_fieldsri   )r   r   r   rj   _get_declared_fields  s    

z(SerializerMetaclass._get_declared_fieldsc                    s"   |  |||d< t | |||S )Nr   )r   rc   rl   )rn   r   r   r   rg   ri   rj   rl   3  s    zSerializerMetaclass.__new__)r   r   r   r   r   r   rl   r   ri   ri   rg   rj   r     s   
r   c                 C   sh   t | ttfstt | tr&t| }n| j}t |trHdd | D S t |tr\t	j
|iS t	j
|giS )Nc                 S   s*   i | ]"\}}|t |ttfr |n|gqS ri   )r   r   r   rt   ri   ri   rj   rx   C  s    z'as_serializer_error.<locals>.<dictcomp>)r   r   DjangoValidationErrorr   r   r   r   r}   r   r   NON_FIELD_ERRORS_KEY)r   r   ri   ri   rj   as_serializer_error8  s    



  r   c                       s   e Zd ZdediZdd Zedd Zedd Z	ed	d
 Z
dd Zdd Zdd Zdd ZefddZdd Z fddZdd Zdd Zdd Zdd  Zd!d" Zd#d$ Ze fd%d&Ze fd'd(Z  ZS ))
Serializerinvalidz8Invalid data. Expected a dictionary, but got {datatype}.c                 C   sL   |s| | dS |dd D ]}||kr2i ||< || }q|||d < dS )aI  
        Similar to Python's built in `dictionary[key] = value`,
        but takes a list of nested keys instead of a single key.

        set_value({'a': 1}, [], {'b': 2}) -> {'a': 1, 'b': 2}
        set_value({'a': 1}, ['x'], 2) -> {'a': 1, 'x': 2}
        set_value({'a': 1}, ['x', 'y'], 2) -> {'a': 1, 'x': {'y': 2}}
        N)r|   )re   
dictionarykeysrw   rv   ri   ri   rj   	set_valueW  s    	

zSerializer.set_valuec                 C   s*   t | }|   D ]\}}|||< q|S )z?
        A dictionary of {field_name: field_instance}.
        )r   
get_fieldsr}   )re   r   rv   rw   ri   ri   rj   r   k  s    
zSerializer.fieldsc                 c   s    | j  D ]}|js
|V  q
d S rp   )r   valuesrK   re   fieldri   ri   rj   _writable_fieldsx  s    zSerializer._writable_fieldsc                 c   s    | j  D ]}|js
|V  q
d S rp   )r   r   rL   r   ri   ri   rj   _readable_fields~  s    zSerializer._readable_fieldsc                 C   s   t | jS )zG
        Returns a dictionary of {field_name: field_instance}.
        )copydeepcopyr   re   ri   ri   rj   r     s    zSerializer.get_fieldsc                 C   s(   t | dd}t |dd}|r$t|S g S )z8
        Returns a list of validator callables.
        ry   N
validators)r~   r   )re   r   r   ri   ri   rj   get_validators  s    zSerializer.get_validatorsc                    sF   t  dr2t jtsi S  fdd j D S dd  j D S )Nr`   c                    s4   i | ],\}}|  jtk	r|js||  jqS ri   )	get_valuer`   rH   rK   )ru   r   r   r   ri   rj   rx     s
    z*Serializer.get_initial.<locals>.<dictcomp>c                 S   s   i | ]}|j s|j| qS ri   )rK   r   r   ru   r   ri   ri   rj   rx     s    )r   r   r`   r   r   r}   r   r   ri   r   rj   r     s    

zSerializer.get_initialc                 C   s,   t |rt j|| jdptS || jtS )N)prefix)r   is_html_inputZparse_html_dictr   rH   getre   r   ri   ri   rj   r     s    
zSerializer.get_valuec              
   C   s   |  |\}}|r|S | |}z(| | | |}|dk	sFtdW n4 ttfk
r| } ztt|dW 5 d}~X Y nX |S z
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        Nz,.validate() should return the validated data)r   Zvalidate_empty_valuesr   run_validatorsvalidater   r   r   r   re   rW   Zis_empty_valuerw   r   ri   ri   rj   r     s    


 zSerializer.run_validationc              	   C   sV   dd | j  D }i }|D ]4}z| }W n tk
rD   Y qY nX |||j< q|S )Nc                 S   s4   g | ],}|j r|jtkr|jd krd|jkr|qS *.)rK   rN   rH   rP   r   ri   ri   rj   r     s    
 
 
z2Serializer._read_only_defaults.<locals>.<listcomp>)r   r   get_defaultrG   rP   )re   r   defaultsr   rN   ri   ri   rj   _read_only_defaults  s    
zSerializer._read_only_defaultsc                    s2   t |tr|  }|| n|}t | dS )zX
        Add read_only fields with defaults to value before running validators.
        N)r   r   r   r|   rc   r   )re   rw   Zto_validaterg   ri   rj   r     s
    
zSerializer.run_validatorsc                 C   s  t |ts6| jd jt|jd}ttj|giddi }i }| j	}|D ]}t
| d|j d}||}z||}	|dk	r||	}	W nn tk
r }
 z|
j||j< W 5 d}
~
X Y qH tk
r }
 zt|
||j< W 5 d}
~
X Y qH tk
r   Y qHX | ||j|	 qH|rt||S )zG
        Dict of native values <- Dict of primitive datatypes.
        r   )datatypecodeZ	validate_N)r   r   rT   formattyper   r   r   r   r   r~   r   r   r   r   r   r   rG   r   source_attrs)re   rW   messageretr   r   r   Zvalidate_methodZprimitive_valueZvalidated_valuer   ri   ri   rj   r     s<    

 

zSerializer.to_internal_valuec              	   C   sx   i }| j }|D ]d}z||}W n tk
r8   Y qY nX t|trJ|jn|}|dkrbd||j< q||||j< q|S )zA
        Object instance -> Dict of primitive datatypes.
        N)r   Zget_attributerG   r   rJ   pkr   r   )re   rV   r   r   r   	attributeZcheck_for_noneri   ri   rj   r     s    
zSerializer.to_representationc                 C   s   |S rp   ri   re   r   ri   ri   rj   r     s    zSerializer.validatec                 C   s   t j| ddS Nr   )indent)r   Zserializer_reprr   ri   ri   rj   __repr__!  s    zSerializer.__repr__c                 c   s    | j  D ]}| |j V  q
d S rp   )r   r   r   r   ri   ri   rj   __iter__(  s    zSerializer.__iter__c                 C   sh   | j | }| j|}t| dr,| j|nd }t|trFt|||S t|tr\t	|||S t
|||S )Nr   )r   rW   r   r   r   r   r   r   r3   r   r   )re   rv   r   rw   errorri   ri   rj   __getitem__,  s    


zSerializer.__getitem__c                    s   t  j}t|| dS N
serializer)rc   rW   r   re   r   rg   ri   rj   rW   9  s    zSerializer.datac                    sV   t  j}t|trJt|dkrJt|d dd dkrJtddd}tj|gi}t	|| dS Nr   r   r   nullzNo data providedr   r   )
rc   r   r   r   lenr~   r   r   r   r   re   r   r   rg   ri   rj   r   >  s
    *zSerializer.errors)r   r   r   _default_error_messagesr   r
   r   r   r   r   r   r   r   r   rH   r   r   r   r   r   r   r   r   r   rW   r   r   ri   ri   rg   rj   r   R  s6    


		%r   )	metaclassc                       s   e Zd ZdZdZededededdZ fdd	Zd
d Zdd Z	e
fddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zddd d!Zd"d# Ze fd$d%Ze fd&d'Z  ZS )(r   NTz5Expected a list of items but got type "{input_type}".zThis list may not be empty.z9Ensure this field has no more than {max_length} elements.z5Ensure this field has at least {min_length} elements.)
not_a_listrH   r[   r\   c                    s   | dt| j| _| dd| _| dd | _| dd | _| jd k	sRtdt	| jrftdt
 j|| | jjd| d	 d S )
Nrr   rU   Tr[   r\   z`child` is a required argument.z"`child` has not been instantiated. )r   parent)ra   r   r   rr   rU   r[   r\   r   inspectisclassrc   rd   bind)re   ro   rf   rg   ri   rj   rd   W  s    zListSerializer.__init__c                 C   s   t | dr| | jS g S )Nr`   )r   r   r`   r   ri   ri   rj   r   a  s    
zListSerializer.get_initialc                 C   s*   t |rt j|| jtdS || jtS )zE
        Given the input dictionary, return the field value.
        )r   rN   )r   r   parse_html_listr   rH   r   r   ri   ri   rj   r   f  s    
zListSerializer.get_valuec              
   C   s   |  |\}}|r|S | |}z(| | | |}|dk	sFtdW n4 ttfk
r| } ztt|dW 5 d}~X Y nX |S r   r   r   ri   ri   rj   r   p  s    


 zListSerializer.run_validationc                 C   s   | j |S )a%  
        Run validation on child serializer.
        You may need to override this method to support multiple updates. For example:

        self.child.instance = self.instance.get(pk=data['id'])
        self.child.initial_data = data
        return super().run_child_validation(data)
        )rr   r   r   ri   ri   rj   run_child_validation  s    	z#ListSerializer.run_child_validationc                 C   s|  t |rt j|g d}t|tsN| jd jt|jd}t	t
j|gidd| js~t|dkr~| jd }t	t
j|gidd| jdk	rt|| jkr| jd j| jd	}t	t
j|gidd| jdk	rt|| jk r| jd
 j| jd}t	t
j|gid
dg }g }|D ]Z}z| |}W n0 t	k
rL } z||j W 5 d}~X Y nX || |i  q
t|rxt	||S )zY
        List of dicts of native values <- List of dicts of primitive datatypes.
        rN   r  )Z
input_typer   r   rH   Nr[   )r[   r\   )r\   )r   r   r	  r   r   rT   r   r   r   r   r   r   rU   r   r[   r\   r
  appendr   any)re   rW   r   r   r   itemZ	validatedr   ri   ri   rj   r     s`    


 
   

z ListSerializer.to_internal_valuec                    s,   t |tjjr| n|} fdd|D S )zS
        List of object instances -> List of dicts of primitive datatypes.
        c                    s   g | ]} j |qS ri   )rr   r   )ru   r  r   ri   rj   r     s    z4ListSerializer.to_representation.<locals>.<listcomp>)r   r   managerZBaseManagerall)re   rW   iterableri   r   rj   r     s    
z ListSerializer.to_representationc                 C   s   |S rp   ri   r   ri   ri   rj   r     s    zListSerializer.validatec                 C   s   t dd S )Na'  Serializers with many=True do not support multiple update by default, only multiple create. For updates it is unclear how to deal with insertions and deletions. If you need to support multiple update, use a `ListSerializer` class and override `.update()` so you can specify the behavior exactly.r   r   ri   ri   rj   r|     s    zListSerializer.updatec                    s    fdd|D S )Nc                    s   g | ]} j |qS ri   )rr   r   ru   r   r   ri   rj   r     s    z)ListSerializer.create.<locals>.<listcomp>ri   r   ri   r   rj   r     s    
zListSerializer.createc                    sv   d kst d fdd| jD }| jdk	rR| | j|| _| jdk	spt dn| || _| jdk	spt d| jS )z=
        Save and return a list of object instances.
        r   r   c                    s   g | ]}| qS ri   ri   r  rf   ri   rj   r     s    z'ListSerializer.save.<locals>.<listcomp>Nr   r   )r   r   rV   r|   r   r   ri   r  rj   r     s     
	

zListSerializer.saveFr   c             
   C   s   t | dstdt | dsfz| | j| _W n0 tk
r^ } zg | _|j| _W 5 d }~X Y nX g | _| jrz|rzt| jt	| j S r   r   r   ri   ri   rj   r     s    


zListSerializer.is_validc                 C   s   t j| ddS r   )r   Z	list_reprr   ri   ri   rj   r     s    zListSerializer.__repr__c                    s   t  j}t|| dS r   )rc   rW   r   r   rg   ri   rj   rW     s    zListSerializer.datac                    sl   t  j}t|trJt|dkrJt|d dd dkrJtddd}tj|gi}t|t	r`t
|| dS t|| dS r   )rc   r   r   r   r   r~   r   r   r   r   r   r   r   rg   ri   rj   r     s    *
zListSerializer.errors)r   r   r   rr   r_   r   r  rd   r   r   rH   r   r
  r   r   r   r|   r   r   r   r   r   rW   r   r   ri   ri   rg   rj   r   L  s0   

2	r   c                    s   |j j}t| t fdd|jD rHtdj| |jj	|jj
dt fdd|jD r~tdj| |jj	|jj
ddS )a  
    Give explicit errors when users attempt to pass writable nested data.

    If we don't do this explicitly they'd get a less helpful error when
    calling `.save()` on the serializer.

    We don't *automatically* support these sorts of nested writes because
    there are too many ambiguities to define a default behavior.

    Eg. Suppose we have a `UserSerializer` with a nested profile. How should
    we handle the case of an update, where the `profile` relationship does
    not exist? Any of the following might be valid:

    * Raise an application error.
    * Silently ignore the nested part of the update.
    * Automatically create a profile instance.
    c                 3   sB   | ]:}t |to8|jko8|j jko8t |j ttfV  qd S rp   )r   r^   rP   	relationsr   r   r   Zmodel_field_infor   ri   rj   	<genexpr>H  s   

z0raise_errors_on_nested_writes.<locals>.<genexpr>zThe `.{method_name}()` method does not support writable nested fields by default.
Write an explicit `.{method_name}()` method for serializer `{module}.{class_name}`, or set `read_only=True` on nested serializer fields.)method_namemodule
class_namec                 3   sR   | ]J}t |jd koH|jd koH|jd  jkoHt|jd  ttfV  qdS )r   r   N)r   r   r  r   r   r   r   r  ri   rj   r  g  s   zThe `.{method_name}()` method does not support writable dotted-source fields by default.
Write an explicit `.{method_name}()` method for serializer `{module}.{class_name}`, or set `read_only=True` on dotted-source serializer fields.N)ry   modelr   get_field_infor  r   r   r   rh   r   r   )r  r   r   
ModelClassri   r  rj   raise_errors_on_nested_writes.  s(    


r  c                4   @   s  e Zd ZdZejeejeejeej	e	ej
e	ejeejeejeejeejeejeejeejeejeejeejeejeejeejeejeeje	ejeejeejeejeej e iZ!e"edre#e!ej#< e$re%e!e$j%< e&e!e$j'< e#e!e$j#< e(Z)e*Z+e,Z-e.Z/dZ0dd Z1dd Z2dd	 Z3d
d Z4dd Z5dd Z6dd Z7dd Z8dd Z9dd Z:dd Z;dd Z<dd Z=dd Z>d d! Z?d"d# Z@d$d% ZAd&d' ZBd(d) ZCd*d+ ZDdS ),ModelSerializera  
    A `ModelSerializer` is just a regular `Serializer`, except that:

    * A set of default fields are automatically populated.
    * A set of default validators are automatically populated.
    * Default `.create()` and `.update()` implementations are provided.

    The process of automatically determining a set of serializer fields
    based on the model fields is reasonably complex, but you almost certainly
    don't need to dig into the implementation.

    If the `ModelSerializer` class *doesn't* generate the set of fields that
    you need you should either declare the extra/differing fields explicitly on
    the serializer class, or simply use a `Serializer` class.
    r3   Nc              
   C   s   t d| | | jj}t|}i }|j D ]$\}}|jr,||kr,||||< q,z|j	j
f |}W nH tk
r   t }d|j|j	j|j|j	j| jj|f }	t|	Y nX |r| D ]\}}
t||}||
 q|S )aj  
        We have a bit of extra checking around this in order to provide
        descriptive messages when something goes wrong, but this method is
        essentially just:

            return ExampleModel.objects.create(**validated_data)

        If there are many to many fields present on the instance then they
        cannot be set until the model is instantiated, in which case the
        implementation is like so:

            example_relationship = validated_data.pop('example_relationship')
            instance = ExampleModel.objects.create(**validated_data)
            instance.example_relationship = example_relationship
            return instance

        The default implementation also does not handle nested relationships.
        If you want to support writable nested relationships you'll need
        to write an explicit `.create()` method.
        r   a+  Got a `TypeError` when calling `%s.%s.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `%s.%s.create()`. You may need to make the field read-only, or override the %s.create() method to handle this correctly.
Original exception was:
 %s)r  ry   r  r   r  r  r}   to_manyra   _default_managerr   	TypeError	traceback
format_excr   r   rh   r~   r   )re   r   r  infoZmany_to_manyr   relation_inforV   tbr   rw   r   ri   ri   rj   r     s6    

zModelSerializer.createc                 C   s   t d| | t|}g }| D ]:\}}||jkrP|j| jrP|||f q"t||| q"|  |D ]\}}t	||}|
| qj|S )Nr|   )r  r   r  r}   r  r  r  setattrr   r~   r   )re   rV   r   r$  Z
m2m_fieldsattrrw   r   ri   ri   rj   r|     s    

zModelSerializer.updatec                 C   sl  | j dkrtj| _ t| ds0tdj| jjdt| jdsPtdj| jjdt	
| jjrftdt| j}t| jd}t| jdd	}|dk	r|d	kstd
|dkstdt	|}| ||}|  }| |||\}}i }|D ]p}	|	|kr||	 ||	< q||	i }
|
dd}|dkr.|	}| ||||\}}| ||
}|f |||	< q|| |S )z
        Return the dict of field names -> field instances that should be
        used for `self.fields` when instantiating the serializer.
        Nry   z1Class {serializer_class} missing "Meta" attributeserializer_classr  z7Class {serializer_class} missing "Meta.model" attributez0Cannot use ModelSerializer with Abstract Models.depthr   z'depth' may not be negative.
   z#'depth' may not be greater than 10.rP   r   )url_field_namer   ZURL_FIELD_NAMEr   r   r   rh   r   ry   r   Zis_abstract_modelr  
ValueErrorr   r   r   r~   r  get_field_namesget_extra_kwargsget_uniqueness_extra_kwargsr   build_fieldinclude_extra_kwargsr|   )re   declared_fieldsr  r+  r$  field_namesextra_kwargshidden_fieldsr   r   Zextra_field_kwargsrP   field_classfield_kwargsri   ri   rj   r     sh    

  

    
zModelSerializer.get_fieldsc                 C   s  t | jdd}t | jdd}|rH|tkrHt|ttfsHtdt|j |rlt|ttfsltdt|j |r|rt	dj
| jjd|dkr|dkrt	dj
| jjdf|tkrd}|dk	rt|}| jjD ]}|tt |d	g 8 }q|D ]"}||kst	d
j
|| jjdq|S | ||}|dk	r|D ]R}|| jksZt	dj
|| jjd||kszt	dj
|| jjd|| q4|S )a  
        Returns the list of all field names that should be created when
        instantiating this serializer class. This is based on the default
        set of fields, but also takes into account the `Meta.fields` or
        `Meta.exclude` options if they have been specified.
        r   NexcludezAThe `fields` option must be a list or tuple or "__all__". Got %s.z5The `exclude` option must be a list or tuple. Got %s.zPCannot set both 'fields' and 'exclude' options on serializer {serializer_class}.r)  zCreating a ModelSerializer without either the 'fields' attribute or the 'exclude' attribute has been deprecated since 3.3.0, and is now disallowed. Add an explicit fields = '__all__' to the {serializer_class} serializer.r   zyThe field '{field_name}' was declared on serializer {serializer_class}, but has not been included in the 'fields' option.)r   r*  zCannot both declare the field '{field_name}' and include it in the {serializer_class} 'exclude' option. Remove the field or, if inherited from a parent serializer, disable with `{field_name} = None`.zThe field '{field_name}' was included on serializer {serializer_class} in the 'exclude' option, but does not match any model field.)r~   ry   
ALL_FIELDSr   r   tupler!  r   r   r   r   rh   r   	__bases__get_default_field_namesr   remove)re   r4  r$  r   r:  Zrequired_field_namesrn   r   ri   ri   rj   r/  b  sn    
	


zModelSerializer.get_field_namesc                 C   s&   |j jgt| t|j t|j S z
        Return the default list of field names that will be used if the
        `Meta.fields` option is not specified.
        )r   r   r   r   forward_relationsre   r4  Z
model_infori   ri   rj   r>    s    z'ModelSerializer.get_default_field_namesc                 C   s   ||j kr |j | }| ||S ||jkrT|j| }|sD| ||S | |||S n,t||rj| ||S || jkr| ||S | 	||S )zW
        Return a two tuple of (cls, kwargs) to build a serializer field with.
        )
fields_and_pkbuild_standard_fieldr  build_relational_fieldbuild_nested_fieldr   build_property_fieldr-  build_url_fieldbuild_unknown_field)re   r   r$  model_classnested_depthmodel_fieldr%  ri   ri   rj   r2    s    





zModelSerializer.build_fieldc                 C   sP  t | j}|| }t||}|jr:|jr:| j}|jj|d< d|kr| j}ddddddd	d
ddddddh}t	|D ]}||krp|
| qpt|ts|
dd t|tst|ts|
dd ttdot|tj}trt|tjs|rt|dd|d< |rt|dd|d< trHt|tjrH|j}	| d|	\}
}|
f ||d< ||fS )z.
        Create regular model fields.
        querysetchoicesrK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   r   rZ   allow_blankrL  Nr3   encoderdecoderrr   )r   serializer_field_mappingr   Z
one_to_oneprimary_keyserializer_related_fieldrelated_modelZobjectsserializer_choice_fieldr   ra   
issubclassr5   r#   r$   r   r   r   r3   r   r~   
ArrayFieldZ
base_fieldrD  )re   r   rL  Zfield_mappingr8  r9  Zvalid_kwargsrv   Zis_django_jsonfieldZchild_model_fieldZchild_field_classZchild_field_kwargsri   ri   rj   rD    sV    

         
 z$ModelSerializer.build_standard_fieldc                 C   sb   | j }t||}|dd}|rD|jsD|jj|jsD||d< | j}t	|t
sZ|dd ||fS )zF
        Create fields for forward and reverse relationships.
        to_fieldNZ
slug_fieldZ	view_name)rT  r   ra   reverserU  _meta	get_fieldrS  serializer_related_to_fieldrW  r?   )re   r   r%  r8  r9  rY  ri   ri   rj   rE     s    

z&ModelSerializer.build_relational_fieldc                    s*   G  fdddt }|}t}||fS )M
        Create nested fields for forward and reverse relationships.
        c                       s    e Zd ZG  fdddZdS )z<ModelSerializer.build_nested_field.<locals>.NestedSerializerc                       s   e Zd ZjZ d ZdZdS )zAModelSerializer.build_nested_field.<locals>.NestedSerializer.Metar   r]   Nr   r   r   rU  r  r+  r   ri   rK  r%  ri   rj   ry   7  s   ry   Nr   r   r   ry   ri   r`  ri   rj   NestedSerializer6  s   rb  )r  r   re   r   r%  rK  rb  r8  r9  ri   r`  rj   rF  2  s    z"ModelSerializer.build_nested_fieldc                 C   s   t }i }||fS )zL
        Create a read only field for model methods and properties.
        )r7   re   r   rJ  r8  r9  ri   ri   rj   rG  A  s    z$ModelSerializer.build_property_fieldc                 C   s   | j }t|}||fS )zC
        Create a field representing the object's own URL.
        )serializer_url_fieldr   rd  ri   ri   rj   rH  J  s    zModelSerializer.build_url_fieldc                 C   s"   t d||j| jj| jjf dS )z7
        Raise an error on any unknown fields.
        z7Field name `%s` is not valid for model `%s` in `%s.%s`.N)r   r   rh   r   )re   r   rJ  ri   ri   rj   rI  S  s
    z#ModelSerializer.build_unknown_fieldc                 C   sr   | ddr"dD ]}||d q| drD| ddkrD|d | d| ddrd|dd || |S )z
        Include any 'extra_kwargs' that have been included for this field,
        possibly removing any incompatible existing keyword arguments.
        rK   F)	rM   rN   rO  r\   r[   Z	min_valueZ	max_valuer   rM  NrN   rM   )r   ra   r|   )re   rf   r6  r(  ri   ri   rj   r3  \  s    

z$ModelSerializer.include_extra_kwargsc                 C   s   t t| jdi }t| jdd}|dk	rrt|ttfsJtdt|j	 |D ] }|
|i }d|d< |||< qNn$t| jdrtd| jj| jj	f |S )	zr
        Return a dictionary mapping field names to a dictionary of
        additional keyword arguments.
        r6  read_only_fieldsNz>The `read_only_fields` option must be a list or tuple. Got %s.TrK   Zreadonly_fieldszjSerializer `%s.%s` has field `readonly_fields`; the correct spelling for the option is `read_only_fields`.)r   r   r~   ry   r   r   r<  r!  r   r   r   r   r   rh   r   )re   r6  rf  r   rf   ri   ri   rj   r0  t  s&    z ModelSerializer.get_extra_kwargsc                 c   s   |gt |jj D ]l}|jjD ]}||jfV  q|jjD ]D}t|tjr8t	|j
dkr8|j
|jdkrj|jn|j|jfV  q8qdS )z
        Returns iterator of (fields, queryset), each entry describes an unique together
        constraint on `fields` in `queryset`.
        r   N)r   r[  parentsunique_togetherr   constraintsr   r   ZUniqueConstraintr   r   	conditionfilter)re   r  Zparent_classrh  
constraintri   ri   rj   get_unique_together_constraints  s    z/ModelSerializer.get_unique_together_constraintsc                 C   st  t | jdddk	r|i fS t | jd}| |||}t }| D ]}||j|j|jhO }qB|dh8 }| |D ]"\}}	t|	|rp|t|O }qpi }
i }|D ]}|j
|}t |ddrttj}n(t |ddrtj}n| r|j}nt}||kr |tkrddi||< nd|i||< q|tk	rt|d	|
|< q| D ]*\}}||kr`|||  |||< q@||
fS )
z
        Return any additional field options that need to be included as a
        result of uniqueness constraints on the model. This is returned as
        a two-tuple of:

        ('dict of updated extra kwargs', 'mapping of hidden fields')
        r   Nr  Zauto_now_addZauto_nowrM   TrN   r  )r~   ry   _get_model_fieldsr   r   unique_for_dateunique_for_monthunique_for_yearrm  
issupersetr[  r\  rE   r	   nowZhas_defaultrN   rH   r.   r}   r|   )re   r5  r4  r6  r  model_fieldsZunique_constraint_namesrL  Zunique_together_listrM  r7  Zuniqueness_extra_kwargsZunique_constraint_nameZunique_constraint_fieldrN   rv   rw   ri   ri   rj   r1    sN      




z+ModelSerializer.get_uniqueness_extra_kwargsc           	   
   C   s   t | jd}i }|D ]}||kr4|| }|jp0|}n*z|| d }W n tk
r\   |}Y nX d|ks|dkrpqtt$ |j|}t	|t
r|||< W 5 Q R X q|S )z
        Returns all the model fields that are being mapped to by fields
        on the serializer class.
        Returned as a dict of 'model field name' -> 'model field'.
        Used internally by `get_uniqueness_field_options`.
        r  rP   r   r   )r~   ry   rP   KeyError
contextlibsuppressr   r[  r\  r   DjangoModelField)	re   r5  r4  r6  r  rt  r   r   rP   ri   ri   rj   rn    s"    

z!ModelSerializer._get_model_fieldsc                 C   s4   t t | dddd}|dk	r$t|S |  |   S )zW
        Determine the set of validators to use when instantiating serializer.
        ry   Nr   )r~   r   get_unique_together_validatorsget_unique_for_date_validators)re   r   ri   ri   rj   r     s    zModelSerializer.get_validatorsc           	         s   dd | j D }|dd | j D  tt | D ]\}} | | q:g }| | j	j
D ]\}}t |s|qd|D ]>}t | dkstdj| j	j
j| jj|d | dqt fdd	|D }t||d
}|| qd|S )z\
        Determine a default set of validators for any unique_together constraints.
        c                 S   s*   i | ]"}|j d krd|j kr|j|j qS r   )rP   r   r   ri   ri   rj   rx   &  s
   
 
 zBModelSerializer.get_unique_together_validators.<locals>.<dictcomp>c                 S   s:   i | ]2}|j r|jtkr|jd krd|jkr|j|jqS r   )rK   rN   rH   rP   r   r   ri   ri   rj   rx   ,  s    
 
 
 r   a  Unable to create `UniqueTogetherValidator` for `{model}.{field}` as `{serializer}` has multiple fields ({fields}) that map to this model field. Either remove the extra fields, or override `Meta.validators` with a `UniqueTogetherValidator` using the desired field names.z, )r  r   r   r   c                 3   s   | ]} | d  V  qdS )r   Nri   )ru   r   Z
source_mapri   rj   r  P  s     zAModelSerializer.get_unique_together_validators.<locals>.<genexpr>)rM  r   )r   r|   r   r   r   r   r}   r  rm  ry   r  r   rr  r   r   r   r   rh   joinr<  r!   )	re   Zfield_sourcesr   rP   r   rh  rM  r5  	validatorri   r{  rj   ry    s:    
z.ModelSerializer.get_unique_together_validatorsc                 C   s   t | jj}| jjj}dd | j D }g }|j D ]\}}|j	rj||krjt
|||j	d}|| |jr||krt|||jd}|| |jr:||kr:t|||jd}|| q:|S )z
        Determine a default set of validators for the following constraints:

        * unique_for_date
        * unique_for_month
        * unique_for_year
        c                 S   s   g | ]
}|j qS ri   )rP   r   ri   ri   rj   r   b  s     zBModelSerializer.get_unique_for_date_validators.<locals>.<listcomp>)rM  r   Z
date_field)r   r  ry   r  r   r   r   rC  r}   ro  r   r  rp  r   rq  r    )re   r$  Zdefault_managerr5  r   r   r   r}  ri   ri   rj   rz  X  s6    


z.ModelSerializer.get_unique_for_date_validators)Er   r   r   r   r   Z	AutoFieldr2   ZBigIntegerFieldr"   r#   ZCommaSeparatedIntegerFieldr%   r&   r'   r)   r*   r   r5   r+   r-   r1   ZNullBooleanFieldZPositiveIntegerFieldZPositiveSmallIntegerFieldr:   ZSmallIntegerFieldZ	TextFieldr;   r<   r=   ZGenericIPAddressFieldr0   r,   rR  r   r3   r   r/   r4   rX  rA   rT  rC   r]  r>   re  r$   rV  r-  r   r|   r   r/  r>  r2  rD  rE  rF  rG  rH  rI  r3  r0  rm  r1  rn  r   ry  rz  ri   ri   ri   rj   r  y  s                             




	@L\=			I#:r  c                   @   s$   e Zd ZdZeZdd Zdd ZdS )HyperlinkedModelSerializera  
    A type of `ModelSerializer` that uses hyperlinked relationships instead
    of primary key relationships. Specifically:

    * A 'url' field is included instead of the 'id' field.
    * Relationships to other instances are hyperlinks, instead of primary keys.
    c                 C   s$   | j gt| t|j t|j S r@  )r-  r   r   rA  rB  ri   ri   rj   r>    s    z2HyperlinkedModelSerializer.get_default_field_namesc                    s*   G  fdddt }|}t}||fS )r^  c                       s    e Zd ZG  fdddZdS )zGHyperlinkedModelSerializer.build_nested_field.<locals>.NestedSerializerc                       s   e Zd ZjZ d ZdZdS )zLHyperlinkedModelSerializer.build_nested_field.<locals>.NestedSerializer.Metar   r]   Nr_  ri   r`  ri   rj   ry     s   ry   Nra  ri   r`  ri   rj   rb    s   rb  )r~  r   rc  ri   r`  rj   rF    s    z-HyperlinkedModelSerializer.build_nested_fieldN)r   r   r   r   r?   rT  r>  rF  ri   ri   ri   rj   r~    s   r~  )nr   rv  r   r  r"  collectionsr   collections.abcr   Zdjango.core.exceptionsr   r   r   r   Z	django.dbr   Zdjango.db.models.fieldsr   rx  Zdjango.utilsr	   Zdjango.utils.functionalr
   Zdjango.utils.translationr   r   Zrest_framework.compatr   Zrest_framework.exceptionsr   Zrest_framework.fieldsr   Zrest_framework.settingsr   Zrest_framework.utilsr   r   r   Z"rest_framework.utils.field_mappingr   r   r   r   r   Z'rest_framework.utils.serializer_helpersr   r   r   r   r   r   Zrest_framework.validatorsr   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   Zrest_framework.relationsr>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rs   r{   r;  r^   r   r   r   r   r   r  r  r~  ri   ri   ri   rj   <module>   sZ    |$ <& { cK      