Beispiel #1
0
class MisagoApiRouter(DefaultRouter):
    routes = [
        # List route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'list',
                  'post': 'create'
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(url=r'^{prefix}/{methodnamehyphen}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Detail route.
        Route(url=r'^{prefix}/{lookup}{trailing_slash}$',
              mapping={
                  'get': 'retrieve',
                  'put': 'update',
                  'patch': 'partial_update',
                  'delete': 'destroy'
              },
              name='{basename}-detail',
              initkwargs={'suffix': 'Instance'}),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodnamehyphen}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
    ]
Beispiel #2
0
class MetricRouter(SimpleRouter):
    """
    A router for Metric APIs
    """
    routes = [
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'list',
                  'post': 'create',
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        Route(
            url=r'^{prefix}/{lookup}{trailing_slash}$',
            mapping={
                #                'get': 'retrieve',
                #                'patch': 'partial_update',
                'delete': 'destroy'
            },
            name='{basename}-detail',
            initkwargs={'suffix': 'Instance'}),
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
    ]
Beispiel #3
0
class CreateDeleteRouter(SimpleRouter):
    """
    A router for create / delete APIs
    """
    routes = [
        # Create route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={'post': 'create'},
              name='{basename}-link',
              initkwargs={'suffix': 'Create'}),
        # Dynamically generated list routes.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Delete route
        Route(url=r'^{prefix}/{lookup}{trailing_slash}$',
              mapping={'delete': 'destroy'},
              name='{basename}-unlink',
              initkwargs={'suffix': 'Instance'}),
        # Dynamically generated detail routes.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
    ]
Beispiel #4
0
class SearchRouter(DefaultRouter):
    routes = [
        Route(
            url=r'^{prefix}$',
            mapping={'get': 'list'},
            name='{basename}-list',
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}$',
            mapping={'get': 'retrieve'},
            name='{basename}-detail',
            initkwargs={'suffix': 'Detail'}
        ),
        DynamicDetailRoute(
            url=r'^{prefix}/{methodname}/(?P<query_term>[^/.]+)/$',
            name='{basename}-{methodname}',
            initkwargs={}
        ),
        DynamicListRoute(
            url=r'^{prefix}/{methodname}/$',
            name='{basename}-{methodname}',
            initkwargs={}
        )
    ]
Beispiel #5
0
class EndpointRouterMixin:
    endpoint_routes = [
        # List route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'list',
                  'post': 'create'
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Edit route.
        Route(url=r'^{prefix}/{lookup}/edit{trailing_slash}$',
              mapping={
                  'get': 'retrieve',
                  'put': 'update',
                  'patch': 'partial_update',
                  'delete': 'destroy'
              },
              name='{basename}-detail',
              initkwargs={'suffix': 'Instance'}),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
        # Endpoint route.
        Route(url=r'^{prefix}/{lookup}{trailing_slash}$',
              mapping={
                  'get': 'endpoint_get',
                  'put': 'endpoint_put',
                  'post': 'endpoint_post',
                  'patch': 'endpoint_patch',
                  'delete': 'endpoint_delete'
              },
              name='{basename}-endpoint',
              initkwargs={'suffix': 'Instance'}),
    ]

    def __init__(self, *args, **kwargs):
        # Save original routes so we can switch them later on without modifying logic too much.
        self._routes = self.routes
        super().__init__(*args, **kwargs)

    def get_routes(self, viewset):
        if getattr(viewset, 'as_endpoint', False):
            self.routes = self.endpoint_routes
        else:
            self.routes = self._routes
        return super().get_routes(viewset)
Beispiel #6
0
class JSONSchemaRouter(SimpleRouter):
    routes = [
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='schema-{basename}-{methodnamehyphen}',
                         initkwargs={}),
    ]

    def get_default_base_name(self, viewset):
        model_cls = viewset.schema_for.Meta.model
        return '{}-{}'.format(viewset.app_name,
                              model_cls._meta.object_name.lower())
Beispiel #7
0
class CreateRouter(SimpleRouter):
    """
    A router for create APIs
    """
    routes = [
        # Create route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={'post': 'create'},
              name='{basename}-create',
              initkwargs={'suffix': 'Create'}),
        # Dynamically generated list routes.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
    ]
