U
    Æ½„b³/  ã                   @   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   |   dd¡  dd¡S )zK
    Double brackets in regex of url_path for escape string formatting
    Ú{z{{Ú}z}})Úreplace)Úurl_path© r   ú:/tmp/pip-unpacked-wheel-iohwuy7z/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 |||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 )úq
        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 overriddenNr.   r!   r   r   r   Úget_urlsD   s    zBaseRouter.get_urlsc                 C   s   t | dƒs|  ¡ | _| jS r$   )r(   r0   r%   r!   r   r   r   ÚurlsJ   s    

zBaseRouter.urls)N)	Ú__name__Ú
__module__Ú__qualname__r#   r,   r&   r0   Úpropertyr1   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Ú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)r9   ÚputÚpatchÚdeletez{basename}-detailTZInstancez.^{prefix}/{lookup}/{url_path}{trailing_slash}$c                    s   |rdnd| _ tƒ  ¡  d S )Nú/Ú )Útrailing_slashÚsuperr#   )r"   rF   ©Ú	__class__r   r   r#   ~   s    zSimpleRouter.__init__c                 C   s*   t |ddƒ}|dk	stdƒ‚|jjj ¡ S )r-   Ú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*   rJ   r   r   r   r&   ‚   s    z!SimpleRouter.get_default_basenamec                    sÚ   t tdd„ ˆjD ƒƒƒ‰ | ¡ }‡ fdd„|D ƒ}|rLd}t|d |¡ ƒ‚dd„ |D ƒ}dd„ |D ƒ}g }ˆjD ]b‰tˆtƒr ˆjr |‡‡fdd„|D ƒ7 }qrtˆtƒrÊˆjsÊ|‡‡fd	d„|D ƒ7 }qr| 	ˆ¡ qr|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 ¡ ‘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   )r2   ©rQ   Úaction)Úknown_actionsr   r   rS   ›   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   rT   r   r   r   rS   ¥   s      c                 S   s   g | ]}|j s|‘qS r   rW   rT   r   r   r   rS   ¦   s      c                    s   g | ]}ˆ  ˆ |¡‘qS r   ©Ú_get_dynamic_routerT   ©rR   r"   r   r   rS   «   s     c                    s   g | ]}ˆ  ˆ |¡‘qS r   rX   rT   rZ   r   r   rS   ­   s     )
r7   r   ÚroutesZget_extra_actionsr   ÚjoinrO   r   r   r'   )r"   r*   Zextra_actionsÚnot_allowedÚmsgZdetail_actionsZlist_actionsr[   r   )rV   rR   r"   r   Ú
get_routes�   s$    
ÿ
zSimpleRouter.get_routesc                 C   sL   |j  ¡ }| |j¡ t|jƒ}t|j d|¡|j	|j
 d|j¡|j|d�S )Nz
{url_path}z
{url_name}r=   )r   Úcopyr?   Úkwargsr   r   r   r   r   r   r   Úurl_namer   )r"   rR   rU   r   r   r   r   r   rY   ³   s    

ûzSimpleRouter._get_dynamic_routec                 C   s,   i }|  ¡ D ]\}}t||ƒr|||< q|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ÚmethodrU   r   r   r   Úget_method_mapÁ   s
    

zSimpleRouter.get_method_maprE   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_prefixrh   Úlookup_value)rK   Úformat)r"   r*   ri   Z
base_regexrf   rh   rj   r   r   r   Úget_lookup_regexÍ   s    ýzSimpleRouter.get_lookup_regexc              	   C   sÐ   g }| j D ]À\}}}|  |¡}|  |¡}|D ]œ}|  ||j¡}|sDq,|jj||| jd�}	|s||	dd… dkr|d|	dd…  }	|j 	¡ }
|
 
||jdœ¡ |j|f|
Ž}|jj|d�}| t|	||d�¡ q,q
|S )	zQ
        Use the registered viewsets to generate a list of URL patterns.
        )r)   ÚlookuprF   Né   z^/ú^)r+   r   ©r+   ©r   )r    rl   r_   re   r   r   rk   rF   r   r`   r?   r   Úas_viewr   r'   r   )r"   Úretr)   r*   r+   rm   r[   rR   r   Úregexr   Úviewr   r   r   r   r0   ä   s0    

ý

þzSimpleRouter.get_urls)T)rE   )r2   r3   r4   r   r   r[   r#   r&   r_   rY   re   rl   r0   Ú__classcell__r   r   rH   r   r6   Q   sP   þøüüöüÝ+$
r6   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   st   t ƒ }|jj}| j ¡ D ]R\}}|r0|d | }z t||||| d¡d�||< W q tk
rh   Y qY qX qt|ƒS )Nú:rk   )Úargsra   Úrequestrk   )	r   Zresolver_matchÚ	namespaceÚapi_root_dictrc   r	   r9   r   r   )r"   rz   ry   ra   rs   r{   Úkeyrb   r   r   r   r9     s     ûzAPIRootView.get)r2   r3   r4   Ú__doc__Z_ignore_model_permissionsZschemar|   r9   r   r   r   r   rw     s
   rw   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|  d¡| _nttjƒ| _tƒ j||Ž d S )NÚroot_renderers)Úpopr€   r7   r   ZDEFAULT_RENDERER_CLASSESrG   r#   )r"   ry   ra   rH   r   r   r#   ;  s    zDefaultRouter.__init__c                 C   sB   t ƒ }| jd j}| jD ]\}}}|j|d�||< q| jj|d�S )z+
        Return a basic root view.
        r   rp   )r|   )r   r[   r   r    rk   rw   rr   )r"   Úapi_urlsr|   Z	list_namer)   r*   r+   r   r   r   Úget_api_root_viewB  s
    zDefaultRouter.get_api_root_viewc                    sH   t ƒ  ¡ }| jr6| j|d�}td|| jd�}| |¡ | jrDt|ƒ}|S )z”
        Generate the list of URL patterns, including a default root view
        for the API, and appending `.json` style format suffixes.
        )r‚   z^$rq   )	rG   r0   Úinclude_root_viewrƒ   r   Úroot_view_namer'   Úinclude_format_suffixesr   )r"   r1   ru   Zroot_urlrH   r   r   r0   M  s    

zDefaultRouter.get_urls)N)r2   r3   r4   r~   r„   r†   r…   Zdefault_schema_renderersrw   r   ZAPISchemaViewr
   r#   rƒ   r0   rv   r   r   rH   r   r   .  s   
r   )!r~   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   r6   ZAPIViewrw   r   r   r   r   r   Ú<module>   s(   ! @