U
    HaLM                     @   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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 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 dd dD Z dd e ! D Z"edd#dd e"D  Z$G dd de%Z&dd Z'dd Z(dd Z)dd Z*d d! Z+d"d# Z,d$d% Z-G d&d' d'eZ.d(d) Z/dEd*d+Z0dFd,d-Z1d.d/ Z2dGd1d2Z3d3d4 Z4d5d6 Z5dHd7d8Z6G d9d: d:e%Z7d;d< Z8d=d> Z9d?d@ Z:dAdB Z;dCdD Z<dS )I    N)defaultdict)FieldDoesNotExist)modelsrouter)
LOOKUP_SEP)	Collector)pretty_name)NoReverseMatchreverse)formatstimezone)format_html)_lazy_re_compile)capfirst)ngettextoverridec                 C   s   i | ]}|d | qS )z_%02X ).0ir   r   >/tmp/pip-unpacked-wheel-3jxiddxt/django/contrib/admin/utils.py
<dictcomp>   s      r   s   ":/_#?;@&=+$,"[]<>%
\c                 C   s   i | ]\}}|t |qS r   )chr)r   kvr   r   r   r      s      z_(?:%s)|c                 C   s   g | ]}|d d qS )   Nr   )r   xr   r   r   
<listcomp>   s     r   c                   @   s   e Zd ZdZdS )FieldIsAForeignKeyColumnNamez/A field is a foreign key attname, i.e. <FK>_id.N)__name__
__module____qualname____doc__r   r   r   r   r      s   r   c              	   C   s   | t}|D ]p}|dkr"| jj}z| |}W n tk
rH   Y qY qX t|dr| }|d j} t	dd |D r dS qdS )zT
    Return True if 'distinct()' should be used to query the given lookup path.
    pkget_path_infoc                 s   s   | ]}|j V  qd S N)Zm2m)r   pathr   r   r   	<genexpr>/   s     z(lookup_needs_distinct.<locals>.<genexpr>TF)
splitr   r#   name	get_fieldr   hasattrr$   to_optsany)optsZlookup_pathZlookup_fields
field_namefieldZ	path_infor   r   r   lookup_needs_distinct   s    



r2   c                 C   s0   |  dr|d}n|  dr,| dk}|S )zJ
    Return a lookup value prepared to be used in queryset filtering.
    Z__in,Z__isnull) false0)endswithr)   lower)keyvaluer   r   r   prepare_lookup_value5   s
    

r;   c                 C   s   t | tr| tS | S )a*  
    Ensure that primary key values do not confuse the admin URLs by escaping
    any '/', '_' and ':' and similarly problematic characters.
    Similar to urllib.parse.quote(), except that the quoting is slightly
    different so that it doesn't get automatically unquoted by the Web browser.
    )
isinstancestr	translate	QUOTE_MAPsr   r   r   quoteB   s    rB   c                 C   s   t dd | S )zUndo the effects of quote().c                 S   s   t | d  S )Nr   )UNQUOTE_MAP)mr   r   r   <lambda>N       zunquote.<locals>.<lambda>)
UNQUOTE_REsubr@   r   r   r   unquoteL   s    rI   c                 C   s6   g }| D ](}t |ttfr&|| q|| q|S )zS
    Return a list which is a single level of flattening of the original list.
    )r<   listtupleextendappend)fieldsZflatr1   r   r   r   flattenQ   s    rO   c                 C   s(   g }| D ]\}}| t|d  q|S )z?Return a list of field names from an admin fieldsets structure.rN   )rL   rO   )Z	fieldsetsfield_namesr*   r/   r   r   r   flatten_fieldsets^   s    
