Commit 4ac4676a by Tom Christie

First pass

parent 371d30aa
...@@ -79,18 +79,16 @@ class GenericAPIView(views.APIView): ...@@ -79,18 +79,16 @@ class GenericAPIView(views.APIView):
'view': self 'view': self
} }
def get_serializer(self, instance=None, data=None, files=None, many=False, def get_serializer(self, instance=None, data=None, many=False, partial=False):
partial=False, allow_add_remove=False):
""" """
Return the serializer instance that should be used for validating and Return the serializer instance that should be used for validating and
deserializing input, and for serializing output. deserializing input, and for serializing output.
""" """
serializer_class = self.get_serializer_class() serializer_class = self.get_serializer_class()
context = self.get_serializer_context() context = self.get_serializer_context()
return serializer_class(instance, data=data, files=files, return serializer_class(
many=many, partial=partial, instance, data=data, many=many, partial=partial, context=context
allow_add_remove=allow_add_remove, )
context=context)
def get_pagination_serializer(self, page): def get_pagination_serializer(self, page):
""" """
......
...@@ -36,12 +36,10 @@ class CreateModelMixin(object): ...@@ -36,12 +36,10 @@ class CreateModelMixin(object):
Create a model instance. Create a model instance.
""" """
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.DATA, files=request.FILES) serializer = self.get_serializer(data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
self.pre_save(serializer.object) self.object = serializer.save()
self.object = serializer.save(force_insert=True)
self.post_save(self.object, created=True)
headers = self.get_success_headers(serializer.data) headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, return Response(serializer.data, status=status.HTTP_201_CREATED,
headers=headers) headers=headers)
...@@ -90,26 +88,20 @@ class UpdateModelMixin(object): ...@@ -90,26 +88,20 @@ class UpdateModelMixin(object):
partial = kwargs.pop('partial', False) partial = kwargs.pop('partial', False)
self.object = self.get_object_or_none() self.object = self.get_object_or_none()
serializer = self.get_serializer(self.object, data=request.DATA, serializer = self.get_serializer(self.object, data=request.DATA, partial=partial)
files=request.FILES, partial=partial)
if not serializer.is_valid(): if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
try: lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
self.pre_save(serializer.object) lookup_value = self.kwargs[lookup_url_kwarg]
except ValidationError as err: extras = {self.lookup_field: lookup_value}
# full_clean on model instance may be called in pre_save,
# so we have to handle eventual errors.
return Response(err.message_dict, status=status.HTTP_400_BAD_REQUEST)
if self.object is None: if self.object is None:
self.object = serializer.save(force_insert=True) self.object = serializer.save(extras=extras)
self.post_save(self.object, created=True)
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
self.object = serializer.save(force_update=True) self.object = serializer.save(extras=extras)
self.post_save(self.object, created=False)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
def partial_update(self, request, *args, **kwargs): def partial_update(self, request, *args, **kwargs):
......
...@@ -48,17 +48,17 @@ class DefaultObjectSerializer(serializers.Field): ...@@ -48,17 +48,17 @@ class DefaultObjectSerializer(serializers.Field):
super(DefaultObjectSerializer, self).__init__(source=source) super(DefaultObjectSerializer, self).__init__(source=source)
class PaginationSerializerOptions(serializers.SerializerOptions): # class PaginationSerializerOptions(serializers.SerializerOptions):
""" # """
An object that stores the options that may be provided to a # An object that stores the options that may be provided to a
pagination serializer by using the inner `Meta` class. # pagination serializer by using the inner `Meta` class.
Accessible on the instance as `serializer.opts`. # Accessible on the instance as `serializer.opts`.
""" # """
def __init__(self, meta): # def __init__(self, meta):
super(PaginationSerializerOptions, self).__init__(meta) # super(PaginationSerializerOptions, self).__init__(meta)
self.object_serializer_class = getattr(meta, 'object_serializer_class', # self.object_serializer_class = getattr(meta, 'object_serializer_class',
DefaultObjectSerializer) # DefaultObjectSerializer)
class BasePaginationSerializer(serializers.Serializer): class BasePaginationSerializer(serializers.Serializer):
...@@ -66,7 +66,7 @@ class BasePaginationSerializer(serializers.Serializer): ...@@ -66,7 +66,7 @@ class BasePaginationSerializer(serializers.Serializer):
A base class for pagination serializers to inherit from, A base class for pagination serializers to inherit from,
to make implementing custom serializers more easy. to make implementing custom serializers more easy.
""" """
_options_class = PaginationSerializerOptions # _options_class = PaginationSerializerOptions
results_field = 'results' results_field = 'results'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
......
...@@ -458,7 +458,7 @@ class BrowsableAPIRenderer(BaseRenderer): ...@@ -458,7 +458,7 @@ class BrowsableAPIRenderer(BaseRenderer):
): ):
return return
serializer = view.get_serializer(instance=obj, data=data, files=files) serializer = view.get_serializer(instance=obj, data=data)
serializer.is_valid() serializer.is_valid()
data = serializer.data data = serializer.data
...@@ -579,10 +579,10 @@ class BrowsableAPIRenderer(BaseRenderer): ...@@ -579,10 +579,10 @@ class BrowsableAPIRenderer(BaseRenderer):
'available_formats': [renderer_cls.format for renderer_cls in view.renderer_classes], 'available_formats': [renderer_cls.format for renderer_cls in view.renderer_classes],
'response_headers': response_headers, 'response_headers': response_headers,
'put_form': self.get_rendered_html_form(view, 'PUT', request), #'put_form': self.get_rendered_html_form(view, 'PUT', request),
'post_form': self.get_rendered_html_form(view, 'POST', request), #'post_form': self.get_rendered_html_form(view, 'POST', request),
'delete_form': self.get_rendered_html_form(view, 'DELETE', request), #'delete_form': self.get_rendered_html_form(view, 'DELETE', request),
'options_form': self.get_rendered_html_form(view, 'OPTIONS', request), #'options_form': self.get_rendered_html_form(view, 'OPTIONS', request),
'raw_data_put_form': raw_data_put_form, 'raw_data_put_form': raw_data_put_form,
'raw_data_post_form': raw_data_post_form, 'raw_data_post_form': raw_data_post_form,
......
...@@ -7,7 +7,7 @@ from django.db.models.query import QuerySet ...@@ -7,7 +7,7 @@ from django.db.models.query import QuerySet
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.functional import Promise from django.utils.functional import Promise
from rest_framework.compat import force_text from rest_framework.compat import force_text
from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata # from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata
import datetime import datetime
import decimal import decimal
import types import types
...@@ -106,14 +106,14 @@ else: ...@@ -106,14 +106,14 @@ else:
SortedDict, SortedDict,
yaml.representer.SafeRepresenter.represent_dict yaml.representer.SafeRepresenter.represent_dict
) )
SafeDumper.add_representer( # SafeDumper.add_representer(
DictWithMetadata, # DictWithMetadata,
yaml.representer.SafeRepresenter.represent_dict # yaml.representer.SafeRepresenter.represent_dict
) # )
SafeDumper.add_representer( # SafeDumper.add_representer(
SortedDictWithMetadata, # SortedDictWithMetadata,
yaml.representer.SafeRepresenter.represent_dict # yaml.representer.SafeRepresenter.represent_dict
) # )
SafeDumper.add_representer( SafeDumper.add_representer(
types.GeneratorType, types.GeneratorType,
yaml.representer.SafeRepresenter.represent_list yaml.representer.SafeRepresenter.represent_list
......
"""
Helpers for dealing with HTML input.
"""
def is_html_input(dictionary):
# MultiDict type datastructures are used to represent HTML form input,
# which may have more than one value for each key.
return hasattr(dictionary, 'getlist')
def parse_html_list(dictionary, prefix=''):
"""
Used to suport list values in HTML forms.
Supports lists of primitives and/or dictionaries.
* List of primitives.
{
'[0]': 'abc',
'[1]': 'def',
'[2]': 'hij'
}
-->
[
'abc',
'def',
'hij'
]
* List of dictionaries.
{
'[0]foo': 'abc',
'[0]bar': 'def',
'[1]foo': 'hij',
'[2]bar': 'klm',
}
-->
[
{'foo': 'abc', 'bar': 'def'},
{'foo': 'hij', 'bar': 'klm'}
]
"""
Dict = type(dictionary)
ret = {}
regex = re.compile(r'^%s\[([0-9]+)\](.*)$' % re.escape(prefix))
for field, value in dictionary.items():
match = regex.match(field)
if not match:
continue
index, key = match.groups()
index = int(index)
if not key:
ret[index] = value
elif isinstance(ret.get(index), dict):
ret[index][key] = value
else:
ret[index] = Dict({key: value})
return [ret[item] for item in sorted(ret.keys())]
def parse_html_dict(dictionary, prefix):
"""
Used to support dictionary values in HTML forms.
{
'profile.username': 'example',
'profile.email': 'example@example.com',
}
-->
{
'profile': {
'username': 'example,
'email': 'example@example.com'
}
}
"""
ret = {}
regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix))
for field, value in dictionary.items():
match = regex.match(field)
if not match:
continue
key = match.groups()[0]
ret[key] = value
return ret
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment