3
Ah`/                 @   s  d Z ddlZddlmZ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 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dd Zdd ZG dd d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
    N)OrderedDict
namedtuple)ImproperlyConfigured)NoReverseMatchre_path)views)Response)reverse)SchemaGenerator)
SchemaView)api_settings)format_suffix_patternsRouteurlmappingnamedetail
initkwargsDynamicRoutec             C   s   | j ddj ddS )zK
    Double brackets in regex of url_path for escape string formatting
    {z{{}z}})replace)url_path r   E/tmp/pip-build-9m32_hle/djangorestframework/rest_framework/routers.py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   flatten)   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__1   s    zBaseRouter.__init__Nc             C   s6   |d kr| j |}| jj|||f t| dr2| `d S )N_urls)get_default_basenamer    appendhasattrr#   )r!   prefixviewsetbasenamer   r   r   register4   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)r!   r(   r   r   r   r$   =   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+   )r!   r   r   r   get_urlsD   s    zBaseRouter.get_urlsc             C   s   t | ds| j | _| jS )Nr#   )r&   r,   r#   )r!   r   r   r   urlsJ   s    

zBaseRouter.urls)N)	__name__
__module____qualname__r"   r*   r$   r,   propertyr-   r   r   r   r   r   0   s
   
	r   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suffixZ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)r5   putpatchdeletez{basename}-detailTZInstancez.^{prefix}/{lookup}/{url_path}{trailing_slash}$c                s   |rdnd| _ t j  d S )N/ )trailing_slashsuperr"   )r!   r@   )	__class__r   r   r"   ~   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.)getattrAssertionErrormodelZ_metaZobject_namelower)r!   r(   rC   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.   )rJ   action)known_actionsr   r   rL      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   )rJ   rM   r   r   r   rL      s    c             S   s   g | ]}|j s|qS r   )r   )rJ   rM   r   r   r   rL      s    c                s   g | ]}j  |qS r   )_get_dynamic_route)rJ   rM   )rK   r!   r   r   rL      s    c                s   g | ]}j  |qS r   )rO   )rJ   rM   )rK   r!   r   r   rL      s    )
r3   r   routesZget_extra_actionsr   joinrH   r   r   r%   )r!   r(   Zextra_actionsnot_allowedmsgZdetail_actionsZlist_actionsrP   r   )rN   rK   r!   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   copyr9   kwargsr   r   r   r   r   r   r   url_namer   )r!   rK   rM   r   r   r   r   r   rO      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.
        )itemsr&   )r!   r(   Z
method_mapZbound_methodsmethodrM   r   r   r   get_method_map   s
    
zSimpleRouter.get_method_mapr?   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_prefixr]   lookup_value)rD   format)r!   r(   r^   Z
base_regexr[   r]   r_   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.
        )r'   lookupr@   N   z^/^)r)   r   )r)   )r   )r    ra   rT   rZ   r   r   r`   r@   r   rU   r9   r   as_viewr   r%   r   )r!   retr'   r(   r)   rb   rP   rK   r   regexr   viewr   r   r   r   r,      s,    




zSimpleRouter.get_urls)T)r?   )r.   r/   r0   r   r   rP   r"   r$   rT   rO   rZ   ra   r,   __classcell__r   r   )rB   r   r2   Q   sB   


$
r2   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:r`   )argsrV   requestr`   )	r   Zresolver_match	namespaceapi_root_dictrX   r	   r5   r   r   )r!   rm   rl   rV   rf   rn   keyrW   r   r   r   r5     s    zAPIRootView.get)r.   r/   r0   __doc__Z_ignore_model_permissionsZschemaro   r5   r   r   r   r   rj     s
   rj   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                s4   d|kr|j d| _nttj| _t j|| d S )Nroot_renderers)poprs   r3   r   ZDEFAULT_RENDERER_CLASSESrA   r"   )r!   rl   rV   )rB   r   r   r"   ;  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)   )ro   )r   rP   r   r    r`   rj   re   )r!   api_urlsro   Z	list_namer'   r(   r)   r   r   r   get_api_root_viewB  s
    zDefaultRouter.get_api_root_viewc                sH   t  j }| jr6| j|d}td|| jd}|j| | jrDt|}|S )z
        Generate the list of URL patterns, including a default root view
        for the API, and appending `.json` style format suffixes.
        )ru   z^$)r   )	rA   r,   include_root_viewrv   r   root_view_namer%   include_format_suffixesr   )r!   r-   rh   Zroot_url)rB   r   r   r,   M  s    

zDefaultRouter.get_urls)N)r.   r/   r0   rq   rw   ry   rx   Zdefault_schema_renderersrj   r   ZAPISchemaViewr
   r"   rv   r,   ri   r   r   )rB   r   rr   .  s   
rr   )!rq   r   collectionsr   r   Zdjango.core.exceptionsr   Zdjango.urlsr   r   Zrest_frameworkr   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   r   r   r   r2   ZAPIViewrj   rr   r   r   r   r   <module>   s(   ! @