rQ   c           	         s   z| d }W n" t k
r.   g i t g f Y S X t|jj}t|d}||  t  fdd|}fdd|j	D }dd |j
 D }|||fS )	a  
    Find all objects related to ``objs`` that should also be deleted. ``objs``
    must be a homogeneous iterable of objects (e.g. a QuerySet).

    Return a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.
    r   )usingc                    s   | j }| jk}| j}dt|j| f }|r j| | sJ|j z(td j|j	|j
f d t| jf}W n tk
r   | Y S X tdt|j|| S |S d S )Nz%s: %sz%s:%s_%s_changez{}: <a href="{}">{}</a>)	__class__	_registry_metar   verbose_nameZhas_delete_permissionaddr
   r*   	app_label
model_namerB   r#   r	   r   )objmodelZ	has_adminr/   Zno_edit_linkZ	admin_url)
admin_siteperms_neededrequestr   r   format_callbackz   s2    
 

z,get_deleted_objects.<locals>.format_callbackc                    s   g | ]} |qS r   r   )r   rZ   )r_   r   r   r      s     z'get_deleted_objects.<locals>.<listcomp>c                 S   s   i | ]\}}|j jt|qS r   )rU   verbose_name_plurallen)r   r[   objsr   r   r   r      s      z'get_deleted_objects.<locals>.<dictcomp>)
IndexErrorsetr   Zdb_for_writerU   r[   NestedObjectscollectnested	protected
model_objsitems)	rb   r^   r\   rZ   rR   	collectorZ	to_deleterh   Zmodel_countr   )r\   r_   r]   r^   r   get_deleted_objectsh   s    


rl   c                       sX   e Zd Z fddZdd Zd fdd	Z fdd	Zd
d ZdddZdd Z	  Z
S )re   c                    s*   t  j|| i | _t | _tt| _d S r&   )super__init__edgesrd   rh   r   ri   selfargskwargsrS   r   r   rn      s    zNestedObjects.__init__c                 C   s   | j |g | d S r&   )ro   
setdefaultrM   )rq   sourcetargetr   r   r   add_edge   s    zNestedObjects.add_edgeNc              
      s   |D ]\}|r@| ds@||jj|jjd }| t||| n| d | | j|jj | qzt	 j
|fd|i|W S  tjk
r } z| j|j W 5 d }~X Y n2 tjk
r } z| j|j W 5 d }~X Y nX d S )N+)classrX   source_attr)r7   rU   rY   rX   rx   getattrri   r[   rW   rm   rf   r   ZProtectedErrorrh   updateZprotected_objectsZRestrictedErrorZrestricted_objects)rq   rb   rv   r{   rs   rZ   related_nameert   r   r   rf      s    zNestedObjects.collectc                    s$   t  |||}|jdd |D  S )Nc                 S   s   g | ]
}|j qS r   )r*   )r   Zrelated_fieldr   r   r   r      s     z1NestedObjects.related_objects.<locals>.<listcomp>)rm   related_objectsZselect_related)rq   related_modelZrelated_fieldsrb   qsrt   r   r   r      s    zNestedObjects.related_objectsc                 C   sj   ||krg S | | g }| j|dD ]}|| ||| q(|rR||g}n|g}|rf|| |S )Nr   )rW   ro   getrL   _nestedrM   )rq   rZ   seenr_   childrenchildretr   r   r   r      s    

zNestedObjects._nestedc                 C   s6   t  }g }| jddD ]}|| ||| q|S )z4
        Return the graph as a nested list.
        Nr   )rd   ro   r   rL   r   )rq   r_   r   rootsrootr   r   r   rg      s
    zNestedObjects.nestedc                 O   s   dS )z
        We always want to load the objects into memory so that we can display
        them to the user in confirm page.
        Fr   rp   r   r   r   can_fast_delete   s    zNestedObjects.can_fast_delete)NN)N)r   r    r!   rn   rx   rf   r   r   rg   r   __classcell__r   r   rt   r   re      s   

