U
    dƳ                     @   s  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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mZ d d
lmZ d dlmZ d dlmZ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*m+Z+m,Z, ddl-m.Z. e/e0Z1e12e3  dd Z4dd Z5G dd dZ6G dd de7Z8G dd dZ9G dd  d e8d!Z:G d"d# d#e8Z;G d$d% d%e:e;d!Z<e<fd&d'Z=dS )(    N)OrderedDict)deepcopy)diff_match_patch)settings)FieldDoesNotExistImproperlyConfiguredValidationError)no_style)	Paginator)connectionsrouter)ForeignObjectRel)QuerySet)TransactionManagementError	savepointsavepoint_commitsavepoint_rollback)	force_str)	mark_safe   )widgets)Field)ModelInstanceLoader)ErrorResult	RowResult)atomic_if_using_transactionc                 C   s   t | dr| jS d S )Nrelated_model)hasattrr   )field r    ;/tmp/pip-unpacked-wheel-gh2cwdms/import_export/resources.pyget_related_model(   s    
r"   c                 C   s   t | dot | jdS )z@
    Determine if a model has natural foreign key functions
    Znatural_keyZget_by_natural_key)r   objectsmodelr    r    r!   has_natural_foreign_key,   s    r&   c                   @   sb   e Zd ZdZdZdZdZdZdgZdZ	dZ
dZdZdZdZdZdZdZdZdZdZdZdZdZdS )ResourceOptionsz
    The inner Meta class allows for class-level configuration of how the
    Resource should behave. The following options are available:
    NidFTi  )__name__
__module____qualname____doc__r%   fieldsexcludeinstance_loader_classimport_id_fieldsexport_orderr   use_transactionsskip_unchangedreport_skippedclean_model_instances
chunk_size	skip_diffskip_html_diffuse_bulk
batch_sizeforce_init_instanceusing_dbstore_row_valuesuse_natural_foreign_keysr    r    r    r!   r'   2   s,   r'   c                       s   e Zd Z fddZ  ZS )DeclarativeMetaclassc                    s  g }t  }|d d d D ]Z}t|drt|j | }t|dd   fddt D D ]}t||t | qZq|  D ]6\}}	t	|	t
r||}
|
js||
_|||
f qt||d< t | |||}t|dd   fddt D D ]}t||t | q||_|S )Nr-   Metac                    s$   g | ]}| d st |r|qS _
startswithr   .0optionoptionsr    r!   
<listcomp>   s    
 
z0DeclarativeMetaclass.__new__.<locals>.<listcomp>c                    s$   g | ]}| d st |r|qS rB   rD   rF   rI   r    r!   rK      s    
 
)r'   r   listr-   itemsgetattrdirsetattrcopy
isinstancer   popcolumn_nameappendr   super__new___meta)clsnamebasesattrsdeclared_fieldsmetabaserH   
field_nameobjr   	new_class	__class__rI   r!   rW      s*    


zDeclarativeMetaclass.__new__r)   r*   r+   rW   __classcell__r    r    rc   r!   r?      s   r?   c                   @   s.   e Zd Zdd ZdddZdd Zdd	 Zd
S )Diffc                 C   s   |  ||| _g | _|| _d S N)_export_resource_fieldsleftrightnew)selfresourceinstancerl   r    r    r!   __init__   s    zDiff.__init__Fc                 C   s   |  ||| _d S rh   )ri   rk   )rm   rn   ro   dry_runr    r    r!   compare_with   s    zDiff.compare_withc                 C   sr   g }t  }t| j| jD ]T\}}||kr2| jr2d}|t|t|}|| ||}t	|}|
| q|S )N )r   ziprj   rk   rl   Z	diff_mainr   Zdiff_cleanupSemanticZdiff_prettyHtmlr   rU   )rm   dataZdmpZv1Zv2diffhtmlr    r    r!   as_html   s    

