
    !%i4B                        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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ej8                        Z G d de      Z G d de      Z G d dej8                        Z y)    )OrderedDictdefaultdict)ListTuple)GenericRelation)ContentType)FieldDoesNotExist)ProtectedErrorSET_NULLSET_DEFAULT)ForeignObjectRelManyToManyRel)gettext_lazy)serializers)ValidationError)UniqueValidatorc                   Z     e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Z fd
Zd Z xZS )BaseNestedModelSerializerc                    t               }t               }| j                  j                         D ]6  \  }}|j                  r	 | j	                  |      \  }}t        |t        j                        rjt        |j                  t        j                        rF|j                  |vrv|j                  |j                         ||j                  |j                  f||<   t        |t        j                        s|j                  |vr|j                  |j                        |r|j                  |j                         |r||j                  f||<   %|||j                  f||<   9 ||fS # t
        $ r Y Jw xY w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directs           t/var/www/html/navyabakers_fullstack/navyabakers_prod/venv/lib/python3.12/site-packages/drf_writable_nested/mixins.py_extract_relationsz,BaseNestedModelSerializer._extract_relations   sd   'MM	 "&!2!2!4 %	<J(,(?(?(F%v %!;!;<u{{K,G,GH<<~5""5<<0 "5;;1>!*- %!<!<=<<~5!%%ell3; !""5<<0 -2ELL,AIj) &uell5<%j1I%	<N +++E % s   E--	E:9E:c                    | j                   j                  }	 |j                  j                  |j                        }t        |t              rt        |t              s|j                  dfS |dfS # t
        $ rT d}|j                  j                  |      r3|j                  j                  |j                  d t        |              }n Y w xY w)N_setFT)Metamodel_meta	get_fieldr   r	   endswithlenr   r   r   r'   )r"   r'   model_classr(   default_postfixs        r*   r   z,BaseNestedModelSerializer._get_related_field?   s    iioo
	'--77EM m%56z-Yf?g &&--d"" ! 	 %O||$$_5 + 1 1 ; ;LL!73#7"78!:  	s   %A/ /ACCc                 J   |j                  | j                  |j                  d      r| j                  ndd       t	        |d      rK|j                  |j                  d      j                  |j                              } |j                  di |S  |j                  di |S )NinstanceF)contextpartial"_get_serializer_from_resource_typedata )updater8   r!   r9   hasattrr:   resource_type_field_name	__class__)r"   r'   kwargs
serializers       r*   _get_serializer_for_fieldz3BaseNestedModelSerializer._get_serializer_for_fieldR   s    ||'-zz*'=t||5
 	 5>?AA

6"&&u'E'EFJ (:''1&11"5??,V,,    c                     |j                   t        j                  j                  |      |j                  |j
                  iS r   )content_type_field_namer   objectsget_for_modelobject_id_field_namepk)r"   r7   r(   s      r*   _get_generic_lookupz-BaseNestedModelSerializer._get_generic_lookupc   s8    11##11(;..
 	
rD   c                     |j                  d      xs/ |j                  |j                  j                  j                        }|rt	        |      S y )NrJ   )r!   r0   rJ   attnamestr)r"   r;   r4   rJ   s       r*   _get_related_pkz)BaseNestedModelSerializer._get_related_pkj   s>    XXd^Etxx(9(9(<(<(D(DEr7NrD   c                     |j                   j                  }g }t        d |      D ](  }| j                  ||      }|s|j	                  |       * |S r   )r.   r/   filterrO   append)r"   r'   related_datar4   pk_listdrJ   s          r*   _extract_related_pksz.BaseNestedModelSerializer._extract_related_pksr   sT    jj&&l+ 	#A%%a5Br"	#
 rD   c                     |j                   j                  }| j                  ||      }|j                  j	                  |      D ci c]  }t        |j                        | }}|S c c}w )Npk__in)r.   r/   rV   rG   rQ   rN   rJ   )r"   r'   rS   r4   rT   related_instance	instancess          r*   _prefetch_related_instancesz5BaseNestedModelSerializer._prefetch_related_instances|   sz    jj&&++E<@ %0$7$7$>$> %? %
   ##$&66
	 
 
s   A(c                    |j                         D ]  \  }\  }}}| j                         j                  |d       }|.|j                  rc|j                  j
                  j                  j                  j                  }||vrd|v rd}||vrt        ||d       }	|	r|	j                  ||<   |g}| j                  ||      }
