3
u^sK                 @   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mZ dd dD Zdd ej D Z ej!ddj"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.dDd)d*Z/dEd+d,Z0d-d. Z1dFd0d1Z2d2d3 Z3d4d5 Z4dGd6d7Z5G d8d9 d9e$Z6d:d; Z7d<d= Z8d>d? Z9d@dA Z:dBdC Z;dS )H    N)defaultdict)FieldDoesNotExist)modelsrouter)
LOOKUP_SEP)	Collector)pretty_name)NoReverseMatchreverse)formatstimezone)format_html)capfirst)ngettextoverridec             C   s   i | ]}d | |qS )z_%02X ).0ir   r   >/usr/lib/python3.6/site-packages/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   |j t}xt|D ]l}|dkr$| jj}y| j|}W n tk
rH   wY qX t|dr|j }|d j} t	dd |D rdS qW dS )	zT
    Return True if 'distinct()' should be used to query the given lookup path.
    pkget_path_infor   c             s   s   | ]}|j V  qd S )N)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_pathlookup_fields
field_namefield	path_infor   r   r   lookup_needs_distinct   s    



r3   c             C   s0   | j dr|jd}n| j dr,|j dk}|S )zJ
    Return a lookup value prepared to be used in queryset filtering.
    __in,Z__isnull false0)r6   r7   r8   )endswithr(   lower)keyvaluer   r   r   prepare_lookup_value4   s
    

r=   c             C   s   t | tr| j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   quoteA   s    rC   c             C   s   t jdd | S )zUndo the effects of quote().c             S   s   t | jd S )Nr   )UNQUOTE_MAPgroup)mr   r   r   <lambda>M   s    zunquote.<locals>.<lambda>)
UNQUOTE_REsub)rB   r   r   r   unquoteK   s    rJ   c             C   s:   g }x0| D ](}t |ttfr(|j| q
|j| q
W |S )zS
    Return a list which is a single level of flattening of the original list.
    )r>   listtupleextendappend)fieldsflatr1   r   r   r   flattenP   s    
rQ   c             C   s,   g }x"| D ]\}}|j t|d  q
W |S )z?Return a list of field names from an admin fieldsets structure.rO   )rM   rQ   )	fieldsetsfield_namesr)   r.   r   r   r   flatten_fieldsets]   s
    rT   c       	         s   y| d }W n t k
r*   g i t g fS X tj|jj}t|d}|j|  t  fdd|j}fdd|j	D }dd |j
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| j| sJj|j y(td j|j	|j
f d t| jf}W n tk
r   |S X tdt|j|| S |S d S )Nz%s: %sz%s:%s_%s_changez{}: <a href="{}">{}</a>)	__class__	_registry_metar   verbose_namehas_delete_permissionaddr
   r)   	app_label
model_namerC   r"   r	   r   )objmodelZ	has_adminr.   Zno_edit_linkZ	admin_url)
admin_siteperms_neededrequestr   r   format_callbacky   s(    
z,get_deleted_objects.<locals>.format_callbackc                s   g | ]} |qS r   r   )r   r^   )rc   r   r   r      s    z'get_deleted_objects.<locals>.<listcomp>c             S   s   i | ]\}}t ||jjqS r   )lenrX   verbose_name_plural)r   r_   objsr   r   r   r      s    z'get_deleted_objects.<locals>.<dictcomp>)
IndexErrorsetr   db_for_writerX   r_   NestedObjectscollectnested	protected
model_objsitems)	rf   rb   r`   r^   rU   	collectorZ	to_deleterm   model_countr   )r`   rc   ra   rb   r   get_deleted_objectsg   s    


rr   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 )rj   c                s*   t  j|| i | _t | _tt| _d S )N)super__init__edgesrh   rm   r   rn   )selfargskwargs)rV   r   r   rt      s    zNestedObjects.__init__c             C   s   | j j|g j| d S )N)ru   
setdefaultrN   )rv   sourcetargetr   r   r   add_edge   s    zNestedObjects.add_edgeNc                s   xf|D ]^}|rD|j d rD||jj|jjd }| jt||| n| jd | | j|jj j| qW yt	 j
|fd|i|S  tjk
r } z| jj|j W Y d d }~X nX d S )N+)classr\   source_attr)r9   rX   r]   r\   r|   getattrrn   r_   r[   rs   rk   r   ProtectedErrorrm   updateprotected_objects)rv   rf   rz   r   rx   r^   related_namee)rV   r   r   rk      s    
zNestedObjects.collectc                s   t  j||}|j|jjS )N)rs   related_objectsselect_relatedr1   r)   )rv   relatedrf   qs)rV   r   r   r      s    zNestedObjects.related_objectsc             C   sn   ||krg S |j | g }x*| jj|f D ]}|j| j||| q*W |rV||g}n|g}|rj|j| |S )N)r[   ru   getrM   _nestedrN   )rv   r^   seenrc   childrenchildretr   r   r   r      s    

zNestedObjects._nestedc             C   s:   t  }g }x*| jjdf D ]}|j| j||| qW |S )z4
        Return the graph as a nested list.
        N)rh   ru   r   rM   r   )rv   rc   r   rootsrootr   r   r   rl      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   )rv   rw   rx   r   r   r   can_fast_delete   s    zNestedObjects.can_fast_delete)NN)N)r   r   r    rt   r|   rk   r   r   rl   r   __classcell__r   r   )rV   r   rj      s   