re   c                 C   sF   t | tjtjjfr| j}nt | tjjr4| jj}n| }|j	|j
dS )z
    Return a `dict` with keys 'verbose_name' and 'verbose_name_plural',
    typically for use with string formatting.

    `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance.
    )rV   r`   )r<   r   ZModelbaseZ	ModelBaserU   queryQuerySetr[   rV   r`   )rZ   r/   r   r   r   model_format_dict   s    
r   c                 C   sN   t | tjjr$|dkr|  }| j} t| }|d |d  }}t|||pJdS )a-  
    Return the appropriate `verbose_name` or `verbose_name_plural` value for
    `obj` depending on the count `n`.

    `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance.
    If `obj` is a `QuerySet` instance, `n` is optional and the length of the
    `QuerySet` is used.
    NrV   r`   r   )r<   r   r   r   countr[   r   r   )rZ   ndZsingularpluralr   r   r   model_ngettext   s    	r   c              	   C   s   |j }zt|| }W nv ttfk
r   t| r>| }||}nDt|| rd| dkrdt|| }||}nt|| }t|r~| }n|}d }Y nX d }t|| }|||fS )N__str__)rU   _get_non_gfk_fieldr   r   callabler,   r|   )r*   rZ   model_adminr/   fattrr:   r   r   r   lookup_field  s$    





r   c                 C   sR   |  |}|jr(|jr|jr"|jr(t |jrN|jsNt|drN|j|krNt	 |S )a  
    For historical reasons, the admin app relies on GenericForeignKeys as being
    "not found" by get_field(). This could likely be cleaned up.

    Reverse relations should also be excluded as these aren't attributes of the
    model (rather something like `foo_set`).
    attname)
r+   is_relationZmany_to_oner   Zone_to_manyr   Zmany_to_manyr,   r   r   )r/   r*   r1   r   r   r   r      s    
 r   Fc           	      C   s  d}z<t |j| }z
|j}W n tk
r:   |jjj}Y nX W nZ tk
rz   | dkrnt|jj}t}nt| r|| }nt|| rt	|| }npt|| rt	|| }nZ|r| |j
kr|j
|  }n@d| |jjf }|r|d|jj 7 }|r|d|jj 7 }t|t|dr|j}n`t|trFt|drFt|jdrF|jj}n0t|rn|jdkrbd}n
t|j}nt| }Y n" tk
r   t| }| }Y nX |r||fS |S dS )	ak  
    Return a sensible label for a field name. The name can be a callable,
    property (but not created with @property decorator), or the name of an
    object's attribute, as well as a model field. If return_attr is True, also
    return the resolved attribute (which could be a callable). This will be
    None if (and only if) the name refers to a field.
    Nr   zUnable to lookup '%s' on %sz or %sshort_descriptionfgetz<lambda>z--)r   rU   rV   AttributeErrorr   r   r=   r   r,   r|   rN   Zobject_namerS   r   r   r<   propertyr   r   r   )	r*   r[   r   Zreturn_attrformr   r1   labelmessager   r   r   label_for_field5  sX    






r   c              	   C   sB   d}zt |j| }W n ttfk
r,   Y nX t|dr>|j}|S )Nr4   	help_text)r   rU   r   r   r,   r   )r*   r[   r   r1   r   r   r   help_text_for_fieldq  s    
r   c                 C   s0  ddl m} t|dd r*t|j| |S t|tjr>|| S | d krJ|S t|tj	rft
t| S t|tjtjfrt
| S t|tjrt
| |jS t|tjtjfrt
| S t|tjr| rtd| j| S t|tjr"| r"ztj| d|jdW S  tk
r   t| | Y S X n
t| |S d S )Nr   _boolean_iconflatchoicesz<a href="{}">{}</a>F)ensure_asciicls),django.contrib.admin.templatetags.admin_listr   r|   dictr   r   r<   r   ZBooleanFieldZDateTimeFieldr   localizer   template_localtimeZ	DateFieldZ	TimeFieldZDecimalFieldnumber_formatZdecimal_placesZIntegerFieldZ
FloatFieldZ	FileFieldr   urlZ	JSONFieldjsondumpsencoder	TypeErrordisplay_for_value)r:   r1   empty_value_displayr   r   r   r   display_for_field}  s.    