zDiff.as_htmlc                    s    fdd  D S )Nc                    s    g | ]} r | nd qS )rs   export_fieldrG   fro   rn   r    r!   rK     s     z0Diff._export_resource_fields.<locals>.<listcomp>get_user_visible_fields)rm   rn   ro   r    r}   r!   ri     s    zDiff._export_resource_fieldsN)F)r)   r*   r+   rp   rr   rx   ri   r    r    r    r!   rg      s   
rg   c                   @   s  e Zd ZdZdd Ze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dd ZdkddZdd Zdd Zdd Zdd  Zdld!d"Zdmd#d$Zd%d& Zdnd(d)Zdod+d,Zd-d. Zd/d0 Zdpd1d2Zd3d4 Zd5d6 Zdqd7d8Zd9d: Zd;d< Z d=d> Z!d?d@ Z"drdAdBZ#dCdD Z$dEdF Z%dGdH Z&dsdIdJZ'dtdKdLZ(dudMdNZ)dvdOdPZ*dwdQdRZ+dxdSdTZ,dUdV Z-dWdX Z.dYdZ Z/d[d\ Z0d]d^ Z1d_d` Z2dadb Z3dcdd Z4dedf Z5dgdh Z6dydidjZ7dS )zResourcez
    Resource defines how objects are mapped to their import and export
    representations and handle importing and exporting data.
    c                 C   s(   t | j| _t | _t | _t | _d S rh   )r   r-   rL   create_instancesupdate_instancesdelete_instancesrm   r    r    r!   rp     s    zResource.__init__c                 C   s   t S )zJ
        Returns the class used to store the result of an import.
        )r   r   r    r    r!   get_result_class  s    zResource.get_result_classc                 C   s   t S )zM
        Returns the class used to store the result of a row import.
        )r   r   r    r    r!   get_row_result_class#  s    zResource.get_row_result_classc                 C   s   t S )zT
        Returns the class used to store an error resulting from an import.
        )r   r   r    r    r!   get_error_result_class*  s    zResource.get_error_result_classc                 C   s   t S )zV
        Returns the class used to display the diff for an imported instance.
        )rg   r   r    r    r!   get_diff_class1  s    zResource.get_diff_classc                 C   s&   | j jd krt| j jS | j jS d S rh   )rX   r<   r   Zdb_for_writer%   r   r    r    r!   get_db_connection_name8  s    zResource.get_db_connection_namec                 C   s$   | j jd krttddS | j jS d S )NZIMPORT_EXPORT_USE_TRANSACTIONST)rX   r2   rN   r   r   r    r    r!   get_use_transactions>  s    zResource.get_use_transactionsc                 C   s$   | j jd krttddS | j jS d S )NZIMPORT_EXPORT_CHUNK_SIZEd   )rX   r6   rN   r   r   r    r    r!   get_chunk_sizeD  s    zResource.get_chunk_sizec                    s    fdd   D S )z{
        Returns fields sorted according to
        :attr:`~import_export.resources.ResourceOptions.export_order`.
        c                    s   g | ]} j | qS r    r-   r{   r   r    r!   rK   O  s     z'Resource.get_fields.<locals>.<listcomp>)get_export_order)rm   kwargsr    r   r!   
get_fieldsJ  s    zResource.get_fieldsc                 C   s:   | j  D ]\}}||kr
|  S q
td|| jf dS )z;
        Returns the field name for a given field.
        z'Field %s does not exists in %s resourceN)r-   rM   AttributeErrorrd   )rm   r   r`   r|   r    r    r!   get_field_nameQ  s    
 zResource.get_field_nameNc                 C   s
   t  dS )z|
        Initializes an object. Implemented in
        :meth:`import_export.resources.ModelResource.init_instance`.
        N)NotImplementedErrorrm   rowr    r    r!   init_instance[  s    zResource.init_instancec                    s:    fdd   D }|D ]}|j|kr dS q||S )z
        If all 'import_id_fields' are present in the dataset, calls
        the :doc:`InstanceLoader <api_instance_loaders>`. Otherwise,
        returns `None`.
        c                    s   g | ]} j | qS r    r   r{   r   r    r!   rK   h  s    z)Resource.get_instance.<locals>.<listcomp>N)get_import_id_fieldsrT   get_instance)rm   instance_loaderr   r0   r   r    r   r!   r   b  s    

