3
=^               	   @   s   d 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mZ dd
lmZ dd ZG dd deZG dd deejZG dd deejZG dd dejejeZG dd dejejej ej!ejeZ"dS )a  
ViewSets are essentially just a type of class based view, that doesn't provide
any method handlers, such as `get()`, `post()`, etc... but instead has actions,
such as `list()`, `retrieve()`, `create()`, etc...

Actions are only bound to methods at the point of instantiating the views.

    user_list = UserViewSet.as_view({'get': 'list'})
    user_detail = UserViewSet.as_view({'get': 'retrieve'})

Typically, rather than instantiate views from viewsets directly, you'll
register the viewset with a router and let the URL conf be determined
automatically.

    router = DefaultRouter()
    router.register(r'users', UserViewSet, 'user')
    urlpatterns = router.urls
    )unicode_literals)OrderedDict)update_wrapper)
getmembers)NoReverseMatch)classonlymethod)csrf_exempt)genericsmixinsviews)reversec             C   s
   t | dS )Nmapping)hasattr)attr r   F/tmp/pip-build-8app2_gc/djangorestframework/rest_framework/viewsets.py_is_extra_action!   s    r   c                   sJ   e Zd ZdZedddZ fddZdd Zed	d
 Z	dd Z
  ZS )ViewSetMixinad  
    This is the magic.

    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.

    For example, to create a concrete view binding the 'GET' and 'POST' methods
    to the 'list' and 'create' actions...

    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    Nc                s   d_ d_d_d_d_ s*tdxDD ]<}|jkrPtd|jf t|s0tdj|f q0W dkrdkrtdj  fdd	}t	|f d
 t	|j
f d |_|_ |_t|S )z
        Because of the way class based views create a closure around the
        instantiated view, we need to totally reimplement `.as_view`,
        and slightly modify the view function that is created and returned.
        NzwThe `actions` argument must be provided when calling `.as_view()` on a ViewSet. For example `.as_view({'get': 'list'})`zUYou tried to pass in the %s method name as a keyword argument to %s(). Don't do that.z#%s() received an invalid keyword %rnamesuffixzO%s() received both `name` and `suffix`, which are mutually exclusive arguments.c                s~   f } |_ x* j D ]\}}t||}t||| qW t|drZt|d rZ|j|_| |_||_||_	|j
| f||S )Ngethead)
action_mapitemsgetattrsetattrr   r   r   requestargskwargsdispatch)r   r   r   selfmethodactionhandler)actionscls
initkwargsr   r   view_   s    

z"ViewSetMixin.as_view.<locals>.view)updated)assigned)r   descriptionr   detailbasename	TypeErrorZhttp_method_names__name__r   r   r   r%   r&   r$   r   )r%   r$   r&   keyr'   r   )r$   r%   r&   r   as_view2   s0    	



zViewSetMixin.as_viewc                sD   t t| j|f||}|jj }|dkr2d| _n| jj|| _|S )z[
        Set the `.action` attribute on the view, depending on the request method.
        optionsmetadata)superr   initialize_requestr!   lowerr"   r   r   )r    r   r   r   r!   )	__class__r   r   r4      s    
zViewSetMixin.initialize_requestc             O   s,   d| j |f }|jd| j t|f||S )z>
        Reverse the action for the given `url_name`.
        z%s-%sr   )r,   
setdefaultr   r   )r    url_namer   r   r   r   r   reverse_action   s    zViewSetMixin.reverse_actionc             C   s   dd t | tD S )zP
        Get the methods that are marked as an extra ViewSet `@action`.
        c             S   s   g | ]\}}|qS r   r   ).0_r!   r   r   r   
<listcomp>   s    z2ViewSetMixin.get_extra_actions.<locals>.<listcomp>)r   r   )r%   r   r   r   get_extra_actions   s    zViewSetMixin.get_extra_actionsc                s   t  } jdkr|S  fdd j D }xf|D ]^}yDd j|jf }t| j j jd} j	f |j}|||j
 < W q0 tk
r   Y q0X q0W |S )z
        Build a map of {names: urls} for the extra actions.

        This method will noop if `detail` was not provided as a view initkwarg.
        Nc                s   g | ]}|j  j kr|qS r   )r+   )r:   r"   )r    r   r   r<      s    z9ViewSetMixin.get_extra_action_url_map.<locals>.<listcomp>z%s-%s)r   )r   r+   r=   r,   r8   r   r   r   r   r6   Zget_view_namer   )r    Zaction_urlsr$   r"   r8   urlr'   r   )r    r   get_extra_action_url_map   s    


z%ViewSetMixin.get_extra_action_url_map)N)r.   
__module____qualname____doc__r   r0   r4   r9   classmethodr=   r?   __classcell__r   r   )r6   r   r   %   s   R	r   c               @   s   e Zd ZdZdS )ViewSetzI
    The base ViewSet class does not provide any actions by default.
    N)r.   r@   rA   rB   r   r   r   r   rE      s   rE   c               @   s   e Zd ZdZdS )GenericViewSetz
    The GenericViewSet class does not provide any actions by default,
    but does include the base set of generic view behavior, such as
    the `get_object` and `get_queryset` methods.
    N)r.   r@   rA   rB   r   r   r   r   rF      s   rF   c               @   s   e Zd ZdZdS )ReadOnlyModelViewSetzL
    A viewset that provides default `list()` and `retrieve()` actions.
    N)r.   r@   rA   rB   r   r   r   r   rG      s   rG   c               @   s   e Zd ZdZdS )ModelViewSetz
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    N)r.   r@   rA   rB   r   r   r   r   rH      s   	rH   N)#rB   
__future__r   collectionsr   	functoolsr   inspectr   Zdjango.urlsr   Zdjango.utils.decoratorsr   Zdjango.views.decorators.csrfr   Zrest_frameworkr	   r
   r   Zrest_framework.reverser   r   objectr   ZAPIViewrE   ZGenericAPIViewrF   ZRetrieveModelMixinZListModelMixinrG   ZCreateModelMixinZUpdateModelMixinZDestroyModelMixinrH   r   r   r   r   <module>   s.    	