""" Basic building blocks for generic class based views. We don't bind behaviour to http method handlers yet, which allows mixin classes to be composed in interesting ways. Eg. Use mixins to build a Resource class, and have a Router class perform the binding of http methods to actions for us. """ from rest_framework import status from rest_framework.response import Response class CreateModelMixin(object): """ Create a model instance. Should be mixed in with any `BaseView`. """ def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.DATA) if serializer.is_valid(): self.object = serializer.object self.object.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class ListModelMixin(object): """ List a queryset. Should be mixed in with `MultipleObjectBaseView`. """ def list(self, request, *args, **kwargs): self.object_list = self.get_queryset() serializer = self.get_serializer(instance=self.object_list) return Response(serializer.data) class RetrieveModelMixin(object): """ Retrieve a model instance. Should be mixed in with `SingleObjectBaseView`. """ def retrieve(self, request, *args, **kwargs): self.object = self.get_object() serializer = self.get_serializer(instance=self.object) return Response(serializer.data) class UpdateModelMixin(object): """ Update a model instance. Should be mixed in with `SingleObjectBaseView`. """ def update(self, request, *args, **kwargs): self.object = self.get_object() serializer = self.get_serializer(data=request.DATA, instance=self.object) if serializer.is_valid(): self.object = serializer.object self.object.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class DestroyModelMixin(object): """ Destroy a model instance. Should be mixed in with `SingleObjectBaseView`. """ def destroy(self, request, *args, **kwargs): self.object = self.get_object() self.object.delete() return Response(status=status.HTTP_204_NO_CONTENT) class MetadataMixin(object): """ Return a dicitonary of view metadata. Should be mixed in with any `BaseView`. This mixin is typically used for the HTTP 'OPTIONS' method. """ def metadata(self, request, *args, **kwargs): content = { 'name': self.get_name(), 'description': self.get_description(), 'renders': [renderer.media_type for renderer in self.renderer_classes], 'parses': [parser.media_type for parser in self.parser_classes], } # TODO: Add 'fields', from serializer info. # form = self.get_bound_form() # if form is not None: # field_name_types = {} # for name, field in form.fields.iteritems(): # field_name_types[name] = field.__class__.__name__ # content['fields'] = field_name_types return Response(content, status=status.HTTP_200_OK)