
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# Gd 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, Gd% d&   d& e  Z- d' d(   Z. d d) d*  Z/ d d+ d,  Z0 d- d.   Z1 d d/ d d0 d1  Z2 d2 d3   Z3 d4 d5   Z4 d/ d6 d7  Z5 Gd8 d9   d9 e$  Z6 d: d;   Z7 d< d=   Z8 d> d?   Z9 d@ dA   Z: dB dC   Z; d S)D    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   </tmp/pip-build-8lau8j11/django/django/contrib/admin/utils.py
<dictcomp>   s   	 r   s   ":/_#?;@&=+$,"[]<>%
\c             C   s%   i  |  ] \ } } t  |  |  q Sr   )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  } x | D] } | d k r4 |  j j } y |  j |  } Wn t k
 r^ w Yq Xt | d  r | j   } | d j }  t	 d d   | D  r d Sq Wd 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)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    r0   c             C   sF   |  j  d  r! | j d  } n! |  j  d  rB | j   d k } | S)zJ
    Return a lookup value prepared to be used in queryset filtering.
    Z__in,Z__isnull false0)r2   zfalser4   )endswithr'   lower)keyvaluer   r   r   prepare_lookup_value4   s
    r9   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    r?   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)r>   r   r   r   unquoteK   s    rF   c             C   sM   g  } x@ |  D]8 } t  | t t f  r8 | 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)fieldsZflatr/   r   r   r   flattenP   s    rL   c             C   s8   g  } x+ |  D]# \ } } | j  t | d   q W| S)z?Return a list of field names from an admin fieldsets structure.rK   )rI   rL   )Z	fieldsetsfield_namesr(   r-   r   r   r   flatten_fieldsets]   s
    rN   c       	         s   y |  d } Wn% t  k
 r5 g  i  t   g  f SYn Xt 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  |   si  j | j  y8 t d   j | j	 | j
 f d  t |  j  f  } Wn t k
 r | SYn Xt d t | j  | |   S| Sd  S)Nz%s: %sz%s:%s_%s_changez{}: <a href="{}">{}</a>)	__class__	_registry_metar   verbose_nameZhas_delete_permissionaddr
   r(   	app_label
model_namer?   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 Sr   r   )r   rW   )r\   r   r   r      s   	 z'get_deleted_objects.<locals>.<listcomp>c             S   s+   i  |  ]! \ } } t  |  | j j  q Sr   )lenrR   verbose_name_plural)r   rX   objsr   r   r   r      s   	 z'get_deleted_objects.<locals>.<dictcomp>)
IndexErrorsetr   Zdb_for_writerR   rX   NestedObjectscollectnested	protected
model_objsitems)	r_   r[   rY   rW   rO   Z	collectorZ	to_deletere   Zmodel_countr   )rY   r\   rZ   r[   r   get_deleted_objectsg   s    	rh   c                   s   e  Z d  Z   f d d   Z d d   Z d d   f d d  Z   f d d	   Z d
 d   Z d d d  Z d d   Z	   S)rb   c                s;   t    j | |   i  |  _ t   |  _ t t  |  _ d  S)N)super__init__edgesra   re   r   rf   )selfargskwargs)rP   r   r   rj      s    	zNestedObjects.__init__c             C   s    |  j  j | g   j |  d  S)N)rk   
setdefaultrJ   )rl   sourcetargetr   r   r   add_edge   s    zNestedObjects.add_edgeNc                s   x | D] } | ra | j  d  ra | d | j j d | j j i } |  j t | |  |  n |  j d  |  |  j | j j j |  q Wy t	   j
 | d | | SWn; t j k
 r } z |  j j | j  WYd  d  } ~ Xn Xd  S)N+classrU   source_attr)r5   rR   rV   rU   rr   getattrrf   rX   rT   ri   rc   r   ZProtectedErrorre   updateZprotected_objects)rl   r_   rp   ru   rn   rW   related_namee)rP   r   r   rc      s    zNestedObjects.collectc                s(   t    j | |  } | j | j j  S)N)ri   related_objectsZselect_relatedr/   r(   )rl   relatedr_   qs)rP   r   r   rz      s    zNestedObjects.related_objectsc             C   s   | | k r g  S| j  |  g  } x9 |  j j | f   D]" } | j |  j | | |   q9 W| rw | |  g } n	 | g } | r | j |  | S)N)rT   rk   getrI   _nestedrJ   )rl   rW   seenr\   childrenchildretr   r   r   r~      s     	zNestedObjects._nestedc             C   sO   t    } g  } x9 |  j j d f   D]" } | j |  j | | |   q% W| S)z4
        Return the graph as a nested list.
        N)ra   rk   r}   rI   r~   )rl   r\   r   rootsrootr   r   r   rd      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   )rl   rm   rn   r   r   r   can_fast_delete   s    zNestedObjects.can_fast_delete)
