o
    9Of_B                     @   s   d dl mZ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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 G dd dejZG dd deZG dd deZG dd dejZ dS )    )OrderedDictdefaultdict)ListTuple)GenericRelation)ContentType)FieldDoesNotExist)ProtectedErrorSET_NULLSET_DEFAULT)ForeignObjectRel)gettext_lazy)serializers)ValidationError)UniqueValidator)ManyToManyRelc                       sl   e Z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 Z
dd Z fddZdd Z  ZS )BaseNestedModelSerializerc              	   C   s   t  }t  }| j D ]l\}}|jrqz	| |\}}W n	 ty%   Y qw t|tjrHt|j	tj
rH|j|vr9q||j ||j	|jf||< t|tj
rw|j|vrTq||jd u r_|r_q||j |ro||jf||< q|||jf||< q||fS N)r   fieldsitems	read_only_get_related_fieldr   
isinstancer   ListSerializerchildModelSerializersourcepopget)selfvalidated_datareverse_relations	relations
field_namefieldrelated_fielddirect r'   f/var/www/html/Testing_prj/Navya-Bakers/venv/lib/python3.10/site-packages/drf_writable_nested/mixins.py_extract_relations   s>   


z,BaseNestedModelSerializer._extract_relationsc              	   C   s   | j j}z	|j|j}W n! ty.   d}|j|r+|j|jd t|  }n Y nw t|t	r>t|t
s>|jdfS |dfS )N_setFT)Metamodel_meta	get_fieldr   r   endswithlenr   r   r   r$   )r   r$   model_classr%   default_postfixr'   r'   r(   r   @   s   

z,BaseNestedModelSerializer._get_related_fieldc                 K   sd   | | j|dr| jndd t|dr*||d|j}|jdi |S |jdi |S )NinstanceF)contextpartial"_get_serializer_from_resource_typedatar'   )updater4   r   r5   hasattrr6   resource_type_field_name	__class__)r   r$   kwargs
serializerr'   r'   r(   _get_serializer_for_fieldS   s   
z3BaseNestedModelSerializer._get_serializer_for_fieldc                 C   s   |j tj||j|jiS r   )content_type_field_namer   objectsget_for_modelobject_id_field_namepk)r   r3   r%   r'   r'   r(   _get_generic_lookupd   s   
z-BaseNestedModelSerializer._get_generic_lookupc                 C   s*   | dp| |jjj}|rt|S d S )NrC   )r   r-   rC   attnamestr)r   r7   r1   rC   r'   r'   r(   _get_related_pkk   s   z)BaseNestedModelSerializer._get_related_pkc                 C   s:   |j j}g }td |D ]}| ||}|r|| q|S r   )r+   r,   filterrG   append)r   r$   related_datar1   pk_listdrC   r'   r'   r(   _extract_related_pkss   s   
z.BaseNestedModelSerializer._extract_related_pksc                 C   s0   |j j}| ||}dd |jj|dD }|S )Nc                 S   s   i | ]}t |j|qS r'   )rF   rC   ).0related_instancer'   r'   r(   
<dictcomp>   s    
zIBaseNestedModelSerializer._prefetch_related_instances.<locals>.<dictcomp>pk__in)r+   r,   rM   r@   rH   )r   r$   rJ   r1   rK   	instancesr'   r'   r(   _prefetch_related_instances}   s   z5BaseNestedModelSerializer._prefetch_related_instancesc                 C   s  |  D ]\}\}}}|  |d }|d u rq|jr@|jjjjj}||vr,d|v r,d}||vr=t	||d }	|	r=|	j||< |g}| 
||}
| |}t|trZ|| || n|jsb|||j< g }g }|D ]L}|
| ||jj}| j|||d}z|jdd |jdi |}	|	j|d< ||	 |i  W qh ty } z||j W Y d }~qhd }~ww t|r|jrt||d it||i|jrt	||}|j|  qd S )NrC   r3   r7   Traise_exceptionr   r'   )r   get_initialr   
one_to_oner+   r,   r-   rC   rE   getattrrT   _get_save_kwargsr   r   r8   rD   many_to_manynamerG   r>   is_validsaverI   r   detailanyadd)r   r3   r!   r#   r%   r$   field_sourcerJ   pk_namerO   rS   save_kwargsnew_related_instanceserrorsr7   objr=   excm2m_managerr'   r'   r(   "update_or_create_reverse_relations   sh   








z<BaseNestedModelSerializer.update_or_create_reverse_relationsc                 C   s   |  D ]S\}\}}d }|  | }|jj}| ||}	|	r'|jj|	d }| j|||d}
z|
j	dd |
j
di | |||< W q tyW } zt||jid }~ww d S )N)rC   rU   TrV   r'   )r   rX   r+   r,   rG   r@   rH   firstr>   r^   r_   r[   r   r`   )r   attrsr"   r#   r$   rc   rh   r7   r1   rC   r=   ri   r'   r'   r(   !update_or_create_direct_relations   s4   z;BaseNestedModelSerializer.update_or_create_direct_relationsc                    s"   t t|| _tt| jdi |S )Nr'   )r   dict_save_kwargssuperr   r_   )r   r<   r;   r'   r(   r_      s   zBaseNestedModelSerializer.savec                 C   s$   | j | }t|tsttd|S )Nz6Arguments to nested serializer's `save` must be dict's)rp   r   ro   	TypeError_)r   r#   re   r'   r'   r(   r[      s   

