3
(hB                 @   s  d dl mZ d dlZd dl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 d d	lmZ d d
lmZ d dlmZmZ d dlmZmZ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$ 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-d<d#d$Z.d=d%d&Z/d'd( Z0d>d*d+Z1d,d- Z2d.d/ Z3d?d0d1Z4G d2d3 d3e5Z6d4d5 Z7d6d7 Z8d8d9 Z9d:d; Z:dS )@    )unicode_literalsN)defaultdict)get_permission_codename)FieldDoesNotExist)models)
LOOKUP_SEP)	Collector)QUERY_TERMS)pretty_name)NoReverseMatchreverse)formatssixtimezone)	force_str
force_text
smart_text)format_html)capfirst)	ungettextc             C   sp   |j d}|d	 tkr"|dd
 }xH|D ]@}| j|}t|dr(|j }|d j} tdd |D r(dS q(W dS )zU
    Returns True if 'distinct()' should be used to query the given lookup path.
    __   Nget_path_infoc             s   s   | ]}|j V  qd S )N)Zm2m).0path r   >/tmp/pip-install-q3hcpn_q/Django/django/contrib/admin/utils.py	<genexpr>%   s    z(lookup_needs_distinct.<locals>.<genexpr>TFr   r   )splitr	   	get_fieldhasattrr   to_optsany)optsZlookup_pathZlookup_fields
field_namefieldZ	path_infor   r   r   lookup_needs_distinct   s    




r'   c             C   s8   | j dr|jd}| j dr4|j d	kr0d}nd}|S )
zK
    Returns a lookup value prepared to be used in queryset filtering.
    Z__in,Z__isnull false0FT)r)   r*   r+   )endswithr   lower)keyvaluer   r   r   prepare_lookup_value+   s    


r0   c             C   sX   t | tjs| S t| }x4tt|D ]$}|| }|dkr&dt| ||< q&W dj|S )a"  
    Ensure that primary key values do not confuse the admin URLs by escaping
    any '/', '_' and ':' and similarly problematic characters.
    Similar to urllib.quote, except that the quoting is slightly different so
    that it doesn't get automatically unquoted by the Web browser.
    z:/_#?;@&=+$,"[]<>%
\z_%02Xr)   )
isinstancer   string_typeslistrangelenordjoin)sresicr   r   r   quote;   s    r<   c             C   s   t }t}| jd}|d g}|j}|d= xr|D ]j}|dd ry*||||dd d|dd   W q tk
r   |d|  Y qX q.|d|  q.W dj|S )zI
    Undo the effects of quote(). Based heavily on urllib.unquote().
    _r   r      N   r)   )chrintr   append
ValueErrorr7   )r8   ZmychrZmyatoir3   r9   Zmyappenditemr   r   r   unquoteL   s    


*rE   c             C   s:   g }x0| D ](}t |ttfr(|j| q
|j| q
W |S )zNReturns a list which is a single level of flattening of the
    original list.)r1   r3   tupleextendrB   )fieldsZflatr&   r   r   r   flattena   s    
rI   c             C   s,   g }x"| D ]\}}|j t|d  q
W |S )z@Returns a list of field names from an admin fieldsets structure.rH   )rG   rI   )Z	fieldsetsfield_namesnamer$   r   r   r   flatten_fieldsetsm   s
    rL   c       	         sh   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).

    Returns a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.
    )usingc                s   | j  jk}| j}dt|jt| f }|ry*td j|j|j	f d t
| j f}W n tk
rj   |S X d|jtd|f }j|sj|j tdt|j|| S |S d S )Nz%s: %sz%s:%s_%s_changez%s.%sdeletez{}: <a href="{}">{}</a>)	__class__	_registry_metar   verbose_namer   r   rK   	app_label
model_namer<   Z_get_pk_valr   r   Zhas_permaddr   )objZ	has_adminr$   Zno_edit_linkZ	admin_urlp)
admin_siteperms_neededuserr   r   format_callback   s,    

z,get_deleted_objects.<locals>.format_callbackc                s   g | ]} |qS r   r   )r   rV   )r[   r   r   
<listcomp>   s    z'get_deleted_objects.<locals>.<listcomp>c             S   s   i | ]\}}t ||jjqS r   )r5   rQ   verbose_name_plural)r   modelobjsr   r   r   
<dictcomp>   s    z'get_deleted_objects.<locals>.<dictcomp>)NestedObjectscollectsetnested	protected
model_objsitems)	r_   r$   rZ   rX   rM   Z	collectorZ	to_deletere   Zmodel_countr   )rX   r[   rY   rZ   r   get_deleted_objectsw   s    

 
rh   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 )ra   c                s.   t t| j|| i | _t | _tt| _d S )N)superra   __init__edgesrc   re   r   rf   )selfargskwargs)rO   r   r   rj      s    zNestedObjects.__init__c             C   s   | j j|g j| d S )N)rk   
setdefaultrB   )rl   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	t
| j|fd|i|S  tjk
r } z| jj|j W Y d d }~X nX d S )N+)classrS   source_attr)r,   rQ   rT   rS   rr   getattrrf   r^   rU   ri   ra   rb   r   ZProtectedErrorre   updateZprotected_objects)rl   r_   rp   ru   rn   rV   related_namee)rO   r   r   rb      s    
zNestedObjects.collectc                s    t t| j||}|j|jjS )N)ri   ra   related_objectsZselect_relatedr&   rK   )rl   relatedr_   qs)rO   r   r   rz      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)rU   rk   getrG   _nestedrB   )rl   rV   seenr[   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)rc   rk   r}   rG   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)NN)N)__name__
__module____qualname__rj   rr   rb   rz   r~   rd   r   __classcell__r   r   )rO   r   ra      s   

