
     +hj                     H    d Z ddlmZ ddlmZ  G d dej                  ZdS )a  
tl;dr: See FutureModelForm's docstring.

Many apps provide new related managers to extend your django models with. For
example, django-tagulous provides a TagField which abstracts an M2M relation
with the Tag model, django-gm2m provides a GM2MField which abstracts an
relation, django-taggit provides a TaggableManager which abstracts a relation
too, django-generic-m2m provides RelatedObjectsDescriptor which abstracts a
relation again.

While that works pretty well, it gets a bit complicated when it comes to
encapsulating the business logic for saving such data in a form object. This is
three-part problem:

- getting initial data,
- saving instance attributes,
- saving relations like reverse relations or many to many.

Django's ModelForm calls the model field's ``value_from_object()`` method to
get the initial data. ``FutureModelForm`` tries the ``value_from_object()``
method from the form field instead, if defined. Unlike the model field, the
form field doesn't know its name, so ``FutureModelForm`` passes it when calling
the form field's ``value_from_object()`` method.

Django's ModelForm calls the form field's ``save_form_data()`` in two
occasions:

- in ``_post_clean()`` for model fields in ``Meta.fields``,
- in ``_save_m2m()`` for model fields in ``Meta.virtual_fields`` and
  ``Meta.many_to_many``, which then operate on an instance which as a PK.

If we just added ``save_form_data()`` to form fields like for
``value_from_object()`` then it would be called twice, once in
``_post_clean()`` and once in ``_save_m2m()``. Instead, ``FutureModelForm``
would call the following methods from the form field, if defined:

- ``save_object_data()`` in ``_post_clean()``, to set object attributes for a
  given value,
- ``save_relation_data()`` in ``_save_m2m()``, to save relations for a given
  value.

For example:

- a generic foreign key only sets instance attributes, its form field would do
  that in ``save_object_data()``,
- a tag field saves relations, its form field would do that in
  ``save_relation_data()``.
    )chain)formsc                   P     e Zd ZdZ fdZ fdZd ZddZed             Z	 xZ
S )	FutureModelForma/  
    ModelForm which adds extra API to form fields.

    Form fields may define new methods for FutureModelForm:

    - ``FormField.value_from_object(instance, name)`` should return the initial
      value to use in the form, overrides ``ModelField.value_from_object()``
      which is what ModelForm uses by default,
    - ``FormField.save_object_data(instance, name, value)`` should set instance
      attributes. Called by ``save()`` **before** writing the database, when
      ``instance.pk`` may not be set, it overrides
      ``ModelField.save_form_data()`` which is normally used in this occasion
      for non-m2m and non-virtual model fields.
    - ``FormField.save_relation_data(instance, name, value)`` should save
      relations required for value on the instance. Called by ``save()``
      **after** writing the database, when ``instance.pk`` is necessarily set,
      it overrides ``ModelField.save_form_data()`` which is normally used in
      this occasion for m2m and virtual model fields.

    For complete rationale, see this module's docstring.
    c                      t          t          |           j        |i | | j                                        D ]9\  }}t          |d          s|                    | j        |          | j        |<   :dS )z:Override that uses a form field's ``value_from_object()``.value_from_objectN)	superr   __init__fieldsitemshasattrr   instanceinitial)selfargskwargsnamefield	__class__s        M/var/www/html/e360mart/e360mart_env/lib/python3.11/site-packages/dal/forms.pyr
   zFutureModelForm.__init__N   s    -ot$$-t>v>>>;,,.. 	N 	NKD%5"566 !&!8!8!M!MDL		N 	N    c           	          t          t          |                                            | j                                        D ]K\  }}t          |d          s|                    | j        || j        	                    |d                     LdS );Override that uses the form field's ``save_object_data()``.save_object_dataN)
r	   r   _post_cleanr   r   r   r   r   cleaned_dataget)r   r   r   r   s      r   r   zFutureModelForm._post_cleanX   s    ot$$00222;,,.. 	 	KD%5"455 ""!%%dD11   		 	r   c                 j   | j         }| j        j        }| j        j        }| j        j        }g }| j                                        D ]M\  }}t          |d          s|                    | j        |||                    |                    |           Nt          |dg           }|st          |dg           }t          |j        |          D ]d}	|	j        |v rt          |	d          s|r
|	j        |vr)|r
|	j        |v r5|	j        |v r&|	                    | j        ||	j                            edS )r   save_relation_datavirtual_fieldsprivate_fieldssave_form_dataN)r   _metaexcluder   r   r   r   r   appendgetattrr   many_to_manyr   r"   )
r   r   r$   r   optshandledr   r   r    fs
             r   	_save_m2mzFutureModelForm._save_m2mf   s   (*$"}" ;,,.. 
	! 
	!KD%5"677 $$T"   NN4    
 !'7<< 	A$T+;R@@Nt(.99 	F 	FAv  1.//  !&.. 16W,,v%%  QV0DEEE	F 	Fr   Tc                    | j         r8t          d| j        j        j        d| j        j        j        rdndd          |r.| j                                         |                                  n| j        | _	        | j        S )z"Backport from Django 1.9+ for 1.8.zThe z could not be createdchangedz" because the data didn't validate.)
errors
ValueErrorr   r#   object_name_stateaddingsaver+   save_m2m)r   commits     r   r4   zFutureModelForm.save   s    ; 	*M'333!%!5!<KII)KK    	+M   NN !NDM}r   c                 Z      fd j         d                                         D             S )z
        Create a list of url patterns, to be called in url.py.

        Example::

            urlpattern.append(*ModelForm.as_url())

        Iterate over the fields to call the as_url() method from the
        GenericForeignKeyField
        c                 j    g | ]/\  }}t          |j        d           |                              0S )as_url)r   r   r9   ).0keyvalueclss      r   
<listcomp>z+FutureModelForm.as_urls.<locals>.<listcomp>   sK     
 
 
Uu11
LL
 
 
r   declared_fields)__dict__r   )r=   s   `r   as_urlszFutureModelForm.as_urls   sB    
 
 
 
!l+<=CCEE
 
 
 	
r   )T)__name__
__module____qualname____doc__r
   r   r+   r4   classmethodrA   __classcell__)r   s   @r   r   r   7   s         ,N N N N N    'F 'F 'FR   & 
 
 [
 
 
 
 
r   r   N)rE   	itertoolsr   djangor   	ModelFormr    r   r   <module>rL      sv   / /b            {
 {
 {
 {
 {
eo {
 {
 {
 {
 {
r   