3
=^6                 @   sz  d Z ddlmZ ddlZddl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 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 ddlmZ ddlmZ ddl m!Z! eddddddgZ"edddddgZ#G dd de$Z%G dd de$Z&dd Z'dd Z(G d d! d!eZ)G d"d# d#ej*e)Z+G d$d% d%e+Z,G d&d' d'ej-Z.G d(d) d)e,Z/dS )*a  
Routers provide a convenient and consistent way of automatically
determining the URL conf for your API.

They are used by simply instantiating a Router class, and then registering
all the required ViewSets with that router.

For example, you might have a `urls.py` that looks something like this:

    router = routers.DefaultRouter()
    router.register('users', UserViewSet, 'user')
    router.register('accounts', AccountViewSet, 'account')

    urlpatterns = router.urls
    )unicode_literalsN)OrderedDict
namedtuple)url)ImproperlyConfigured)NoReverseMatch)six)RenameMethodsBase)RemovedInDRF310WarningRemovedInDRF311Warningviews)Response)reverse)SchemaGenerator)
SchemaView)api_settings)format_suffix_patternsRouter   mappingnamedetail
initkwargsDynamicRoutec               @   s   e Zd Zdd ZdS )DynamicDetailRoutec             C   s   t jdtdd t||d|S )Nz`DynamicDetailRoute` is deprecated and will be removed in 3.10 in favor of `DynamicRoute`, which accepts a `detail` boolean. Use `DynamicRoute(url, name, True, initkwargs)` instead.   )
stacklevelT)warningswarnr
   r   )clsr   r   r    r   E/tmp/pip-build-8app2_gc/djangorestframework/rest_framework/routers.py__new__+   s    
zDynamicDetailRoute.__new__N)__name__
__module____qualname__r!   r   r   r   r    r   *   s   r   c               @   s   e Zd Zdd ZdS )DynamicListRoutec             C   s   t jdtdd t||d|S )Nz`DynamicListRoute` is deprecated and will be removed in 3.10 in favor of `DynamicRoute`, which accepts a `detail` boolean. Use `DynamicRoute(url, name, False, initkwargs)` instead.r   )r   F)r   r   r
   r   )r   r   r   r   r   r   r    r!   6   s    
zDynamicListRoute.__new__N)r"   r#   r$   r!   r   r   r   r    r%   5   s   r%   c             C   s$   dod| kr | j ddj dd} | S )zK
    Double brackets in regex of url_path for escape string formatting
    {}z{{z}})replace)url_pathr   r   r    escape_curly_brackets@   s    r*   c             C   s
   t j|  S )zX
    Takes an iterable of iterables, returns a single iterable containing all items
    )	itertoolschain)Zlist_of_listsr   r   r    flattenI   s    r-   c               @   s   e Zd ZddeffZdS )RenameRouterMethodsZget_default_base_nameget_default_basenameN)r"   r#   r$   r   Zrenamed_methodsr   r   r   r    r.   P   s   r.   c               @   s:   e Zd Zdd ZdddZdd Zdd	 Zed