Beispiel #8
0
class SingleRecordRouter(SimpleRouter):
    routes = [
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'post': 'create',
                  'get': 'retrieve',
                  'put': 'update',
                  'patch': 'partial_update',
                  'delete': 'destroy'
              },
              name='{basename}-detail',
              initkwargs={'suffix': 'Instance'}),
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
    ]
Beispiel #9
0
class SimpleRouter(BaseRouter):
    """
    Custom Router that maps viewset methods to its methodnamehyphen variant.

    For example:
        Method do_some_stuff will be translated to url resource/do-some-stuff
    """
    routes = [
        # List route.
        Route(
            url=r'^{prefix}{trailing_slash}$',
            mapping={
                'get': 'list',
                'post': 'create'
            },
            name='{basename}-list',
            initkwargs={'suffix': 'List'}
        ),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(
            url=r'^{prefix}/{methodnamehyphen}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
        # Detail route.
        Route(
            url=r'^{prefix}/{lookup}{trailing_slash}$',
            mapping={
                'get': 'retrieve',
                'put': 'update',
                'patch': 'partial_update',
                'delete': 'destroy'
            },
            name='{basename}-detail',
            initkwargs={'suffix': 'Instance'}
        ),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodnamehyphen}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
    ]
class MisagoApiRouter(DefaultRouter):
    include_root_view = False
    include_format_suffixes = False

    routes = [
        # List route.
        Route(
            url=r"^{prefix}{trailing_slash}$",
            mapping={
                "get": "list",
                "post": "create"
            },
            name="{basename}-list",
            initkwargs={"suffix": "List"},
        ),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(
            url=r"^{prefix}/{methodnamehyphen}{trailing_slash}$",
            name="{basename}-{methodnamehyphen}",
            initkwargs={},
        ),
        # Detail route.
        Route(
            url=r"^{prefix}/{lookup}{trailing_slash}$",
            mapping={
                "get": "retrieve",
                "put": "update",
                "patch": "partial_update",
                "delete": "destroy",
            },
            name="{basename}-detail",
            initkwargs={"suffix": "Instance"},
        ),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r"^{prefix}/{lookup}/{methodnamehyphen}{trailing_slash}$",
            name="{basename}-{methodnamehyphen}",
            initkwargs={},
        ),
    ]
