Fleshing out viewsets/routers · encode/django-rest-framework@c785628 (original) (raw)
1
``
`-
Not properly implemented yet, just the basic idea
`
2
``
-
3
``
-
4
``
`-
class BaseRouter(object):
`
5
``
`-
def init(self):
`
6
``
`-
self.resources = []
`
7
``
-
8
``
`-
def register(self, name, resource):
`
9
``
`-
self.resources.append((name, resource))
`
10
``
-
11
``
`-
@property
`
12
``
`-
def urlpatterns(self):
`
13
``
`-
ret = []
`
14
``
-
15
``
`-
for name, resource in self.resources:
`
16
``
`-
list_actions = {
`
17
``
`-
'get': getattr(resource, 'list', None),
`
18
``
`-
'post': getattr(resource, 'create', None)
`
19
``
`-
}
`
20
``
`-
detail_actions = {
`
21
``
`-
'get': getattr(resource, 'retrieve', None),
`
22
``
`-
'put': getattr(resource, 'update', None),
`
23
``
`-
'delete': getattr(resource, 'destroy', None)
`
24
``
`-
}
`
25
``
`-
list_regex = r'^%s/$' % name
`
26
``
`-
detail_regex = r'^%s/(?P[0-9]+)/$' % name
`
27
``
`-
list_name = '%s-list'
`
28
``
`-
detail_name = '%s-detail'
`
29
``
-
30
``
`-
ret += url(list_regex, resource.as_view(list_actions), list_name)
`
31
``
`-
ret += url(detail_regex, resource.as_view(detail_actions), detail_name)
`
32
``
-
33
``
`-
return ret
`
``
1
`+
from functools import update_wrapper
`
``
2
`+
from django.utils.decorators import classonlymethod
`
``
3
`+
from rest_framework import views, generics, mixins
`
``
4
+
``
5
+
``
6
`+
class ViewSetMixin(object):
`
``
7
`+
"""
`
``
8
`+
This is the magic.
`
``
9
+
``
10
`` +
Overrides .as_view()
so that it takes an actions
keyword that performs
``
``
11
`+
the binding of HTTP methods to actions on the Resource.
`
``
12
+
``
13
`+
For example, to create a concrete view binding the 'GET' and 'POST' methods
`
``
14
`+
to the 'list' and 'create' actions...
`
``
15
+
``
16
`+
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
`
``
17
`+
"""
`
``
18
+
``
19
`+
@classonlymethod
`
``
20
`+
def as_view(cls, actions=None, **initkwargs):
`
``
21
`+
"""
`
``
22
`+
Main entry point for a request-response process.
`
``
23
+
``
24
`+
Because of the way class based views create a closure around the
`
``
25
`` +
instantiated view, we need to totally reimplement .as_view
,
``
``
26
`+
and slightly modify the view function that is created and returned.
`
``
27
`+
"""
`
``
28
`+
sanitize keyword arguments
`
``
29
`+
for key in initkwargs:
`
``
30
`+
if key in cls.http_method_names:
`
``
31
`+
raise TypeError("You tried to pass in the %s method name as a "
`
``
32
`+
"keyword argument to %s(). Don't do that."
`
``
33
`+
% (key, cls.name))
`
``
34
`+
if not hasattr(cls, key):
`
``
35
`+
raise TypeError("%s() received an invalid keyword %r" % (
`
``
36
`+
cls.name, key))
`
``
37
+
``
38
`+
def view(request, *args, **kwargs):
`
``
39
`+
self = cls(**initkwargs)
`
``
40
+
``
41
`+
Bind methods to actions
`
``
42
`+
This is the bit that's different to a standard view
`
``
43
`+
for method, action in actions.items():
`
``
44
`+
handler = getattr(self, action)
`
``
45
`+
setattr(self, method, handler)
`
``
46
+
``
47
`+
Patch this in as it's otherwise only present from 1.5 onwards
`
``
48
`+
if hasattr(self, 'get') and not hasattr(self, 'head'):
`
``
49
`+
self.head = self.get
`
``
50
+
``
51
`+
And continue as usual
`
``
52
`+
return self.dispatch(request, *args, **kwargs)
`
``
53
+
``
54
`+
take name and docstring from class
`
``
55
`+
update_wrapper(view, cls, updated=())
`
``
56
+
``
57
`+
and possible attributes set by decorators
`
``
58
`+
like csrf_exempt from dispatch
`
``
59
`+
update_wrapper(view, cls.dispatch, assigned=())
`
``
60
`+
return view
`
``
61
+
``
62
+
``
63
`+
class ViewSet(ViewSetMixin, views.APIView):
`
``
64
`+
pass
`
``
65
+
``
66
+
``
67
`+
Note the inheritence of both MultipleObjectAPIView and SingleObjectAPIView
`
``
68
`+
is a bit weird given the diamond inheritence, but it will work for now.
`
``
69
`+
There's some implementation clean up that can happen later.
`
``
70
`+
class ModelViewSet(mixins.CreateModelMixin,
`
``
71
`+
mixins.RetrieveModelMixin,
`
``
72
`+
mixins.UpdateModelMixin,
`
``
73
`+
mixins.DestroyModelMixin,
`
``
74
`+
mixins.ListModelMixin,
`
``
75
`+
ViewSetMixin,
`
``
76
`+
generics.MultipleObjectAPIView,
`
``
77
`+
generics.SingleObjectAPIView):
`
``
78
`+
pass
`
``
79
+
``
80
+
``
81
`+
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
`
``
82
`+
mixins.ListModelMixin,
`
``
83
`+
ViewSetMixin,
`
``
84
`+
generics.MultipleObjectAPIView,
`
``
85
`+
generics.SingleObjectAPIView):
`
``
86
`+
pass
`