RESTful class dispatch

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
from django.http import HttpResponse
from django.http import HttpResponseNotAllowed

METHODS = sorted(('get', 'post', 'head', 'options', 'put', 'delete'))

class ResourceView(object):
    """\
    @brief Base class which implements restful dispatch on a resource

    To use this class you derive from this class and provide an
    implementation for any of the methods in the METHODS tuple found
    at file scope in this file. 

    Define a class which extends ResourceView.

    class Region(ResourceView):
        def get(self, request):
            ...
        def post(self, request):
            ...

    And then in urls.py, dispatch to a new class instance via the call:

    urlpatterns = patterns(
        '',
        (r'^region/$', views.Region.dispatch))

    The call to dispatch call will automatically generate a private Region
    instance which will live for the lengh of the HTTP request/responce
    cycle and then discarded.

    The ResourceView class will generate a reasonable default
    implementation of head() if your class does not provide one and
    defines get().

    *NOTE: Any callable without a leading underscore is considered part of
    the public API and may be called by the dispatch. Make sure you
    prepend underscores in implementation methods which should not be
    accepting direct connections from a client.
    """
    @classmethod
    def dispatch(klass, request, *args, **kwargs):
        """\
        @brief classmethod which is the django callable to call during
        RESTful dispatch.

        @param klass The derived class we are calling.
        @param request The Django request object.
        @return Returns the response in klass in the matching
        request.method.
        """
        return klass().__dispatch(request, *args, **kwargs)

    def __not_allowed(self):
        """\
        @breif Generate the HTTP Not Allowed message for the client.
        """
        allow = []
        for method in METHODS:
            if hasattr(self, method):
                allow.append(method)
        if 'get' in allow and 'head' not in allow:
            allow.append('head')
        return HttpResponseNotAllowed(k.upper() for k in allow)        

    def __default_head(self, request, *args, **kwargs):
        """\
        @brief Simple implementation of HEAD.

        This is implemented as a private method because we cannot add
        automatic support for HEAD unless the instance supports GET
        which has to be detected at runtime in this code structure.
        """
        response = self.get(request, *args, **kwargs)
        if not isinstance(response, HttpResponse): 
            return ''
        response.content = ''
        return response

    def __no_method(self, request, *args, **kwargs):
        """\
        @brief This method is called when the derived class does not
        implement the HTTP method invoked on the object.
        """
        if request.method == 'HEAD' and hasattr(self, 'get'):
            return self.__default_head(request, *args, **kwargs)
        return self.__not_allowed()

    def __dispatch(self, request, *args, **kwargs):
        """\
        @brief Class level implementation for classmethod dispatch.
        """
        method = request.method.lower()
        if method.startswith('_'):
            # do not allow people who make up bad http methods to call
            # into the private implementation details. Phoenix 2009-05-21
            return self.__not_allowed()
        return getattr(self, method, self.__no_method)(request, *args, **kwargs)

More like this

  1. Base class for RESTful Views by jpwatts 5 years, 4 months ago
  2. A simple rest template filter by marinho 6 years, 5 months ago
  3. DateTimeWidget using JSCal2 by ramusus 4 years, 9 months ago
  4. RestView - class for creating a view that dispatches based on request.method by simon 5 years, 7 months ago
  5. orm_tools by limscoder 3 years, 3 months ago

Comments

(Forgotten your password?)