| j                  |      }t        |t              r"|j                  | j                  ||             n|j                   s|||j"                  <   g }g }|D ]  }|
j                  | j%                  ||j                  j
                              }| j'                  |||      }	 |j)                  d        |j*                  di |}	|	j                  |d<   |j-                  |	       |j-                  i         t3        |      r)|j                  rt/        ||d   i      t/        ||i      |j                   st        ||      } |j4                  |   y # t.        $ r&}|j-                  |j0                         Y d }~/d }~ww xY w)NrJ   r7   r;   Traise_exceptionr   r<   )r   get_initialr!   
one_to_oner.   r/   r0   rJ   rM   getattrr\   _get_save_kwargsr   r   r=   rK   many_to_manynamerO   rC   is_validsaverR   r   detailanyadd)r"   r7   r$   r&   r(   r'   field_sourcerS   pk_namerZ   r[   save_kwargsnew_related_instanceserrorsr;   objrB   excm2m_managers                      r*   "update_or_create_reverse_relationsz<BaseNestedModelSerializer.update_or_create_reverse_relations   s]    "'')?	8<J<|  ++-11*dCL#''  ****0033;;,.4<3G"G,.'.xt'L$'0@0C0CW- !-~88MI//
;K-9"",,X}E #//2:M../$&!F$ .mm((uzz/?/?@ ";;  < 