rj   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.
    )rY   re   )r>   r   Modelbase	ModelBaserX   queryQuerySetr_   rY   re   )r^   r.   r   r   r   model_format_dict   s    
r   c             C   sN   t | tjjr$|dkr| j }| 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.
    NrY   re   r   )r>   r   r   r   countr_   r   r   )r^   ndsingularpluralr   r   r   model_ngettext   s    	r   c             C   s   |j }y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__)rX   _get_non_gfk_fieldr   r   callabler+   r   )r)   r^   model_adminr.   fattrr<   r   r   r   lookup_field  s$    





r   c             C   sV   | j |}|jr*|jr|j s$|jr*t |jrR|j rRt|drR|j|krRt	 |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_relationmany_to_onerelated_modelone_to_manyr   many_to_manyr+   r   r   )r.   r)   r1   r   r   r   r     s    
"r   Fc       	      C   s  d}y<t |j| }y
|j}W n tk
r:   |jjj}Y nX W n\ tk
r|   | dkrnt|jj}t}n
t| r|| }nt|| rt	|| }nrt|| rt	|| }n\|r| |j
kr|j
|  }nBd| |jjf }|r|d|jjf 7 }|r|d|jj 7 }t|t|dr|j}n`t|trHt|drHt|jdrH|jj}n0t|rp|jdkrdd}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   rX   rY   AttributeErrorr   r   r?   r   r+   r   rO   object_namerV   r   r   r>   propertyr   r   r   )	r)   r_   r   Zreturn_attrformr   r1   labelmessager   r   r   label_for_field2  sT    





r   c             C   sB   d}yt |j| }W n ttfk
r,   Y nX t|dr>|j}|S )Nr6   	help_text)r   rX   r   r   r+   r   )r)   r_   r   r1   r   r   r   help_text_for_fieldn  s    
r   c             C   s   ddl m} t|dd r*t|jj| |S t|tjr>|| S | d krJ|S t|tj	rft
jtj| S t|tjtjfrt
j| S t|tjrt
j| |jS t|tjtjfrt
j| S t|tjr| rtd| j| S t| |S d S )Nr   )_boolean_iconflatchoicesz<a href="{}">{}</a>),django.contrib.admin.templatetags.admin_listr   r   dictr   r   r>   r   BooleanFieldDateTimeFieldr   localizer   template_localtime	DateField	TimeFieldDecimalFieldnumber_formatdecimal_placesIntegerField
FloatField	FileFieldr   urldisplay_for_value)r<   r1   empty_value_displayr   r   r   r   display_for_fieldz  s$    

r   c             C   s   ddl m} |r|| S | d kr$|S t| tr6t| S t| tjrRtjtj	| S t| tj
tjfrntj| S t| ttjtfrtj| S t| ttfrdjdd | D S t| S d S )Nr   )r   z, c             s   s   | ]}t |V  qd S )N)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   rK   rL   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| j d jjS td S )Nr#   r   r'   )r+   r#   r,   r_   r   )r1   r   r   r   get_model_from_relation  s    
r   c             C   s   g }| }|j t}x|D ]}|jj|}t|t|d kr`yt| W n tk
r^   P Y nX |jr|jor|j	  r|j
 }|jj}n|jj}|j}|jd| qW |tj|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   rX   r*   rd   r   r   r   auto_createdconcreterelated_query_name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   sH   |j t}g }x4|D ],}|r*t|d }n| }|j|jj| qW |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   r   rN   rX   r*   )r_   r%   r   rO   r   r   r   r   r   get_fields_from_path  s    	

r   c             C   s"  | j }td t| |}W dQ R X g }|r<|jdi i n| j rT|jdd|ii |rtd x|D ]}x.|jD ]$}|jdt|jjt|di qvW x@|jD ]6\}}	|jdt|jjt|t|j	d |	di qW x.|j
D ]$}
|jdt|
jjt|
di qW qjW W d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.
    NZaddedchangedrO   )r)   objectr   )r)   r   rO   deleted)changed_datatranslation_override#_get_changed_field_labels_from_formrN   new_objectsr?   rX   rY   changed_objectsformsdeleted_objects)r   formsetsr[   r   changed_field_labelschange_messageformsetZadded_objectZchanged_objectZchanged_fieldsZdeleted_objectr   r   r   construct_change_message  s8    	





"r   c             C   sR   g }xH|D ]@}y| j | jp|}W n tk
r:   |}Y nX |jt| q
W |S )N)rO   r   KeyErrorrN   r?   )r   r   r   r0   Zverbose_field_namer   r   r   r     s    

r   )N)N)NFN)F)<r   r   recollectionsr   django.core.exceptionsr   	django.dbr   r   django.db.models.constantsr   django.db.models.deletionr   django.forms.utilsr   django.urlsr	   r
   django.utilsr   r   django.utils.htmlr   django.utils.textr   django.utils.translationr   r   r   rA   ro   rD   compiler   rH   	Exceptionr   r3   r=   rC   rJ   rQ   rT   rr   rj   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sN   

8?


<
1