aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/generic-views.md2
-rw-r--r--rest_framework/fields.py2
-rw-r--r--rest_framework/renderers.py17
-rw-r--r--rest_framework/serializers.py10
-rw-r--r--rest_framework/tests/models.py4
-rw-r--r--rest_framework/tests/serializer.py20
6 files changed, 32 insertions, 23 deletions
diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md
index 97b4441f..360ef1a2 100644
--- a/docs/api-guide/generic-views.md
+++ b/docs/api-guide/generic-views.md
@@ -30,7 +30,7 @@ For more complex cases you might also want to override various methods on the vi
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
- def get_paginate_by(self):
+ def get_paginate_by(self, queryset):
"""
Use smaller pagination for HTML representations.
"""
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index 6ed37823..85e6ee31 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -258,7 +258,7 @@ class ManyRelatedMixin(object):
def field_from_native(self, data, field_name, into):
if self.readonly:
return
-
+
try:
# Form data
value = data.getlist(self.source or field_name)
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index c64fb517..1a8b1d97 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -224,7 +224,7 @@ class BrowsableAPIRenderer(BaseRenderer):
return content
- def show_form_for_method(self, view, method, request):
+ def show_form_for_method(self, view, method, request, obj):
"""
Returns True if a form should be shown for this method.
"""
@@ -236,7 +236,7 @@ class BrowsableAPIRenderer(BaseRenderer):
request = clone_request(request, method)
try:
- if not view.has_permission(request):
+ if not view.has_permission(request, obj):
return # Don't have permission
except:
return # Don't have permission and exception explicitly raise
@@ -295,7 +295,8 @@ class BrowsableAPIRenderer(BaseRenderer):
In the absence on of the Resource having an associated form then
provide a form that can be used to submit arbitrary content.
"""
- if not self.show_form_for_method(view, method, request):
+ obj = getattr(view, 'object', None)
+ if not self.show_form_for_method(view, method, request, obj):
return
if method == 'DELETE' or method == 'OPTIONS':
@@ -305,17 +306,13 @@ class BrowsableAPIRenderer(BaseRenderer):
media_types = [parser.media_type for parser in view.parser_classes]
return self.get_generic_content_form(media_types)
- # Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
- obj, data = None, None
- if getattr(view, 'object', None):
- obj = view.object
-
serializer = view.get_serializer(instance=obj)
fields = self.serializer_to_form_fields(serializer)
+ # Creating an on the fly form see:
+ # http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields)
- if obj:
- data = serializer.data
+ data = (obj is not None) and serializer.data or None
form_instance = OnTheFlyForm(data)
return form_instance
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 8ee9a0ec..db6f9f61 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -3,6 +3,7 @@ import datetime
import types
from decimal import Decimal
from django.db import models
+from django.forms import widgets
from django.utils.datastructures import SortedDict
from rest_framework.compat import get_concrete_model
from rest_framework.fields import *
@@ -409,6 +410,15 @@ class ModelSerializer(Serializer):
kwargs = {}
if model_field.has_default():
kwargs['required'] = False
+ kwargs['default'] = model_field.get_default()
+
+ if model_field.__class__ == models.TextField:
+ kwargs['widget'] = widgets.Textarea
+
+ # TODO: TypedChoiceField?
+ if model_field.flatchoices: # This ModelField contains choices
+ kwargs['choices'] = model_field.flatchoices
+ return ChoiceField(**kwargs)
field_mapping = {
models.FloatField: FloatField,
diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py
index 97cd0849..0ee18c69 100644
--- a/rest_framework/tests/models.py
+++ b/rest_framework/tests/models.py
@@ -62,12 +62,12 @@ class CallableDefaultValueModel(RESTFrameworkModel):
class ManyToManyModel(RESTFrameworkModel):
rel = models.ManyToManyField(Anchor)
-
+
class ReadOnlyManyToManyModel(RESTFrameworkModel):
text = models.CharField(max_length=100, default='anchor')
rel = models.ManyToManyField(Anchor)
-
+
# Models to test generic relations
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 936f15aa..67c97f0f 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -7,7 +7,7 @@ from rest_framework.tests.models import *
class SubComment(object):
def __init__(self, sub_comment):
self.sub_comment = sub_comment
-
+
class Comment(object):
def __init__(self, email, content, created):
@@ -18,7 +18,7 @@ class Comment(object):
def __eq__(self, other):
return all([getattr(self, attr) == getattr(other, attr)
for attr in ('email', 'content', 'created')])
-
+
def get_sub_comment(self):
sub_comment = SubComment('And Merry Christmas!')
return sub_comment
@@ -29,7 +29,7 @@ class CommentSerializer(serializers.Serializer):
content = serializers.CharField(max_length=1000)
created = serializers.DateTimeField()
sub_comment = serializers.Field(source='get_sub_comment.sub_comment')
-
+
def restore_object(self, data, instance=None):
if instance is None:
return Comment(**data)
@@ -42,6 +42,7 @@ class ActionItemSerializer(serializers.ModelSerializer):
class Meta:
model = ActionItem
+
class BasicTests(TestCase):
def setUp(self):
self.comment = Comment(
@@ -73,7 +74,7 @@ class BasicTests(TestCase):
self.assertEquals(serializer.data, expected)
def test_retrieve(self):
- serializer = CommentSerializer(instance=self.comment)
+ serializer = CommentSerializer(instance=self.comment)
self.assertEquals(serializer.data, self.expected)
def test_create(self):
@@ -104,7 +105,7 @@ class ValidationTests(TestCase):
'email': 'tom@example.com',
'content': 'x' * 1001,
'created': datetime.datetime(2012, 1, 1)
- }
+ }
self.actionitem = ActionItem('Some to do item',
)
@@ -131,7 +132,7 @@ class ValidationTests(TestCase):
"""Make sure that a boolean value with a 'False' value is not
mistaken for not having a default."""
data = {
- 'title':'Some action item',
+ 'title': 'Some action item',
#No 'done' value.
}
serializer = ActionItemSerializer(data, instance=self.actionitem)
@@ -295,11 +296,13 @@ class ManyToManyTests(TestCase):
self.assertEquals(len(ManyToManyModel.objects.all()), 2)
self.assertEquals(instance.pk, 2)
self.assertEquals(list(instance.rel.all()), [])
-
+
+
class ReadOnlyManyToManyTests(TestCase):
def setUp(self):
class ReadOnlyManyToManySerializer(serializers.ModelSerializer):
- rel = serializers.ManyRelatedField(readonly=True)
+ rel = serializers.ManyRelatedField(readonly=True)
+
class Meta:
model = ReadOnlyManyToManyModel
@@ -317,7 +320,6 @@ class ReadOnlyManyToManyTests(TestCase):
# A serialized representation of the model instance
self.data = {'rel': [self.anchor.id], 'id': 1, 'text': 'anchor'}
-
def test_update(self):
"""
Attempt to update an instance of a model with a ManyToMany