a
    Cgc6                     @   s   d Z ddl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 ddlmZ edg dZedg d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)
namedtuple)ImproperlyConfigured)NoReverseMatchpathre_path)views)Response)reverse)SchemaGenerator)
SchemaView)api_settings)format_suffix_patternsRouteurlmappingnamedetail
initkwargsDynamicRouter   r   r   r   c                 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   U/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/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                   @   sB   e Zd Zdd ZdddZ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   sZ   |d u r|  |}| |r6d| d| d}t|| j|||f t| drV| `d S )NzRouter with basename "zG" is already registered. Please provide a unique basename for viewset ""_urls)get_default_basenameis_already_registeredr   r#   appendhasattrr(   )r%   prefixviewsetbasenamemsgr   r   r   register4   s    


zBaseRouter.registerc                    s   t  fdd| jD S )z;
        Check if `basename` is already registered
        c                 3   s   | ]\}}}| kV  qd S r"   r   ).0_prefixZ_viewsetr/   new_basenamer   r   	<genexpr>G       z3BaseRouter.is_already_registered.<locals>.<genexpr>)anyr#   )r%   r5   r   r4   r   r*   C   s    z BaseRouter.is_already_registeredc                 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)   I   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_urlsP   s    zBaseRouter.get_urlsc                 C   s   t | ds|  | _| jS )Nr(   )r,   r<   r(   r$   r   r   r   urlsV   s    

zBaseRouter.urls)N)
__name__
__module____qualname__r&   r1   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suffixListr   z%^{prefix}/{url_path}{trailing_slash}$z{basename}-{url_name}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| _ || _|r,d| _d| _t| _npd| _d| _t| _g }| jD ]L}|j}|d dkrj|d	d  }|d
 dkr|d d
 }|	|j
|d qH|| _t   d S )N/ z5(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})z[^/.]+z2<{lookup_value}:{lookup_prefix}{lookup_url_kwarg}>strr   ^   $)r   )trailing_slash
_use_regex_base_pattern_default_value_patternr   	_url_confr   routesr   r+   _replacesuperr&   )r%   rV   Zuse_regex_pathZ_routesrouteZ	url_param	__class__r   r   r&      s&    
zSimpleRouter.__init__c                 C   s*   t |dd}|dusJ d|jjj S )r9   querysetNz`basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.)getattrmodelZ_metaZobject_namelower)r%   r.   ra   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)r2   r^   r   r   r   
<listcomp>   r7   z+SimpleRouter.get_routes.<locals>.<listcomp>c                    s   g | ]}|j  v r|j qS r   )r>   r2   action)known_actionsr   r   rg      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   rh   r   r   r   rg      r7   c                 S   s   g | ]}|j s|qS r   rk   rh   r   r   r   rg      r7   c                    s   g | ]}  |qS r   _get_dynamic_routerh   r^   r%   r   r   rg      r7   c                    s   g | ]}  |qS r   rl   rh   rn   r   r   rg      r7   )
rC   r    r[   Zget_extra_actionsr   joinre   r   r   r+   )r%   r.   Zextra_actionsnot_allowedr0   Zdetail_actionsZlist_actionsr[   r   )rj   r^   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   copyrJ   kwargsr   r   r   r   r   r   r   url_namer   )r%   r^   ri   r   r   r   r   r   rm      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methodri   r   r   r   get_method_map   s
    

zSimpleRouter.get_method_maprP   c                 C   sZ   t |dd}t |ddp|}d}| js2t |dd}|du rHt |d| j}| j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
        lookup_fieldpklookup_url_kwargNZlookup_value_converterZlookup_value_regex)lookup_prefixrz   lookup_value)rb   rW   rY   rX   format)r%   r.   r{   rx   rz   r|   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| jt	u r|	d dkr|	dd }	n |	dd dkrd|	dd  }	|j
 }
|
||jd	 |j|fi |
}|jj|d
}|| j|	||d q,q
|S )zQ
        Use the registered viewsets to generate a list of URL patterns.
        )r-   lookuprV   r   rO   rS   N   z^/rR   )r/   r   r/   r   )r#   r~   rq   rw   r   r   r}   rV   rZ   r   r   rr   rJ   r   as_viewr   r+   )r%   retr-   r.   r/   r   r[   r^   r   regexr   viewr   r   r   r   r<   
  s8    




zSimpleRouter.get_urls)TT)rP   )r>   r?   r@   r   r   r[   r&   r)   rq   rm   rw   r~   r<   __classcell__r   r   r_   r   rB   ]   sP   +$
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   sp   i }|j j}| j D ]P\}}|r.|d | }z t|||||dd||< W q tyd   Y qY q0 qt|S )N:r}   )argsrs   requestr}   )Zresolver_match	namespaceapi_root_dictru   r	   rE   r   r   )r%   r   r   rs   r   r   keyrt   r   r   r   rE   B  s     zAPIRootView.get)r>   r?   r@   __doc__Z_ignore_model_permissionsZschemar   rE   r   r   r   r   r   :  s
   r   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|v r| d| _nttj| _t j|i | d S )Nroot_renderers)popr   rC   r   ZDEFAULT_RENDERER_CLASSESr]   r&   )r%   r   rs   r_   r   r   r&   e  s    zDefaultRouter.__init__c                 C   s@   i }| j d j}| jD ]\}}}|j|d||< q| jj|dS )z+
        Return a basic root view.
        r   r   )r   )r[   r   r#   r}   r   r   )r%   api_urlsr   Z	list_namer-   r.   r/   r   r   r   get_api_root_viewl  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   rP   r   )	r]   r<   include_root_viewr   r   root_view_namer+   include_format_suffixesr   )r%   r=   r   Zroot_urlr_   r   r   r<   w  s    

zDefaultRouter.get_urls)N)r>   r?   r@   r   r   r   r   Zdefault_schema_renderersr   r   ZAPISchemaViewr
   r&   r   r<   r   r   r   r_   r   r   X  s   
r   )!r   r   collectionsr   Zdjango.core.exceptionsr   Zdjango.urlsr   r   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!   rB   ZAPIViewr   r   r   r   r   r   <module>   s(   - ^