z*BaseNestedModelSerializer._get_save_kwargs)__name__
__module____qualname__r)   r   r>   rD   rG   rM   rT   rk   rn   r_   r[   __classcell__r'   r'   rr   r(   r      s    .
Dr   c                       s    e Zd ZdZ fddZ  ZS )NestedCreateMixinz$
    Adds nested create feature
    c                    s:   |  |\}}| || tt| |}| || |S r   )r)   rn   rq   ry   createrk   )r   r    r"   r!   r3   rr   r'   r(   rz      s   zNestedCreateMixin.create)ru   rv   rw   __doc__rz   rx   r'   r'   rr   r(   ry      s    ry   c                       s<   e Zd ZdZdediZ fddZdd Zdd	 Z  Z	S )
NestedUpdateMixinz$
    Adds update nested feature
    cannot_delete_protectedz;Cannot delete {instances} because protected relation existsc                    sP   |  |\}}| || tt| ||}| || | || |  |S r   )r)   rn   rq   r|   r8   rk    delete_reverse_relations_if_needrefresh_from_db)r   r3   r    r"   r!   rr   r'   r(   r8     s   
zNestedUpdateMixin.updatec           
      C   s|   |j rt||}|j|  d S |jj|d}|jj}|ttfv r8|tkr)|	 }	nd }	|j
di |j|	i d S |  d S )NrQ   r'   )r\   rZ   remover@   rH   remote_field	on_deleter
   r   get_defaultr8   r]   delete)
r   pks_to_deleter1   r3   r%   rc   rj   qsr   defaultr'   r'   r(   perform_nested_delete_or_update'  s   

z1NestedUpdateMixin.perform_nested_delete_or_updatec                 C   s  t tt| }| D ]}\}\}}}|jj}|  | }|jr%|g}|jr/|j	j
|i}	nt|tr;| ||}	n|j
|i}	| ||}
zt|jjdi |	j|
djddd}| ||||| W q ty } z|jd }| jdddd	 |D d
 W Y d }~qd }~ww d S )NrQ   rC   T)flat   r}   z, c                 S   s   g | ]}t |qS r'   )rF   )rN   r3   r'   r'   r(   
<listcomp>j  s    zFNestedUpdateMixin.delete_reverse_relations_if_need.<locals>.<listcomp>)rS   r'   )r   reversedlistr   r+   r,   rX   rY   r\   r   r]   r   r   rD   rM   r@   rH   excludevalues_listr   r	   argsfailjoin)r   r3   r!   r#   r%   r$   rc   r1   rJ   related_field_lookupcurrent_idsr   erS   r'   r'   r(   r~   9  sX   



z2NestedUpdateMixin.delete_reverse_relations_if_need)
ru   rv   rw   r{   rt   default_error_messagesr8   r   r~   rx   r'   r'   rr   r(   r|   
  s    r|   c                       sD   e Zd ZdZg Z fddZdd Z fddZ fdd	Z  Z	S )
UniqueFieldsMixinah  
    Moves `UniqueValidator`'s from the validation stage to the save stage.
    It solves the problem with nested validation for unique fields on update.

    If you want more details, you can read related issues and articles:
    https://github.com/beda-software/drf-writable-nested/issues/1
    http://www.django-rest-framework.org/api-guide/validators/#updating-nested-serializers

    Example of usage:
    ```
        class Child(models.Model):
        field = models.CharField(unique=True)


    class Parent(models.Model):
        child = models.ForeignKey('Child')


    class ChildSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
        class Meta:
            model = Child


    class ParentSerializer(NestedUpdateMixin, serializers.ModelSerializer):
        child = ChildSerializer()

        class Meta:
            model = Parent
    ```

    Note: `UniqueFieldsMixin` must be applied only on the serializer
    which has unique fields.

    Note: When you are using both mixins
    (`UniqueFieldsMixin` and `NestedCreateMixin` or `NestedUpdateMixin`)
    you should put `UniqueFieldsMixin` ahead.
    c                    sd   g | _ tt|  }| D ]!\}}dd |jD }|r/| j ||d f dd |jD |_q|S )Nc                 S   s   g | ]	}t |tr|qS r'   r   r   rN   	validatorr'   r'   r(   r     s    
z0UniqueFieldsMixin.get_fields.<locals>.<listcomp>r   c                 S   s   g | ]	}t |ts|qS r'   r   r   r'   r'   r(   r     s    )_unique_fieldsrq   r   
get_fieldsr   
validatorsrI   )r   r   r#   r$   unique_validatorsrr   r'   r(   r     s   zUniqueFieldsMixin.get_fieldsc                 C   s   | j D ]A}|\}}| jr||vrqz t|dr&|| j|  |||  n
||| | j|  W q tyD } zt||jid }~ww d S )Nset_context)r   r5   r9   r   r   r   r`   )r   r    unique_fieldr#   unique_validatorri   r'   r'   r(   _validate_unique_fields  s"   

z)UniqueFieldsMixin._validate_unique_fieldsc                    s   |  | tt| |S r   )r   rq   r   rz   )r   r    rr   r'   r(   rz     s   
zUniqueFieldsMixin.createc                    s   |  | tt| ||S r   )r   rq   r   r8   )r   r3   r    rr   r'   r(   r8     s   
zUniqueFieldsMixin.update)
ru   rv   rw   r{   r   r   r   rz   r8   rx   r'   r'   rr   r(   r   n  s    %r   N)!collectionsr   r   typingr   r   "django.contrib.contenttypes.fieldsr   "django.contrib.contenttypes.modelsr   django.core.exceptionsr   django.db.modelsr	   r
   r   django.db.models.fields.relatedr   django.utils.translationr   rt   rest_frameworkr   rest_framework.exceptionsr   rest_framework.validatorsr   r   r   r   ry   r|   r   r'   r'   r'   r(   <module>   s"    ed