Beispiel #11
0
class TusAPIRouter(SimpleRouter):
    routes = [
        # List route.
        get_list_route(),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(
            url=r'^{prefix}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
        # Detail route.
        get_detail_route(),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
    ]
Beispiel #12
0
class PostHackedRouter(DefaultRouter):
    """ hack post method for detail api, make post method avaliable for partial_update action """

    routes = [
        # List route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'list',
                  'post': 'create'
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Detail route.
        Route(
            url=r'^{prefix}/{lookup}{trailing_slash}$',
            mapping={
                'get': 'retrieve',
                'put': 'update',
                'patch': 'partial_update',
                'post':
                'partial_update',  # some browser cannot patch data, use post instead
                'delete': 'destroy'
            },
            name='{basename}-detail',
            initkwargs={'suffix': 'Instance'}),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
    ]
Beispiel #13
0
class Router(DefaultRouter):
    routes = [
        # List route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'list',
                  'post': 'create'
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{methodname}/{lookup}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
        # Detail route.
        Route(url=r'^{prefix}/{lookup}{trailing_slash}$',
              mapping={
                  'get': 'retrieve',
                  'put': 'update',
                  'patch': 'partial_update',
                  'delete': 'destroy'
              },
              name='{basename}-detail',
              initkwargs={'suffix': 'Instance'}),
    ]

    def produce_urls(self):
        ret = []
        base_regex = '(?P<{lookup_field}>[^/]+)'

        for prefix, viewset, basename in self.registry:
            lookup = self.get_lookup_regex(viewset)
            routes = self.get_routes(viewset)

            for route in routes:

                # Only actions which actually exist on the viewset will be bound
                mapping = self.get_method_map(viewset, route.mapping)
                if not mapping:
                    continue

                # Build the url pattern
                regex = route.url.format(prefix=prefix,
                                         lookup=lookup,
                                         trailing_slash=self.trailing_slash)

                if not route.initkwargs:
                    function_name = mapping.get('get', None) or mapping.get(
                        'post', None)
                    handler = getattr(viewset, function_name)
                    if hasattr(handler, 'lookup'):
                        lookup_list = []
                        for lp in handler.lookup:
                            lookup_list.append(
                                base_regex.format(lookup_field=lp))
                        custom_lookup = '/'.join(lookup_list)
                        regex = route.url.format(
                            prefix=prefix,
                            lookup=custom_lookup,
                            trailing_slash=self.trailing_slash
                            if custom_lookup else '')
                view = viewset.as_view(mapping, **route.initkwargs)
                name = route.name.format(basename=basename)
                ret.append(url(regex, view, name=name))
        return ret

    def get_urls(self):
        """
        Generate the list of URL patterns, including a default root view
        for the API, and appending `.json` style format suffixes.
        """
        urls = []

        if self.include_root_view:
            root_url = url(r'^api_root$',
                           self.get_api_root_view(),
                           name=self.root_view_name)
            urls.append(root_url)

        #default_urls = super(DefaultRouter, self).get_urls()
        default_urls = self.produce_urls()
        urls.extend(default_urls)

        if self.include_format_suffixes:
            urls = format_suffix_patterns(urls)

        return urls
Beispiel #14
0
class APIRouter(BaseRouter):
    routes = [
        # List route.
        Route(url=r'^{prefix}{trailing_slash}$',
              mapping={
                  'get': 'get',
                  'post': 'post',
                  'options': 'post'
              },
              name='{basename}-list',
              initkwargs={'suffix': 'List'}),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(url=r'^{prefix}/{methodname}{trailing_slash}$',
                         name='{basename}-{methodnamehyphen}',
                         initkwargs={}),
        # Detail route.
        Route(url=r'^{prefix}/{lookup}{trailing_slash}$',
              mapping={
                  'get': 'retrieve',
                  'put': 'update',
                  'patch': 'partial_update',
                  'delete': 'destroy'
              },
              name='{basename}-detail',
              initkwargs={'suffix': 'Instance'}),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}),
    ]

    def __init__(self, trailing_slash=True):
        self.trailing_slash = trailing_slash and '/' or ''
        super(APIRouter, self).__init__()

    def get_default_base_name(self, viewset):
        """
        If `base_name` is not specified, attempt to automatically determine
        it from the viewset.
        """
        queryset = getattr(viewset, 'queryset', None)

        assert queryset is not None, '`base_name` argument not specified, and could ' \
                                     'not automatically determine the name from the viewset, as ' \
                                     'it does not have a `.queryset` attribute.'

        return queryset.model._meta.object_name.lower()

    def get_routes(self, viewset):
        """
        Augment `self.routes` with any dynamically generated routes.

        Returns a list of the Route namedtuple.
        """

        known_actions = flatten([
            route.mapping.values() for route in self.routes
            if isinstance(route, Route)
        ])

        # Determine any `@detail_route` or `@list_route` decorated methods on the viewset
        detail_routes = []
        list_routes = []
        for methodname in dir(viewset):
            attr = getattr(viewset, methodname)
            httpmethods = getattr(attr, 'bind_to_methods', None)
            detail = getattr(attr, 'detail', True)
            if httpmethods:
                if methodname in known_actions:
                    raise ImproperlyConfigured(
                        'Cannot use @detail_route or @list_route '
                        'decorators on method "%s" '
                        'as it is an existing route' % methodname)
                httpmethods = [method.lower() for method in httpmethods]
                if detail:
                    detail_routes.append((httpmethods, methodname))
                else:
                    list_routes.append((httpmethods, methodname))

        def _get_dynamic_routes(route, dynamic_routes):
            ret = []
            for httpmethods, methodname in dynamic_routes:
                method_kwargs = getattr(viewset, methodname).kwargs
                initkwargs = route.initkwargs.copy()
                initkwargs.update(method_kwargs)
                url_path = initkwargs.pop("url_path", None) or methodname
                ret.append(
                    Route(
                        url=replace_methodname(route.url, url_path),
                        mapping={
                            httpmethod: methodname
                            for httpmethod in httpmethods
                        },
                        name=replace_methodname(route.name, url_path),
                        initkwargs=initkwargs,
                    ))

            return ret

        ret = []
        for route in self.routes:
            if isinstance(route, DynamicDetailRoute):
                # Dynamic detail routes (@detail_route decorator)
                ret += _get_dynamic_routes(route, detail_routes)
            elif isinstance(route, DynamicListRoute):
                # Dynamic list routes (@list_route decorator)
                ret += _get_dynamic_routes(route, list_routes)
            else:
                # Standard route
                ret.append(route)

        return ret

    def get_method_map(self, viewset, method_map):
        """
        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.
        """
        bound_methods = {}
        for method, action in method_map.items():
            if hasattr(viewset, action):
                bound_methods[method] = action
        return bound_methods

    def get_lookup_regex(self, viewset, lookup_prefix=''):
        """
        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
        """
        base_regex = '(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})'
        # Use `pk` as default field, unset set.  Default regex should not
        # consume `.json` style suffixes and should break at '/' boundaries.
        lookup_field = getattr(viewset, 'lookup_field', 'pk')
        lookup_url_kwarg = getattr(viewset, 'lookup_url_kwarg',
                                   None) or lookup_field
        lookup_value = getattr(viewset, 'lookup_value_regex', '[^/.]+')
        return base_regex.format(lookup_prefix=lookup_prefix,
                                 lookup_url_kwarg=lookup_url_kwarg,
                                 lookup_value=lookup_value)

    def get_urls(self):
        """
        Use the registered viewsets to generate a list of URL patterns.
        """
        ret = []

        for prefix, viewset, basename in self.registry:
            lookup = self.get_lookup_regex(viewset)
            routes = self.get_routes(viewset)

            for route in routes:

                # Only actions which actually exist on the viewset will be bound
                mapping = self.get_method_map(viewset, route.mapping)
                if not mapping:
                    continue

                # Build the url pattern
                regex = route.url.format(prefix=prefix,
                                         lookup=lookup,
                                         trailing_slash=self.trailing_slash)
                view = viewset.as_view(mapping, **route.initkwargs)
                name = route.name.format(basename=basename)
                ret.append(url(regex, view, name=name))

        return ret