d ZdS )
BaseRouterc             C   s
   g | _ d S )N)registry)selfr   r   r    __init__W   s    zBaseRouter.__init__Nc             C   sn   |d k	rd}t j|td |o | s,td|d kr8|}|d krJ| j|}| jj|||f t| drj| `d S )NzGThe `base_name` argument is pending deprecation in favor of `basename`.r   z=Do not provide both the `basename` and `base_name` arguments._urls)	r   r   r   AssertionErrorr/   r1   appendhasattrr4   )r2   prefixviewsetbasename	base_namemsgr   r   r    registerZ   s    

zBaseRouter.registerc             C   s   t ddS )zq
        If `basename` is not specified, attempt to automatically determine
        it from the viewset.
        z'get_default_basename must be overriddenN)NotImplementedError)r2   r9   r   r   r    r/   m   s    zBaseRouter.get_default_basenamec             C   s   t ddS )zO
        Return a list of URL patterns, given the registered viewsets.
        zget_urls must be overriddenN)r>   )r2   r   r   r    get_urlst   s    zBaseRouter.get_urlsc             C   s   t | ds| j | _| jS )Nr4   )r7   r?   r4   )r2   r   r   r    urlsz   s    

zBaseRouter.urls)NN)	r"   r#   r$   r3   r=   r/   r?   propertyr@   r   r   r   r    r0   V   s
   
r0   c            	       s   e Zd Zeddddddddid	ed
ddi deddddddddddid	edddi dgZd& fdd	Zdd Zdd Zdd Z	dd  Z
d'd"d#Zd$d% Z  ZS )(SimpleRouterz^{prefix}{trailing_slash}$listcreate)getpostz{basename}-listFsuffixList)r   r   r   r   r   z%^{prefix}/{url_path}{trailing_slash}$z{basename}-{url_name})r   r   r   r   z#^{prefix}/{lookup}{trailing_slash}$retrieveupdateZpartial_updatedestroy)rE   putpatchdeletez{basename}-detailTZInstancez.^{prefix}/{lookup}/{url_path}{trailing_slash}$c                s    |rdnd| _ tt| j  d S )N/ )trailing_slashsuperrB   r3   )r2   rQ   )	__class__r   r    r3      s    zSimpleRouter.__init__c             C   s*   t |dd}|dk	std|jjjj S )zq
        If `basename` is not specified, attempt to automatically determine
        it from the viewset.
        querysetNz`basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.)getattrr5   modelZ_metaZobject_namelower)r2   r9   rT   r   r   r    r/      s    z!SimpleRouter.get_default_basenamec                s   t tdd jD  |j } fdd|D }|rLd}t|dj| dd |D }dd |D }g }xnjD ]dttrjr|fdd|D 7 }qtttrΈj r|fd	d|D 7 }qt|j	 qtW |S )
z
        Augment `self.routes` with any dynamically generated routes.

        Returns a list of the Route namedtuple.
        c             S   s    g | ]}t |tr|jj qS r   )
isinstancer   r   values).0router   r   r    
<listcomp>   s    z+SimpleRouter.get_routes.<locals>.<listcomp>c                s   g | ]}|j  kr|j qS r   )r"   )rZ   action)known_actionsr   r    r\      s    zZCannot use the @action decorator on the following methods, as they are existing routes: %sz, c             S   s   g | ]}|j r|qS r   )r   )rZ   r]   r   r   r    r\      s    c             S   s   g | ]}|j s|qS r   )r   )rZ   r]   r   r   r    r\      s    c                s   g | ]}j  |qS r   )_get_dynamic_route)rZ   r]   )r[   r2   r   r    r\      s    c                s   g | ]}j  |qS r   )r_   )rZ   r]   )r[   r2   r   r    r\      s    )
rC   r-   routesZget_extra_actionsr   joinrX   r   r   r6   )r2   r9   Zextra_actionsnot_allowedr<   Zdetail_actionsZlist_actionsr`   r   )r^   r[   r2   r    
get_routes   s     zSimpleRouter.get_routesc             C   sL   |j j }|j|j t|j}t|jjd||j	|j
jd|j|j|dS )Nz
{url_path}z
{url_name})r   r   r   r   r   )r   copyrJ   kwargsr*   r)   r   r   r(   r   r   url_namer   )r2   r[   r]   r   r)   r   r   r    r_      s    

zSimpleRouter._get_dynamic_routec             C   s0   i }x&|j  D ]\}}t||r|||< qW |S )z
        Given a viewset, and a mapping of http methods to actions,
        return a new mapping which only includes any mappings that
        are actually implemented by the viewset.
        )itemsr7   )r2   r9   Z
method_mapZbound_methodsmethodr]   r   r   r    get_method_map   s
    
zSimpleRouter.get_method_maprP   c             C   s<   d}t |dd}t |ddp|}t |dd}|j|||dS )	a  
        Given a viewset, return the portion of URL regex that is used
        to match against a single instance.

        Note that lookup_prefix is not used directly inside REST rest_framework
        itself, but is required in order to nicely support nested router
        implementations, such as drf-nested-routers.

        https://github.com/alanjds/drf-nested-routers
        z5(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})lookup_fieldpklookup_url_kwargNZlookup_value_regexz[^/.]+)lookup_prefixrl   lookup_value)rU   format)r2   r9   rm   Z
base_regexrj   rl   rn   r   r   r    get_lookup_regex   s    zSimpleRouter.get_lookup_regexc             C   s   g }x| j D ]\}}}| j|}| j|}x|D ]}| j||j}|sHq0|jj||| jd}	| r|	dd dkrd|	dd  }	|jj	 }
|
j
||jd |j|f|
}|jj|d}|jt|	||d q0W qW |S )	zQ
        Use the registered viewsets to generate a list of URL patterns.
        )r8   lookuprQ   Nr   z^/^)r:   r   )r:   )r   )r1   rp   rc   ri   r   r   ro   rQ   r   rd   rJ   r   as_viewr   r6   )r2   retr8   r9   r:   rq   r`   r[   r   regexr   viewr   r   r   r    r?     s,    




zSimpleRouter.get_urls)T)rP   )r"   r#   r$   r   r   r`   r3   r/   rc   r_   ri   rp   r?   __classcell__r   r   )rS   r    rB      sB   