r   c                 C   s   ddl m} |r|| S | d kr$|S t| tr6t| S t| tjrRtt	| S t| tj
tjfrnt| S t| ttjtfrt| S t| ttfrddd | D S t| S d S )Nr   r   z, c                 s   s   | ]}t |V  qd S r&   )r=   )r   r   r   r   r   r(     s     z$display_for_value.<locals>.<genexpr>)r   r   r<   boolr=   datetimer   r   r   r   datetimeintdecimalDecimalfloatr   rJ   rK   join)r:   r   booleanr   r   r   r   r     s     


r   c                   @   s   e Zd ZdS )NotRelationFieldN)r   r    r!   r   r   r   r   r     s   r   c                 C   s"   t | dr|  d jjS td S )Nr$   r%   )r,   r$   r-   r[   r   )r1   r   r   r   get_model_from_relation  s    
r   c              	   C   s   g }| }| t}|D ]}|j|}t|t|d krbzt| W n tk
r`   Y  qY nX |jr|jrt|j	r|
 }|jj}n|jj}|j}|d| q|t|fS )z Create a reversed field path.

    E.g. Given (Order, "user__groups"),
    return (Group, "user__order").

    Final field must be a related model, not a data field.
    r   r   )r)   r   rU   r+   ra   r   r   r   Zauto_createdZconcreteZrelated_query_nameZremote_fieldr[   r1   r*   r   insertr   )r[   r'   Zreversed_pathparentpiecespiecer1   r~   r   r   r   reverse_field_path  s"    

r   c                 C   sD   | t}g }|D ],}|r(t|d }n| }||j| q|S )a;   Return list of Fields given path relative to model.

    e.g. (ModelX, "user__groups__name") -> [
        <django.db.models.fields.related.ForeignKey object at 0x...>,
        <django.db.models.fields.related.ManyToManyField object at 0x...>,
        <django.db.models.fields.CharField object at 0x...>,
    ]
    r%   )r)   r   r   rM   rU   r+   )r[   r'   r   rN   r   r   r   r   r   get_fields_from_path  s    	
r   c                 C   s  | j }td t| |}W 5 Q R X g }|r<|di i n| j rT|dd|ii |rtd |D ]}|jD ]$}|dt|jjt|di qr|jD ]6\}}	|dt|jjt|t|j	d |	di q|j
D ]$}
|dt|
jjt|
di qqhW 5 Q R X |S )	z
    Construct a JSON structure describing changes from a changed object.
    Translations are deactivated so that strings are stored untranslated.
    Translation happens later on LogEntry access.
    NaddedchangedrN   )r*   objectr   )r*   r   rN   Zdeleted)changed_datatranslation_override#_get_changed_field_labels_from_formrM   Znew_objectsr=   rU   rV   Zchanged_objectsZformsZdeleted_objects)r   ZformsetsrW   r   changed_field_labelsZchange_messageZformsetZadded_objectZchanged_objectZchanged_fieldsZdeleted_objectr   r   r   construct_change_message  sD    	






r   c              	   C   sN   g }|D ]@}z| j | jp|}W n tk
r8   |}Y nX |t| q|S r&   )rN   r   KeyErrorrM   r=   )r   r   r   r0   Zverbose_field_namer   r   r   r     s    
r   )N)N)NFN)F)=r   r   r   collectionsr   Zdjango.core.exceptionsr   Z	django.dbr   r   Zdjango.db.models.constantsr   Zdjango.db.models.deletionr   Zdjango.forms.utilsr   Zdjango.urlsr	   r
   Zdjango.utilsr   r   Zdjango.utils.htmlr   Zdjango.utils.regex_helperr   Zdjango.utils.textr   Zdjango.utils.translationr   r   r   r?   rj   rC   r   rG   	Exceptionr   r2   r;   rB   rI   rO   rQ   rl   re   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sP   

8A


<
1