Beispiel #15
0
class InterfacePushRouter(DefaultRouter):
    """
    A router for interface push APIs 
    """
    routes = [
        # List route.
        Route(
            url=r'^{prefix}{trailing_slash}$',
            mapping={
                'get': 'list',
                'post': 'create'
            },
            name='{basename}-list',
            initkwargs={'suffix': 'List'}
        ),
        # Dynamically generated list routes.
        # Generated using @list_route decorator
        # on methods of the viewset.
        DynamicListRoute(
            url=r'^{prefix}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
        # Detail route.
        #Route(
        #    url=r'^{prefix}/{lookup}{trailing_slash}$',
        #    mapping={
        #        'get': 'retrieve',
        #        'put': 'update',
        #        'patch': 'partial_update',
        #        'delete': 'destroy'
        #    },
        #    name='{basename}-detail',
        #    initkwargs={'suffix': 'Instance'}
        #),
        Route(
            url=r'^{prefix}/{lookup}/$',
            mapping={
                'post': 'push',
                'get': 'pull'
            },
            name='{basename}-table-detail',
            initkwargs={'suffix': 'Instance'}
        ),
        # Dynamically generated detail routes.
        # Generated using @detail_route decorator on methods of the viewset.
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        ),
    ]

    def get_api_root_view(self):
        """
        Return a view to use as the API root.
        """
        api_root_dict = OrderedDict()
        list_name = self.routes[0].name
        interface_entrys = InterfaceEntry.objects.all()
        for prefix, viewset, basename in self.registry:
            api_root_dict[prefix] = list_name.format(basename=basename)

        class APIRoot(views.APIView):
            _ignore_model_permissions = True

            def get(self, request, *args, **kwargs):
                ret = OrderedDict()
                namespace = get_resolver_match(request).namespace
                for key, url_name in api_root_dict.items():
                    if namespace:
                        url_name = namespace + ':' + url_name
                    try:
                        ret[key] = reverse(
                            url_name,
                            request=request,
                            format=kwargs.get('format', None)
                        )
                        
                    except NoReverseMatch:
                        # Don't bail out if eg. no list routes exist, only detail routes.
                        continue

                    for entry in interface_entrys:
                        absolute_url = '/' + key + '/' + entry.tname + '/'
                        url = request.build_absolute_uri(absolute_url)
                        ret['interface-%s' % entry.tname] = url

                return Response(ret)

        return APIRoot.as_view()