Class-Based Views¶
Also included are some mixins for working with Django’s Class-Based Generic Views. As they follow the existing CBV interfaces, they are compatible with existing decorators and other utilities.
At their core is the MapperMixin, which extends the :class:JsonMixin <nap.utils.JsonMixin>. This provides ways to get the mapper to use for the request, and utility functions for returning empty, single object, and multiple object responses.
Additionally it provides wrappers for these to use specific response codes, which can be configured on the class also.
Base Classes¶
-
class
MapperMixin
¶ All of the following classes are based on this.
-
response_class
¶ The class to construct responses from.
Default: nap.http.JsonResponse
-
content_type
¶ The default content type for responses.
Default: ‘application/json’
-
ok_status
¶ Default: nap.http.STATUS.ACCEPTED
-
accepted_status
¶ Default: nap.http.STATUS.CREATED
-
created_status
¶ Default: nap.http.STATUS.NO_CONTENT
-
error_status
¶ Default: nap.http.STATUS.BAD_REQUEST
HTTP Status codes to use for different response types.
-
get_mapper
(obj=None)¶ Returns an instance of mapper_class
-
empty_response
(**kwargs)¶ Returns an instance of response_class with no content.
-
single_response
(**kwargs)¶ Return a response with a single object.
Will use self.object if object is not passed, or call self.get_object if self.object does not exist.
Will use self.mapper if mapper is not passed, or call self.get_mapper if self.mapper does not exist.
-
multiple_response
(**kwargs)¶ Return a response with a list of objects.
Will use self.object_list if object_list is not passed, or call self.get_queryset() if self.object_list does not exist.
Will use self.mapper if mapper is not passed, or call self.get_mapper() if self.mapper does not exist.
Will apply pagination if self.paginate_by is set or self.include_meta is True.
-
get_meta
(page)¶ Returns pagination metadata for paginated lists.
-
accepted_response
(**kwargs)¶ Returns an empty response with
self.accepted_status
-
created_response
(**kwargs)¶ Returns a single response with
self.created_status
.
-
deleted_response
(**kwargs)¶ Returns an empty response with
self.deleted_status
.
-
error_response
(error)¶ Passes the supplied error dict through nap.utils.flatten_errors, and returns it with status=self.error_status
-
List Classes¶
-
class
ListMixin
(MapperMixin, MultipleObjectMixin)¶ Base list mixin, extends Django’s MultipleObjectMixin.
-
ok_response
(**kwargs)¶
Calls
self.list_response(status=self.ok_response)
-
-
class
ListGetMixin
¶ Provides
get()
for lists.
-
class
ListBaseView
(ListMixin, View)¶
Single Object Classes¶
-
class
ObjectMixin
(MapperMixin, SingleObjectMixin)¶ Base single object mixin, extends Django’s SingleObjectMixin.
-
ok_response
(**kwargs)¶ Calls self.single_response(status=self.ok_status)
-
-
class
ObjectGetMixin
¶ Provides
get()
for single objects.
-
class
ObjectPatchMixin
¶ Provides
patch()
for single objects.-
patch_valid
(**kwargs)¶
-
patch_invalid
(errors)¶
-
-
class
ObjectBaseView
(ObjectMixin, View)¶
Example¶
Sample views.py
that provides GET
, PUT
, PATCH
, and DELETE
methods for the Poll model:
from nap.mapper import ModelMapper
from nap.rest.views import (
ObjectGetMixin, ObjectPutMixin, ObjectPatchMixin, ObjectDeleteMixin,
ObjectBaseView,
)
from .models import Poll
class PollMapper(ModelMapper):
class Meta:
model = Poll
fields = ['question', 'pub_date']
class PollDetailView(ObjectGetMixin,
ObjectPutMixin,
ObjectPatchMixin,
ObjectDeleteMixin,
ObjectBaseView):
model = Poll
mapper_class = PollMapper
Example: Updating two objects¶
Here’s an example of updating two related objects in a single PATCH call.
class UserDetailView(ObjectGetMixin, ObjectBaseView):
model = User
mapper_class = UserMapper
def patch(self, request, *args, **kwargs):
data = self.get_request_data({})
self.object = user = self.get_object()
errors = {}
mapper = self.get_mapper(user)
try:
data >> mapper # This is shorthand for _patch
except ValidationError as e:
errors.update(dict(e))
profile_mapper = ProfileMapper(user.profile)
try:
data >> profile_mapper # This is shorthand for _patch
except ValidationError as e:
errors.update(dict(e))
if errors:
return self.patch_invalid(errors)
user.save()
user.profile.save()
return self.ok_response(object=user, mapper=mapper)
Example: Customising GET¶
Here’s an example of customising a GET call based on a querystring:
class QuestionListView(ListGetMixin, ListBaseView):
model = Question
mapper_class = QuestionMapper
def get(self, request, *args, **kwargs):
qset = self.get_queryset()
# Apply filtering to get only questions for a particular poll
poll_id = request.GET.get('poll_id')
if poll_id:
qset = qset.filter(poll_id=poll_id)
self.object_list = qset
return self.ok_response(object_list=qset)