$
rB   c               @   s$   e Zd ZdZdZdZdZdd ZdS )APIRootViewz7
    The default basic root view for DefaultRouter
    TNc             O   sx   t  }|jj}x`| jj D ]R\}}|r2|d | }y"t|||||jdd d||< W q tk
rj   wY qX qW t|S )N:ro   )argsre   requestro   )	r   Zresolver_match	namespaceapi_root_dictrg   r   rE   r   r   )r2   r{   rz   re   rt   r|   keyrf   r   r   r    rE   H  s    zAPIRootView.get)r"   r#   r$   __doc__Z_ignore_model_permissionsZschemar}   rE   r   r   r   r    rx   @  s
   rx   c                   sR   e Zd ZdZdZdZdZdZeZe	Z
eZ fddZdddZ fd	d
Z  ZS )DefaultRouterz
    The default router extends the SimpleRouter, but also adds in a default
    API root view, and adds format suffix patterns to the URLs.
    Tzapi-rootNc                s8   d|kr|j d| _nttj| _tt| j|| d S )Nroot_renderers)popr   rC   r   ZDEFAULT_RENDERER_CLASSESrR   r   r3   )r2   rz   re   )rS   r   r    r3   k  s    zDefaultRouter.__init__c             C   sF   t  }| jd j}x$| jD ]\}}}|j|d||< qW | jj|dS )z+
        Return a basic root view.
        r   )r:   )r}   )r   r`   r   r1   ro   rx   rs   )r2   api_urlsr}   Z	list_namer8   r9   r:   r   r   r    get_api_root_viewr  s
    zDefaultRouter.get_api_root_viewc                sL   t t| j }| jr:| j|d}td|| jd}|j| | jrHt	|}|S )z
        Generate the list of URL patterns, including a default root view
        for the API, and appending `.json` style format suffixes.
        )r   z^$)r   )
rR   r   r?   include_root_viewr   r   root_view_namer6   include_format_suffixesr   )r2   r@   rv   Zroot_url)rS   r   r    r?   }  s    
zDefaultRouter.get_urls)N)r"   r#   r$   r   r   r   r   Zdefault_schema_renderersrx   r   ZAPISchemaViewr   r3   r   r?   rw   r   r   )rS   r    r   ^  s   
r   )0r   
__future__r   r+   r   collectionsr   r   Zdjango.conf.urlsr   Zdjango.core.exceptionsr   Zdjango.urlsr   Zdjango.utilsr   Zdjango.utils.deprecationr	   Zrest_frameworkr
   r   r   Zrest_framework.responser   Zrest_framework.reverser   Zrest_framework.schemasr   Zrest_framework.schemas.viewsr   Zrest_framework.settingsr   Zrest_framework.urlpatternsr   r   r   objectr   r%   r*   r-   r.   with_metaclassr0   rB   ZAPIViewrx   r   r   r   r   r    <module>   s8   	+ @