zResource.get_instancec                 C   s.   | j js | ||}|r |dfS | |dfS )zW
        Either fetches an already existing instance or initializes a new one.
        FT)rX   r;   r   r   )rm   r   r   ro   r    r    r!   get_or_init_instancep  s
    zResource.get_or_init_instancec                 C   s   | j jS )z	
        rX   r0   r   r    r    r!   r   z  s    zResource.get_import_id_fieldsc                    s    fdd j D S )z
        Returns the fields to be included in calls to bulk_update().
        ``import_id_fields`` are removed because `id` fields cannot be supplied to bulk_update().
        c                    s   g | ]}| j jkr|qS r    r   r{   r   r    r!   rK     s      z3Resource.get_bulk_update_fields.<locals>.<listcomp>r   r   r    r   r!   get_bulk_update_fields  s    zResource.get_bulk_update_fieldsc              
   C   s~   zlz2t| j dkr2|s|rn| jjjj| j |d W n4 tk
rh } zt	| |rX|W 5 d}~X Y nX W 5 | j   X dS )z=
        Creates objects by calling ``bulk_create``.
        r   r:   N)
r   clearlenrX   r%   r#   bulk_create	Exceptionlogger	exceptionrm   using_transactionsrq   raise_errorsr:   er    r    r!   r     s    
zResource.bulk_createc              
   C   s   zrz8t| j dkr8|s|rn| jjjj| j |  |d W n4 tk
rn } zt	
| |r^|W 5 d}~X Y nX W 5 | j   X dS )z=
        Updates objects by calling ``bulk_update``.
        r   r   N)r   r   r   rX   r%   r#   bulk_updater   r   r   r   r   r    r    r!   r     s    

zResource.bulk_updatec              
   C   s   z|zBt| j dkrB|s|rn&dd | j D }| jjjj|d  W n4 tk
rx } zt	
| |rh|W 5 d}~X Y nX W 5 | j   X dS )z
        Deletes objects by filtering on a list of instances to be deleted,
        then calling ``delete()`` on the entire queryset.
        r   c                 S   s   g | ]
}|j qS r    pk)rG   or    r    r!   rK     s     z(Resource.bulk_delete.<locals>.<listcomp>)Zpk__inN)r   r   r   rX   r%   r#   filterdeleter   r   r   )rm   r   rq   r   Z
delete_idsr   r    r    r!   bulk_delete  s    
zResource.bulk_deleteTc              
   C   sr   |dkri }n|  }| jjrbz|j| |d W n, tk
