Statistics
| Branch: | Tag: | Revision:

root / userdata / rest.py @ eee0487e

History | View | Annotate | Download (5.1 kB)

1 eee0487e Kostas Papadimitriou
from django import http
2 eee0487e Kostas Papadimitriou
from django.template import RequestContext, loader
3 eee0487e Kostas Papadimitriou
from django.utils import simplejson as json
4 eee0487e Kostas Papadimitriou
from django.core import serializers
5 eee0487e Kostas Papadimitriou
6 eee0487e Kostas Papadimitriou
# base view class
7 eee0487e Kostas Papadimitriou
# https://github.com/bfirsh/django-class-based-views/blob/master/class_based_views/base.py
8 eee0487e Kostas Papadimitriou
class View(object):
9 eee0487e Kostas Papadimitriou
    """
10 eee0487e Kostas Papadimitriou
    Intentionally simple parent class for all views. Only implements
11 eee0487e Kostas Papadimitriou
    dispatch-by-method and simple sanity checking.
12 eee0487e Kostas Papadimitriou
    """
13 eee0487e Kostas Papadimitriou
14 eee0487e Kostas Papadimitriou
    method_names = ['GET', 'POST', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE']
15 eee0487e Kostas Papadimitriou
16 eee0487e Kostas Papadimitriou
    def __init__(self, *args, **kwargs):
17 eee0487e Kostas Papadimitriou
        """
18 eee0487e Kostas Papadimitriou
        Constructor. Called in the URLconf; can contain helpful extra
19 eee0487e Kostas Papadimitriou
        keyword arguments, and other things.
20 eee0487e Kostas Papadimitriou
        """
21 eee0487e Kostas Papadimitriou
        # Go through keyword arguments, and either save their values to our
22 eee0487e Kostas Papadimitriou
        # instance, or raise an error.
23 eee0487e Kostas Papadimitriou
        for key, value in kwargs.items():
24 eee0487e Kostas Papadimitriou
            if key in self.method_names:
25 eee0487e Kostas Papadimitriou
                raise TypeError(u"You tried to pass in the %s method name as a "
26 eee0487e Kostas Papadimitriou
                                u"keyword argument to %s(). Don't do that."
27 eee0487e Kostas Papadimitriou
                                % (key, self.__class__.__name__))
28 eee0487e Kostas Papadimitriou
            if hasattr(self, key):
29 eee0487e Kostas Papadimitriou
                setattr(self, key, value)
30 eee0487e Kostas Papadimitriou
            else:
31 eee0487e Kostas Papadimitriou
                raise TypeError(u"%s() received an invalid keyword %r" % (
32 eee0487e Kostas Papadimitriou
                    self.__class__.__name__,
33 eee0487e Kostas Papadimitriou
                    key,
34 eee0487e Kostas Papadimitriou
                ))
35 eee0487e Kostas Papadimitriou
36 eee0487e Kostas Papadimitriou
    def instance_to_dict(self, i, exclude_fields=[]):
37 eee0487e Kostas Papadimitriou
        """
38 eee0487e Kostas Papadimitriou
        Convert model instance to python dict
39 eee0487e Kostas Papadimitriou
        """
40 eee0487e Kostas Papadimitriou
        d = {}
41 eee0487e Kostas Papadimitriou
        for field in i._meta.get_all_field_names():
42 eee0487e Kostas Papadimitriou
            if field in exclude_fields:
43 eee0487e Kostas Papadimitriou
                continue
44 eee0487e Kostas Papadimitriou
45 eee0487e Kostas Papadimitriou
            d[field] = i.__getattribute__(field)
46 eee0487e Kostas Papadimitriou
        return d
47 eee0487e Kostas Papadimitriou
48 eee0487e Kostas Papadimitriou
    def qs_to_dict_iter(self, qs, exclude_fields=[]):
49 eee0487e Kostas Papadimitriou
        """
50 eee0487e Kostas Papadimitriou
        Convert queryset to an iterator of model instances dicts
51 eee0487e Kostas Papadimitriou
        """
52 eee0487e Kostas Papadimitriou
        for i in qs:
53 eee0487e Kostas Papadimitriou
            yield self.instance_to_dict(i, exclude_fields)
54 eee0487e Kostas Papadimitriou
55 eee0487e Kostas Papadimitriou
    def json_response(self, data):
56 eee0487e Kostas Papadimitriou
        return http.HttpResponse(json.dumps(data))
57 eee0487e Kostas Papadimitriou
58 eee0487e Kostas Papadimitriou
    @classmethod
59 eee0487e Kostas Papadimitriou
    def as_view(cls, *initargs, **initkwargs):
60 eee0487e Kostas Papadimitriou
        """
61 eee0487e Kostas Papadimitriou
        Main entry point for a request-response process.
62 eee0487e Kostas Papadimitriou
        """
63 eee0487e Kostas Papadimitriou
        def view(request, *args, **kwargs):
64 eee0487e Kostas Papadimitriou
            self = cls(*initargs, **initkwargs)
65 eee0487e Kostas Papadimitriou
            return self.dispatch(request, *args, **kwargs)
66 eee0487e Kostas Papadimitriou
        return view
67 eee0487e Kostas Papadimitriou
68 eee0487e Kostas Papadimitriou
    def dispatch(self, request, *args, **kwargs):
69 eee0487e Kostas Papadimitriou
        # Try to dispatch to the right method for that; if it doesn't exist,
70 eee0487e Kostas Papadimitriou
        # raise a big error.
71 eee0487e Kostas Papadimitriou
        if hasattr(self, request.method.upper()):
72 eee0487e Kostas Papadimitriou
            self.request = request
73 eee0487e Kostas Papadimitriou
            self.args = args
74 eee0487e Kostas Papadimitriou
            self.kwargs = kwargs
75 eee0487e Kostas Papadimitriou
            data = request.raw_post_data
76 eee0487e Kostas Papadimitriou
77 eee0487e Kostas Papadimitriou
            if request.method.upper() in ['POST', 'PUT']:
78 eee0487e Kostas Papadimitriou
                # Expect json data
79 eee0487e Kostas Papadimitriou
                if request.META.get('CONTENT_TYPE').startswith('application/json'):
80 eee0487e Kostas Papadimitriou
                    try:
81 eee0487e Kostas Papadimitriou
                        data = json.loads(data)
82 eee0487e Kostas Papadimitriou
                    except ValueError:
83 eee0487e Kostas Papadimitriou
                        raise http.HttpResponseServerError('Invalid JSON data.')
84 eee0487e Kostas Papadimitriou
                else:
85 eee0487e Kostas Papadimitriou
                    raise http.HttpResponseServerError('Unsupported Content-Type.')
86 eee0487e Kostas Papadimitriou
87 eee0487e Kostas Papadimitriou
            return getattr(self, request.method.upper())(request, data, *args, **kwargs)
88 eee0487e Kostas Papadimitriou
        else:
89 eee0487e Kostas Papadimitriou
            allowed_methods = [m for m in self.method_names if hasattr(self, m)]
90 eee0487e Kostas Papadimitriou
            return http.HttpResponseNotAllowed(allowed_methods)
91 eee0487e Kostas Papadimitriou
92 eee0487e Kostas Papadimitriou
93 eee0487e Kostas Papadimitriou
class ResourceView(View):
94 eee0487e Kostas Papadimitriou
    method_names = ['GET', 'POST', 'PUT', 'DELETE']
95 eee0487e Kostas Papadimitriou
96 eee0487e Kostas Papadimitriou
    model = None
97 eee0487e Kostas Papadimitriou
    exclude_fields = []
98 eee0487e Kostas Papadimitriou
99 eee0487e Kostas Papadimitriou
    def queryset(self):
100 eee0487e Kostas Papadimitriou
        return self.model.objects.all()
101 eee0487e Kostas Papadimitriou
102 eee0487e Kostas Papadimitriou
    def instance(self):
103 eee0487e Kostas Papadimitriou
        """
104 eee0487e Kostas Papadimitriou
        Retrieve selected instance based on url parameter
105 eee0487e Kostas Papadimitriou

106 eee0487e Kostas Papadimitriou
        id parameter should be set in urlpatterns expression
107 eee0487e Kostas Papadimitriou
        """
108 eee0487e Kostas Papadimitriou
        try:
109 eee0487e Kostas Papadimitriou
            return self.queryset().get(pk=self.kwargs.get("id"))
110 eee0487e Kostas Papadimitriou
        except self.model.DoesNotExist:
111 eee0487e Kostas Papadimitriou
            raise http.Http404
112 eee0487e Kostas Papadimitriou
113 eee0487e Kostas Papadimitriou
    def GET(self, request, data, *args, **kwargs):
114 eee0487e Kostas Papadimitriou
        return self.json_response(self.instance_to_dict(self.instance(),
115 eee0487e Kostas Papadimitriou
            self.exclude_fields))
116 eee0487e Kostas Papadimitriou
117 eee0487e Kostas Papadimitriou
    def POST(self, request, data, *args, **kwargs):
118 eee0487e Kostas Papadimitriou
        pass
119 eee0487e Kostas Papadimitriou
120 eee0487e Kostas Papadimitriou
    def DELETE(self, request, data, *args, **kwargs):
121 eee0487e Kostas Papadimitriou
        self.instance().delete()
122 eee0487e Kostas Papadimitriou
        return HttpResponse()
123 eee0487e Kostas Papadimitriou
124 eee0487e Kostas Papadimitriou
125 eee0487e Kostas Papadimitriou
class CollectionView(View):
126 eee0487e Kostas Papadimitriou
    method_names = ['GET', 'POST', 'PUT', 'DELETE']
127 eee0487e Kostas Papadimitriou
128 eee0487e Kostas Papadimitriou
    model = None
129 eee0487e Kostas Papadimitriou
    exclude_fields = []
130 eee0487e Kostas Papadimitriou
131 eee0487e Kostas Papadimitriou
    def queryset(self):
132 eee0487e Kostas Papadimitriou
        return self.model.objects.all()
133 eee0487e Kostas Papadimitriou
134 eee0487e Kostas Papadimitriou
    def GET(self, request, data, *args, **kwargs):
135 eee0487e Kostas Papadimitriou
        return self.json_response(list(self.qs_to_dict_iter(self.queryset(),
136 eee0487e Kostas Papadimitriou
            self.exclude_fields)))
137 eee0487e Kostas Papadimitriou
138 eee0487e Kostas Papadimitriou
    def PUT(self, request, data, *args, **kwargs):
139 eee0487e Kostas Papadimitriou
        pass
140 eee0487e Kostas Papadimitriou
141 eee0487e Kostas Papadimitriou
    def DELETE(self, request, data, *args, **kwargs):
142 eee0487e Kostas Papadimitriou
        pass
143 eee0487e Kostas Papadimitriou
144 eee0487e Kostas Papadimitriou
class UserResourceView(ResourceView):
145 eee0487e Kostas Papadimitriou
    """
146 eee0487e Kostas Papadimitriou
    Filter resource queryset for request user entries
147 eee0487e Kostas Papadimitriou
    """
148 eee0487e Kostas Papadimitriou
    def queryset(self):
149 eee0487e Kostas Papadimitriou
        return super(UserResourceView,
150 eee0487e Kostas Papadimitriou
                self).queryset().filter(user=self.request.user)
151 eee0487e Kostas Papadimitriou
152 eee0487e Kostas Papadimitriou
class UserCollectionView(CollectionView):
153 eee0487e Kostas Papadimitriou
    """
154 eee0487e Kostas Papadimitriou
    Filter collection queryset for request user entries
155 eee0487e Kostas Papadimitriou
    """
156 eee0487e Kostas Papadimitriou
    def queryset(self):
157 eee0487e Kostas Papadimitriou
        return super(UserCollectionView, self).queryset().filter(user=self.request.user)