r   r   r    rj   rr   rc   rz   r~   rd   r   r   r   )rP   r   rb      s   
rb   c             C   sj   t  |  t j t j j f  r* |  j } n* t  |  t j j  rN |  j j } n |  } d | j	 d | j
 i 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.
    rS   r^   )r:   r   ZModelbaseZ	ModelBaserR   queryQuerySetrX   rS   r^   )rW   r-   r   r   r   model_format_dict   s    	r   c             C   sm   t  |  t j j  r6 | d k r- |  j   } |  j }  t |   } | d | d } } t | | | pi d  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.
    NrS   r^   r   )r:   r   r   r   countrX   r   r   )rW   ndZsingularpluralr   r   r   model_ngettext   s    		r   c             C   s   | j  } y t | |   } Wn t t f k
 r t |   rS |  } | |  } nf t | |   r |  d k r t | |   } | |  } n- t | |   } t |  r |   } n | } d  } Yn Xd  } t | |   } | | | f S)N__str__)rR   _get_non_gfk_fieldr   r   callabler*   rv   )r(   rW   model_adminr-   fattrr8   r   r   r   lookup_field  s$    	r   c             C   s{   |  j  |  } | j r= | j r+ | j s4 | j r= t    | j rw | j rw t | d  rw | j | k rw t	    | 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_onerelated_modelZone_to_manyr   Zmany_to_manyr*   r   r   )r-   r(   r/   r   r   r   r     s    		1	r   Fc       	      C   s5  d } yG t  | j |   } y | j } Wn! t k
 rK | j j j } Yn XWnt k
 r|  d k r t | j j  } t } nqt |   r |  } n t | |   r t	 | |   } n t | |   r t	 | |   } n~ | r |  | j
 k r | j
 |  } nY d |  | j j f } | r3| d | j j f 7} | rM| d | j j 7} t |   t | d  rt| j } n t | t  rt | d  rt | j d  r| j j } nB t |  r| j d k rd } qt | j  } n t |   } Yn$ t k
 rt |   } |  } Yn X| r-| | f S| Sd 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   rR   rS   AttributeErrorr   r   r;   r   r*   rv   rK   Zobject_namerP   r   r   r:   propertyr   r   r   )	r(   rX   r   Zreturn_attrformr   r/   labelmessager   r   r   label_for_field2  sT    			
r   c             C   sS   d } y t  | j |   } Wn t t f k
 r6 Yn Xt | d  rO | j } | S)Nr2   	help_text)r   rR   r   r   r*   r   )r(   rX   r   r/   r   r   r   help_text_for_fieldn  s    	r   c             C   s@  d d l  m } t | d d   r; t | j  j |  |  St | t j  rW | |   S|  d  k rg | St | t j	  r t
 j t j |    St | t j t j f  r t
 j |   St | t j  r t
 j |  | j  St | t j t j f  rt
 j |   St | t j  r/|  r/t d |  j |   St |  |  Sd  S)Nr   )_boolean_iconflatchoicesz<a href="{}">{}</a>),django.contrib.admin.templatetags.admin_listr   rv   dictr   r}   r:   r   ZBooleanFieldZDateTimeFieldr   localizer   template_localtimeZ	DateFieldZ	TimeFieldZDecimalFieldnumber_formatZdecimal_placesZIntegerFieldZ
FloatFieldZ	FileFieldr   urldisplay_for_value)r8   r/   empty_value_displayr   r   r   r   display_for_fieldz  s$    
r   c             C   s   d d l  m } | r  | |   S|  d  k r0 | St |  t  rI t |   St |  t j  rq t j t j	 |    St |  t j
 t j f  r t j |   St |  t t j t f  r t j |   St |  t t f  r d j d d   |  D  St |   Sd  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decimalZDecimalfloatr   rG   rH   join)r8   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 St  d  S)Nr#   r   r&   )r*   r#   r+   rX   r   )r/   r   r   r   get_model_from_relation  s    r   c             C   s   g  } |  } | j  t  } x | D] } | j j |  } t |  t |  d k rz y t |  Wn t k
 ry PYn X| j r | j o | 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   rR   r)   r]   r   r   r   Zauto_createdZconcreteZrelated_query_nameZremote_fieldrX   r/   r(   r   insertr   )rX   r$   Zreversed_pathparentpiecespiecer/   rx   r   r   r   reverse_field_path  s"    	r   c             C   sb   | j  t  } g  } xF | 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   rJ   rR   r)   )rX   r$   r   rK   r   r   r   r   r   get_fields_from_path  s    	r   c             C   s  |  j  } t d   t |  |  } Wd QRXg  } | rN | j d i  i  n" |  j  rp | j d d | i i  | rt d  x | D] } xB | j D]7 } | j d d t | j j  d t |  i i  q Wx^ | j D]S \ } }	 | j d d t | j j  d t |  d t | j	 d |	  i i  q WxB | j
 D]7 }
 | j d d t |
 j j  d t |
  i i  q@Wq WWd QRX| 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changedrK   r(   objectr   Zdeleted)changed_datatranslation_override#_get_changed_field_labels_from_formrJ   Znew_objectsr;   rR   rS   Zchanged_objectsZformsZdeleted_objects)r   ZformsetsrT   r   changed_field_labelsZchange_messageZformsetZadded_objectZchanged_objectZchanged_fieldsZdeleted_objectr   r   r   construct_change_message  s8    			$%r   c             C   sc   g  } xV | D]N } y |  j  | j p) | } Wn t k
 rG | } Yn X| j t |   q W| S)N)rK   r   KeyErrorrJ   r;   )r   r   r   r.   Zverbose_field_namer   r   r   r     s    r   )<r   r   re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.textr   Zdjango.utils.translationr   r   r   r=   rg   r@   compiler   rD   	Exceptionr   r0   r9   r?   rF   rL   rN   rh   rb   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sN   )

8?<1