r` } z||}W 5 d}~X Y nX |rnt|dS )a  
        Takes any validation errors that were raised by
        :meth:`~import_export.resources.Resource.import_obj`, and combines them
        with validation errors raised by the instance's ``full_clean()``
        method. The combined errors are then re-raised as single, multi-field
        ValidationError.

        If the ``clean_model_instances`` option is False, the instances's
        ``full_clean()`` method is not called, and only the errors raised by
        ``import_obj()`` are re-raised.
        N)r.   validate_unique)rQ   rX   r5   Z
full_cleankeysr   update_error_dict)rm   ro   import_validation_errorsr   errorsr   r    r    r!   validate_instance  s    
zResource.validate_instanceFc                 C   sZ   |  ||| | jjr6|r(| j| qH| j| n|s@|r@n|  | ||| dS )a  
        Takes care of saving the object to the database.

        Objects can be created in bulk if ``use_bulk`` is enabled.

        :param instance: The instance of the object to be persisted.
        :param is_create: A boolean flag to indicate whether this is a new object
        to be created, or an existing object to be updated.
        :param using_transactions: A flag to indicate whether db transactions are used.
        :param dry_run: A flag to indicate dry-run mode.
        N)before_save_instancerX   r9   r   rU   r   saveafter_save_instance)rm   ro   Z	is_creater   rq   r    r    r!   save_instance  s    zResource.save_instancec                 C   s   dS zL
        Override to add additional logic. Does nothing by default.
        Nr    rm   ro   r   rq   r    r    r!   r     s    zResource.before_save_instancec                 C   s   dS r   r    r   r    r    r!   r     s    zResource.after_save_instancec                 C   sD   |  || | jjr"| j| n|s,|r,n|  | || dS )z
        Calls :meth:`instance.delete` as long as ``dry_run`` is not set.
        If ``use_bulk`` then instances are appended to a list for bulk import.
        N)before_delete_instancerX   r9   r   rU   r   after_delete_instancer   r    r    r!   delete_instance  s    zResource.delete_instancec                 C   s   dS r   r    rm   ro   rq   r    r    r!   r     s    zResource.before_delete_instancec                 C   s   dS r   r    r   r    r    r!   r     s    zResource.after_delete_instancec                 K   s&   |j r"|j|kr"|j|||f| dS )z
        Calls :meth:`import_export.fields.Field.save` if ``Field.attribute``
        is specified, and ``Field.column_name`` is found in ``data``.
        N)	attributerT   r   )rm   r   ra   ru   Zis_m2mr   r    r    r!   import_field  s    zResource.import_fieldc                 C   s   |   S rh   r   r   r    r    r!   get_import_fields"  s    zResource.get_import_fieldsc                 K   s   i }|   D ]d}t|jtjr qz| j|||f| W q tk
rn } ztt|dd||j	< W 5 d}~X Y qX q|r~t|dS )a9  
        Traverses every field in this Resource and calls
        :meth:`~import_export.resources.Resource.import_field`. If
        ``import_field()`` results in a ``ValueError`` being raised for
        one of more fields, those errors are captured and reraised as a single,
        multi-field ValidationError.invalid)codeN)
r   rR   widgetr   ManyToManyWidgetr   
ValueErrorr   r   r   )rm   ra   ru   rq   r   r   r   r   r    r    r!   
import_obj%  s      zResource.import_objc                 C   sD   |s|s@| j jrn.|  D ]$}t|jtjs.q| |||d qdS )z
        Saves m2m fields.

        Model instance need to have a primary key value before
        a many-to-many relationship can be used.
        TN)rX   r9   r   rR   r   r   r   r   )rm   ra   ru   r   rq   r   r    r    r!   save_m2m8  s    zResource.save_m2mc                 C   s   dS )z
        Returns ``True`` if ``row`` importing should delete instance.

        Default implementation returns ``False``.
        Override this method to handle deletion.
        Fr    )rm   r   ro   r    r    r!   
for_deleteI  s    zResource.for_deletec                 C   s   | j jr| j js|rdS |  D ]}t|jtjr|j|	 krBq t
||}t
|| }t|t|krx dS tdd |D tdd |D kr dS q ||||kr  dS q dS )aP  
        Returns ``True`` if ``row`` importing should be skipped.

        Default implementation returns ``False`` unless skip_unchanged == True
        and skip_diff == False.

        If skip_diff is True, then no comparisons can be made because ``original``
        will be None.

        When left unspecified, skip_diff and skip_unchanged both default to ``False``, 
        and rows are never skipped.

        By default, rows are not skipped if validation errors have been detected
        during import.  You can change this behavior and choose to ignore validation
        errors by overriding this method.

        Override this method to handle skipping rows meeting certain
        conditions.

        Use ``super`` if you want to preserve default handling while overriding
        ::
            class YourResource(ModelResource):
                def skip_row(self, instance, original, row, import_validation_errors=None):
                    # Add code here
                    return super().skip_row(instance, original, row, import_validation_errors=import_validation_errors)

        Fc                 s   s   | ]}|j V  qd S rh   r   )rG   vr    r    r!   	<genexpr>~  s     z$Resource.skip_row.<locals>.<genexpr>T)rX   r3   r7   r   rR   r   r   r   rT   r   rL   clean	get_valueallr   sorted)rm   ro   originalr   r   r   Zinstance_valuesZoriginal_valuesr    r    r!   skip_rowR  s    $zResource.skip_rowc                 C   s   |   S )z.
        Diff representation headers.
        )get_user_visible_headersr   r    r    r!   get_diff_headers  s    zResource.get_diff_headersc                 K   s   dS r   r    )rm   datasetr   rq   r   r    r    r!   before_import  s    zResource.before_importc                 K   s   dS r   r    )rm   r   resultr   rq   r   r    r    r!   after_import  s    zResource.after_importc                 K   s   dS r   r    )rm   r   
row_numberr   r    r    r!   before_import_row  s    zResource.before_import_rowc                 K   s   dS r   r    )rm   r   
row_resultr   r   r    r    r!   after_import_row  s    zResource.after_import_rowc                 K   s   dS r   r    )rm   ro   rl   r   r   r    r    r!   after_import_instance  s    zResource.after_import_instancec              
   K   s  | j j}|   }| j jr ||_d}	z| j|f| | ||\}
}| j|
|f| |rdtj	|_
ntj|_
||_|st|
}	|  | |	|}| ||
r|rtj|_
|s|| d| n2tj|_
||
 | |
|| |s|| d| ni }z| j|
||f| W n. tk
r6 } z||}W 5 d}~X Y nX | |
|	||rTtj|_
n6| |
| | |
||| | |
||| ||
 |s|| |
| |s| j js| |_| j||f| W n tk
r } ztj |_
||_!W 5 d}~X Y nf t"k
r` } zFtj#|_
t$|t%s0t&j'||d t() }|j*+| , ||| W 5 d}~X Y nX | j j-rt.| j/| j j0kr| j1|||| j j0d t.| j2| j j0kr| j3|||| j j0d t.| j4| j j0kr| 5||| |S )a  
        Imports data from ``tablib.Dataset``. Refer to :doc:`import_workflow`
        for a more complete description of the whole import process.

        :param row: A ``dict`` of the row to import

        :param instance_loader: The instance loader to be used to load the row

        :param using_transactions: If ``using_transactions`` is set, a transaction
            is being used to wrap the import

        :param dry_run: If ``dry_run`` is set, or error occurs, transaction
            will be rolled back.
        Nexc_infor   )6rX   r7   r   r=   Z