ra   c             C   sN   t | tjtjjfr| j}nt | tjjr4| jj}n| }t	|j
t	|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.
    )rR   r]   )r1   r   ZModelbaseZ	ModelBaserQ   queryQuerySetr^   r   rR   r]   )rV   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.
    NrR   r]   r   )r1   r   r   r   countr^   r   r   )rV   ndZsingularpluralr   r   r   model_ngettext   s    	r   c             C   s   |j }yt|| }W n tk
r   t| r:| }||}nX|d k	rtt|| rt| dk rt| dk rtt|| }||}nt|| }t|r| }n|}d }Y nX d }t|| }|||fS )N__str____unicode__)rQ   _get_non_gfk_fieldr   callabler!   rv   )rK   rV   model_adminr$   fattrr/   r   r   r   lookup_field  s*    








r   c             C   s.   | j |}|jr*|jr|j s$|jr*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`).
    )r    is_relationZmany_to_onerelated_modelZone_to_manyr   )r$   rK   r&   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 n0 tk
rp   | dkrnt|jj}tj}n| dkrt	|jj}t
}nt| r| }nb|dk	rt|| rt|| }nDt|| rt|| }n.d| |jjf }|r|d|jjf 7 }t|t|dr|j}n`t|tr<t|dr<t|jdr<|jj}n0t|rd|jdkrXd	}n
t|j}nt| }Y nX |r||fS |S dS )
as  
    Returns 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 genuine fields. If return_attr is
    True, the resolved attribute (which could be a callable) is also returned.
    This will be None if (and only if) the name refers to a field.
    Nr   r   zUnable to lookup '%s' on %sz or %sshort_descriptionfgetz<lambda>z--)r   rQ   rR   AttributeErrorr   r   r   r   	text_typer   bytesr   r!   rv   Zobject_namerO   r   r   r1   propertyr   r
   )rK   r^   r   Zreturn_attrr   r&   labelmessager   r   r   label_for_field<  sL    



r   c             C   sB   d}yt |j| }W n tk
r(   Y nX t|dr:|j}t|S )Nr)   	help_text)r   rQ   r   r!   r   r   )rK   r^   r   r&   r   r   r   help_text_for_fields  s    
r   c             C   s   ddl m} t|dd r*t|jj| |S t|tjsBt|tj	rJ|| S | d krV|S t|tj
rrt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   rv   dictr   r}   r1   r   ZBooleanFieldZNullBooleanFieldZDateTimeFieldr   localizer   template_localtimeZ	DateFieldZ	TimeFieldZDecimalFieldnumber_formatZdecimal_placesZIntegerFieldZ
FloatFieldZ	FileFieldr   urldisplay_for_value)r/   r&   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jr@tjtj| S t| tjtj	fr\tj| S t| t
jtjtf r|t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   vr   r   r   r     s    z$display_for_value.<locals>.<genexpr>)r   r   r1   datetimer   r   r   r   datetimer   integer_typesdecimalDecimalfloatr   r3   rF   r7   r   )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   )r&   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   rQ   r    r5   r   r   r   Zauto_createdZconcreteZrelated_query_nameZremote_fieldr^   r&   rK   r   insertr7   )r^   r   Zreversed_pathparentpiecespiecer&   rx   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   rB   rQ   r    )r^   r   r   rH   r   r   r   r   r   get_fields_from_path  s    	

r   c             C   s6   yt | d  W n  tk
r0   | dd } Y nX | S )z0 Discard trailing non-relation field if extant. r   Nr   r   )r   r   )rH   r   r   r   remove_trailing_data_field  s
    r   )N)N)NF)F);
__future__r   r   r   collectionsr   Zdjango.contrib.authr   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.db.models.constantsr   Zdjango.db.models.deletionr   Zdjango.db.models.sql.constantsr	   Zdjango.forms.utilsr
   Zdjango.urlsr   r   Zdjango.utilsr   r   r   Zdjango.utils.encodingr   r   r   Zdjango.utils.htmlr   Zdjango.utils.textr   Zdjango.utils.translationr   r'   r0   r<   rE   rI   rL   rh   ra   r   r   r   r   r   r   r   r   	Exceptionr   r   r   r   r   r   r   r   r   <module>   sJ   
4?


7