.'''='6z'E'E$!1!4!4DJ)001ABMM"%.$ 6{ ++):vay*ABB):v*>??))%h=!67?	8f ' .MM#**--.s   1AH))	I2IIc                    |j                         D ]  \  }\  }}d }| j                         |   }|j                  j                  }| j	                  ||      }	|	r*|j
                  j                  |	      j                         }| j                  |||      }
	 |
j                  d        |
j                  di | j                  |      ||<    y # t        $ r}t        ||j                  i      d }~ww xY w)N)rJ   r^   Tr_   r<   )r   ra   r.   r/   rO   rG   rQ   firstrC   rg   rh   rd   r   ri   )r"   attrsr%   r&   r'   rl   rq   r;   r4   rJ   rB   rr   s               r*   !update_or_create_direct_relationsz;BaseNestedModelSerializer.update_or_create_direct_relations   s   1:1B 	@-J-C##%j1D****K%%dK8B!))00 1 %'  77 8 J@##D#9&5joo '++J7'l##	@( # @%z3::&>??@s   6C	C6C11C6c                 T    t        t        |      | _        t        t        |   di |S )Nr<   )r   dict_save_kwargssuperr   rh   )r"   rA   r@   s     r*   rh   zBaseNestedModelSerializer.save   s(    'f5.:DVDDrD   c                 l    | j                   |   }t        |t              st        t	        d            |S )Nz6Arguments to nested serializer's `save` must be dict's)r{   r   rz   	TypeError_)r"   r&   rn   s      r*   rd   z*BaseNestedModelSerializer._get_save_kwargs   s:    ''
3+t,JK  rD   )__name__
__module____qualname__r+   r   rC   rK   rO   rV   r\   rt   rx   rh   rd   __classcell__r@   s   @r*   r   r      s?    ,,\#&-"
B8H@0E
rD   r   c                   "     e Zd ZdZ fdZ xZS )NestedCreateMixinz$
    Adds nested create feature
    c                     | j                  |      \  }}| j                  ||       t        t        |   |      }| j                  ||       |S r   )r+   rx   r|   r   creatert   )r"   r#   r%   r$   r7   r@   s        r*   r   zNestedCreateMixin.create   sY    '+'>'>~'N$	$ 	..	
 *D8H//:KLrD   )r   r   r   __doc__r   r   r   s   @r*   r   r      s     rD   r   c                   B     e Zd ZdZd ed      iZ fdZd Zd Z xZ	S )NestedUpdateMixinz$
    Adds update nested feature
    cannot_delete_protectedz;Cannot delete {instances} because protected relation existsc                     | j                  |      \  }}| j                  ||       t        t        |   ||      }| j                  ||       | j                  ||       |j                          |S r   )r+   rx   r|   r   r=   rt    delete_reverse_relations_if_needrefresh_from_db)r"   r7   r#   r%   r$   r@   s        r*   r=   zNestedUpdateMixin.update  s~    '+'>'>~'N$	$ 	..	
 *D8
 	//:KL--h8IJ  "rD   c                 j   |j                   rt        ||      } |j                  |  y |j                  j	                  |      }|j
                  j                  }|t        t        fv r;|t        k(  r|j                         }	nd }	 |j                  di |j                  |	i y |j                          y )NrX   r<   )re   rc   removerG   rQ   remote_field	on_deleter   r   get_defaultr=   rf   delete)
r"   pks_to_deleter4   r7   r(   rl   rs   qsr   defaults
             r*   perform_nested_delete_or_updatez1NestedUpdateMixin.perform_nested_delete_or_update&  s    %%!(L9KK.$$++=+AB%22<<IX{33++779G"G		:]//9:		rD   c                 X   t        t        t        |j                                           }|j                         D ]  \  }\  }}}|j                  j
                  }| j                         |   }|j                  r|g}|j                  r|j                  j                  i}	n1t        |t              r| j                  |      }	n|j                  i}	| j                  ||      }
	 t         |j                  j                   d	i |	j#                  |
      j%                  dd            }| j'                  |||||       	 y # t(        $ rY}|j*                  d   }| j-                  ddj/                  |D cg c]  }t1        |       nc c}w c}             Y d }~hd }~ww xY w)
NrX   rJ   T)flat   r   z, )r[   r<   )r   reversedlistr   r.   r/   ra   rb   re   r   rf   r   r   rK   rV   rG   rQ   excludevalues_listr   r
   argsfailjoinrN   )r"   r7   r$   r&   r(   r'   rl   r4   rS   related_field_lookupcurrent_idsr   er[   s                 r*   r   z2NestedUpdateMixin.delete_reverse_relations_if_need8  s   'T+113457
 "''),	?<J<|****K++-j9L'' ,~ ))!..33X($ M?;,,X}E % "&&($ 33E<HK? $.K''.. .g*  !k$Tk2! 44!! C,	?R " ?FF1I			3tyy2;J=&.CMJ= J= @>	 ? ??s%   (AE	F)*F$:FF$$F))
r   r   r   r   r   default_error_messagesr=   r   r   r   r   s   @r*   r   r   	  s0     	"1($)&$2?rD   r   c                   @     e Zd ZdZg Z fdZd Z fdZ fdZ x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                 t   g | _         t        t        |          }|j	                         D ]  \  }}|j
                  D cg c]  }t        |t              r| }}|s2| j                   j                  ||d   f       |j
                  D cg c]  }t        |t              s| c}|_         |S c c}w c c}w )Nr   )	_unique_fieldsr|   r   
get_fieldsr   
validatorsr   r   rR   )r"   r   r&   r'   	validatorunique_validatorsr@   s         r*   r   zUniqueFieldsMixin.get_fields  s     ($:<!' 		CJ272B2B!L%.$.y/$J "+ !L !L !##**J8I!8L+MN/4/?/?$C"+%iA $C 		C !L$Cs   B0B5c                 B   | j                   D ]h  }|\  }}| j                  r||vr	 t        |d      r*|j                  | j                  |           |||          n |||   | j                  |          j y # t
        $ r}t        ||j                  i      d }~ww xY w)Nset_context)r   r9   r>   r   r   r   ri   )r"   r#   unique_fieldr&   unique_validatorrr   s         r*   _validate_unique_fieldsz)UniqueFieldsMixin._validate_unique_fields  s     // 	@L+7(J(||
. @	@+];$00Z1HI$^J%?@$^J%?%)[[%<>	@ # @%z3::&>??@s   AA99	BBBc                 L    | j                  |       t        t        |   |      S r   )r   r|   r   r   )r"   r#   r@   s     r*   r   zUniqueFieldsMixin.create  s$    $$^4&4^DDrD   c                 N    | j                  |       t        t        |   ||      S r   )r   r|   r   r=   )r"   r7   r#   r@   s      r*   r=   zUniqueFieldsMixin.update  s&    $$^4&4X~NNrD   )
r   r   r   r   r   r   r   r   r=   r   r   s   @r*   r   r   m  s-    $J N"@ EO OrD   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   r   django.utils.translationr   r   rest_frameworkr   rest_framework.exceptionsr   rest_framework.validatorsr   r   r   r   r   r   r<   rD   r*   <module>r      sq    0  > : 4 B B K 6 & 5 5a ; ; aH1 *a?1 a?HOO33 OOrD   