row_valuesr   r   r   r   IMPORT_TYPE_NEWimport_typeZIMPORT_TYPE_UPDATEZ
new_recordr   r   r   IMPORT_TYPE_SKIPrr   ZIMPORT_TYPE_DELETEZadd_instance_infor   r   r   r   r   r   r   r   r8   rx   rv   r   ZIMPORT_TYPE_INVALIDvalidation_errorr   ZIMPORT_TYPE_ERRORrR   r   r   debug	traceback
format_excr   rU   r   r9   r   r   r:   r   r   r   r   r   )rm   r   r   r   rq   r   r   r7   r   r   ro   rl   rv   r   r   tb_infor    r    r!   
import_row  sv    





*
zResource.import_rowc              
   K   s   |dkr|   }|  }t| }	t|	jdd}
|r:|
s:t|sB|oD|
}| jjdk	rtt| jjt	rl| jjdk rtt
dt||d& | j||||||f|W  5 Q R  S Q R X dS )aw  
        Imports data from ``tablib.Dataset``. Refer to :doc:`import_workflow`
        for a more complete description of the whole import process.

        :param dataset: A ``tablib.Dataset``

        :param raise_errors: Whether errors should be printed to the end user
            or raised regularly.

        :param use_transactions: If ``True`` the import process will be processed
            inside a transaction.

        :param collect_failed_rows: If ``True`` the import process will collect
            failed rows.

        :param rollback_on_validation_errors: If both ``use_transactions`` and ``rollback_on_validation_errors``
            are set to ``True``, the import process will be rolled back in case of ValidationError.

        :param dry_run: If ``dry_run`` is set, or an error occurs, if a transaction
            is being used, it will be rolled back.
        Nsupports_transactionsFr   z%Batch size must be a positive integerZusing)r   r   r   rN   featuresr   rX   r:   rR   intr   r   import_data_inner)rm   r   rq   r   r2   collect_failed_rowsrollback_on_validation_errorsr   db_connection
connectionr   r   r    r    r!   import_data  s*    &    zResource.import_datac              
   K   s  |    }|  |_t||_|  }	|r4t|	d}
z.t||	d | j|||f| W 5 Q R X W nR t	k
r } z4t
j||d t }||  || |r W 5 d }~X Y nX | j| |}t||_|r||j t|jdD ]\}}t||	d$ | j||f||||d|}W 5 Q R X || |jrf|rR|||jd  |r|jd jn8|jr||||j |r|||j |r|j|jtjks| jj r|!| q| jj"rt||	d0 | #||| | $||| | %||| W 5 Q R X z0t||	d | j&||||f| W 5 Q R X W nV t	k
r } z6t
j||d t }||  || |r W 5 d }~X Y nX |r|s|' s|r|( rt)|
|	d nt*|
|	d |S )Nr   r   r   )r   rq   r   r   r   r@   )+r   r   Zdiff_headersr   Z
total_rowsr   r   r   r   r   r   r   r   r   Zappend_base_errorr   rX   r/   Zadd_dataset_headersheaders	enumeratedictr   Zincrement_row_result_totalr   Zappend_failed_rowerrorr   Zappend_invalid_rowr   r   r   r4   Zappend_row_resultr9   r   r   r   r   Z
has_errorsZhas_validation_errorsr   r   )rm   r   rq   r   r   r   r   r   r   r   Zsp1r   r   r   ir   r   r    r    r!   r   2  s    



 
	

"zResource.import_data_innerc                    s,   t | jjpd  t  fdd| jD  S )Nr    c                 3   s   | ]}| kr|V  qd S rh   r    )rG   korderr    r!   r     s      z,Resource.get_export_order.<locals>.<genexpr>)tuplerX   r1   r-   r   r    r   r!   r     s    zResource.get_export_orderc                 O   s   dS r   r    )rm   querysetargsr   r    r    r!   before_export  s    zResource.before_exportc                 O   s   dS r   r    )rm   r   ru   r   r   r    r    r!   after_export  s    zResource.after_exportc                 C   s4   |  |}t| d| d }|d k	r*||S ||S )Nzdehydrate_%s)r   rN   export)rm   r   ra   r`   methodr    r    r!   rz     s
    
zResource.export_fieldc                 C   s   |   S rh   r   r   r    r    r!   get_export_fields  s    zResource.get_export_fieldsc                    s    fdd  D S )Nc                    s   g | ]} | qS r    ry   rG   r   ra   rm   r    r!   rK     s     z,Resource.export_resource.<locals>.<listcomp>r  )rm   ra   r    r  r!   export_resource  s    zResource.export_resourcec                 C   s   dd |   D }|S )Nc                 S   s   g | ]}t |jqS r    r   rT   r  r    r    r!   rK     s    z/Resource.get_export_headers.<locals>.<listcomp>r  rm   r   r    r    r!   get_export_headers  s    zResource.get_export_headersc                 C   s   dd |   D }|S )Nc                 S   s   g | ]}t |jqS r    r  r  r    r    r!   rK     s    z5Resource.get_user_visible_headers.<locals>.<listcomp>r~   r  r    r    r!   r     s    z!Resource.get_user_visible_headersc                 C   s   |   S rh   r   r   r    r    r!   r     s    z Resource.get_user_visible_fieldsc                 c   s|   t |ts|E d H  nb|jrb|jjs.|d}t||  }t|jD ]}|	|d E d H  qFn|j
|  dE d H  d S )Nr   r   )r6   )rR   r   Z_prefetch_related_lookupsqueryZorder_byr
   r   rangeZ	num_pagesZget_pageiterator)rm   r   Z	paginatorindexr    r    r!   iter_queryset  s    

zResource.iter_querysetc                 O   sn   | j |f|| |dkr"|  }|  }tj|d}| |D ]}|| | q@| j||f|| |S )z%
        Exports a resource.
        N)r   )	r   get_querysetr	  tablibZDatasetr  rU   r  r   )rm   r   r   r   r   ru   ra   r    r    r!   r     s    zResource.export)N)N)N)NT)TF)TF)F)N)N)N)N)TFF)FFNFF)F)N)8r)   r*   r+   r,   rp   classmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rz   r  r  r	  r   r   r  r   r    r    r    r!   r   	  sz   












	
3



\     
/ 
Vr   )	metaclassc                       s   e Zd Z fddZ  ZS )ModelDeclarativeMetaclassc                    s   t  | |||}|j}|js$t|_|jr|jj}|j}g }t|j|j D ]^}	|jd k	rj|	j	|jkrjqN|j
r~|	j	|j
kr~qN|	j	|krqN|j|	j	|	dd}
||	j	|
f qN|jt| |jd k	rg }|jD ]4}||krq|ddkrq|j}|d}t|D ]\}}d|jjg|d|d   }z|j|}	W nF tk
r } z&tj||d td	||j|f W 5 d }~X Y nX |t|d k rt|	trt|	}n"t|	d krtd
| t|	}qt|	tr|	j}	|j||	dd}
|||
f q|jt| |S )NF)readonly__r@   .r   r   r   z%s: %s has no field named '%s'z%s is not a relationT)rV   rW   rX   r/   r   r%   r-   r   Zmany_to_manyrZ   r.   field_from_django_fieldrU   updater   findsplitr   joinr)   	get_fieldr   r   r   r   rR   r   r"   KeyErrorr   )rY   rZ   r[   r\   rb   optsZ
model_optsr]   Z
field_listr|   r   r`   r%   r   attrZverbose_pathr   rc   r    r!   rW     sp    


 

z!ModelDeclarativeMetaclass.__new__re   r    r    rc   r!   r    s   r  c                   @   s   e Zd ZdZeZdddejejej	ej
ejejejejejejejejejejejejejejdZedd Zedd Zeejfd	d
Zedd Zedd Zdd ZdddZdd Zedd ZdS )ModelResourcezH
    ModelResource is Resource subclass for handling Django models.
    get_m2m_widgetget_fk_widget)ZManyToManyFieldZOneToOneFieldZ
ForeignKeyZ	CharFieldZDecimalFieldZDateTimeFieldZ	DateFieldZ	TimeFieldZDurationFieldZ
FloatFieldZIntegerFieldZPositiveIntegerFieldZBigIntegerFieldZPositiveSmallIntegerFieldZSmallIntegerFieldZSmallAutoFieldZ	AutoFieldZBigAutoFieldZNullBooleanFieldZBooleanFieldZ	JSONFieldc                 C   s   t jtjt|dS )z.
        Prepare widget for m2m field
        r$   )	functoolspartialr   r   r"   )rY   r   r    r    r!   r!  A  s    zModelResource.get_m2m_widgetc                 C   s*   t |}t|o| jj}tjtj||dS )z6
        Prepare widget for fk and o2o fields
        )r%   r>   )r"   r&   rX   r>   r#  r$  r   ZForeignKeyWidget)rY   r   r%   r>   r    r    r!   r"  J  s    zModelResource.get_fk_widgetc                 C   s   |}d}t t|ddr | }|| jkrN| j| }t|trt| ||}nDzddlm} W n" tk
r   G dd d}Y nX t||rt	j
S |S )a	  
        Returns the widget that would likely be associated with each
        Django type.

        Includes mapping of Postgres Array field. In the case that
        psycopg2 is not installed, we consume the error and process the field
        regardless.
        rs   get_internal_typeNr   )
ArrayFieldc                   @   s   e Zd ZdS )z:ModelResource.widget_from_django_field.<locals>.ArrayFieldN)r)   r*   r+   r    r    r    r!   r&  s  s   r&  )callablerN   r%  WIDGETS_MAPrR   strZdjango.contrib.postgres.fieldsr&  ImportErrorr   ZSimpleArrayWidget)rY   r|   defaultr   Zinternal_typer&  r    r    r!   widget_from_django_field[  s    




z&ModelResource.widget_from_django_fieldc                 C   s   | j jr| j j|i S i S )z=
        Returns widget kwargs for given field_name.
        )rX   r   get)rm   r`   r    r    r!   widget_kwargs_for_field{  s    z%ModelResource.widget_kwargs_for_fieldc                 C   s4   |  |}| |}| j|||f |||jd}|S )zU
        Returns a Resource Field instance for the given Django model field.
        )r   rT   r   r  r+  )r,  r.  DEFAULT_RESOURCE_FIELDr+  )rY   r`   Zdjango_fieldr  ZFieldWidgetZwidget_kwargsr   r    r    r!   r    s    

z%ModelResource.field_from_django_fieldc                 C   s   | j jj S )z
        Returns a queryset of all objects for this model. Override this if you
        want to limit the returned queryset.
        )rX   r%   r#   r   r   r    r    r!   r    s    zModelResource.get_querysetNc                 C   s
   | j  S )z1
        Initializes a new Django model.
        )rX   r%   r   r    r    r!   r     s    zModelResource.init_instancec                 K   sr   |snt dd |jD rn|  }t| }|jt | jjg}|rn|	 }	z|D ]}
|	|
 qPW 5 |	
  X dS )zH
        Reset the SQL sequences after new objects are imported
        c                 s   s   | ]}|j tjkV  qd S rh   )r   r   r   )rG   rr    r    r!   r     s     z-ModelResource.after_import.<locals>.<genexpr>N)anyZrowsr   r   opsZsequence_reset_sqlr	   rX   r%   cursorcloseexecute)rm   r   r   r   rq   r   r   r   Zsequence_sqlr3  liner    r    r!   r     s    zModelResource.after_importc                 C   s   t | jdr| jjS | jS )NrZ   )r   rX   rZ   r)   )rY   r    r    r!   get_display_name  s    zModelResource.get_display_name)N)r)   r*   r+   r,   r   r/  r   Z
CharWidgetZDecimalWidgetZDateTimeWidgetZ
DateWidgetZ
TimeWidgetZDurationWidgetZFloatWidgetZIntegerWidgetZBooleanWidgetZ
JSONWidgetr(  r  r!  r"  ZWidgetr,  r.  r  r  r   r   r7  r    r    r    r!   r   "  sN   




r   c                 C   sB   d| i}t tdtf|}| jtd }d|i}t}|||f|S )zN
    Factory for creating ``ModelResource`` class for given Django model.
    r%   rA   r   )typer)  objectr)   r  )r%   Zresource_classr\   rA   
class_nameZclass_attrsr  r    r    r!   modelresource_factory  s     r;  )>r#  loggingr   collectionsr   rQ   r   r  r   Zdjango.confr   Zdjango.core.exceptionsr   r   r   Zdjango.core.management.colorr	   Zdjango.core.paginatorr
   Z	django.dbr   r   Zdjango.db.models.fields.relatedr   Zdjango.db.models.queryr   Zdjango.db.transactionr   r   r   r   Zdjango.utils.encodingr   Zdjango.utils.safestringr   rs   r   r-   r   Zinstance_loadersr   resultsr   r   r   utilsr   	getLoggerr)   r   
addHandlerNullHandlerr"   r&   r'   r8  r?   rg   r   r  r   r;  r    r    r    r!   <module>   sN   
 '     SK 