mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-17 03:51:03 +03:00
Merge pull request #321 from tomchristie/pastebin_tutorial
Tweaks and fixes in order to support the pastebin tutorial
This commit is contained in:
commit
7cdedc0f71
|
@ -30,7 +30,7 @@ For more complex cases you might also want to override various methods on the vi
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
permission_classes = (IsAdminUser,)
|
permission_classes = (IsAdminUser,)
|
||||||
|
|
||||||
def get_paginate_by(self):
|
def get_paginate_by(self, queryset):
|
||||||
"""
|
"""
|
||||||
Use smaller pagination for HTML representations.
|
Use smaller pagination for HTML representations.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -258,7 +258,7 @@ class ManyRelatedMixin(object):
|
||||||
def field_from_native(self, data, field_name, into):
|
def field_from_native(self, data, field_name, into):
|
||||||
if self.readonly:
|
if self.readonly:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Form data
|
# Form data
|
||||||
value = data.getlist(self.source or field_name)
|
value = data.getlist(self.source or field_name)
|
||||||
|
|
|
@ -224,7 +224,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
|
|
||||||
return content
|
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.
|
Returns True if a form should be shown for this method.
|
||||||
"""
|
"""
|
||||||
|
@ -236,7 +236,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
|
|
||||||
request = clone_request(request, method)
|
request = clone_request(request, method)
|
||||||
try:
|
try:
|
||||||
if not view.has_permission(request):
|
if not view.has_permission(request, obj):
|
||||||
return # Don't have permission
|
return # Don't have permission
|
||||||
except:
|
except:
|
||||||
return # Don't have permission and exception explicitly raise
|
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
|
In the absence on of the Resource having an associated form then
|
||||||
provide a form that can be used to submit arbitrary content.
|
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
|
return
|
||||||
|
|
||||||
if method == 'DELETE' or method == 'OPTIONS':
|
if method == 'DELETE' or method == 'OPTIONS':
|
||||||
|
@ -305,17 +306,13 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
media_types = [parser.media_type for parser in view.parser_classes]
|
media_types = [parser.media_type for parser in view.parser_classes]
|
||||||
return self.get_generic_content_form(media_types)
|
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)
|
serializer = view.get_serializer(instance=obj)
|
||||||
fields = self.serializer_to_form_fields(serializer)
|
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)
|
OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields)
|
||||||
if obj:
|
data = (obj is not None) and serializer.data or None
|
||||||
data = serializer.data
|
|
||||||
form_instance = OnTheFlyForm(data)
|
form_instance = OnTheFlyForm(data)
|
||||||
return form_instance
|
return form_instance
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import datetime
|
||||||
import types
|
import types
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.forms import widgets
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
from rest_framework.compat import get_concrete_model
|
from rest_framework.compat import get_concrete_model
|
||||||
from rest_framework.fields import *
|
from rest_framework.fields import *
|
||||||
|
@ -409,6 +410,15 @@ class ModelSerializer(Serializer):
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if model_field.has_default():
|
if model_field.has_default():
|
||||||
kwargs['required'] = False
|
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 = {
|
field_mapping = {
|
||||||
models.FloatField: FloatField,
|
models.FloatField: FloatField,
|
||||||
|
|
|
@ -62,12 +62,12 @@ class CallableDefaultValueModel(RESTFrameworkModel):
|
||||||
|
|
||||||
class ManyToManyModel(RESTFrameworkModel):
|
class ManyToManyModel(RESTFrameworkModel):
|
||||||
rel = models.ManyToManyField(Anchor)
|
rel = models.ManyToManyField(Anchor)
|
||||||
|
|
||||||
|
|
||||||
class ReadOnlyManyToManyModel(RESTFrameworkModel):
|
class ReadOnlyManyToManyModel(RESTFrameworkModel):
|
||||||
text = models.CharField(max_length=100, default='anchor')
|
text = models.CharField(max_length=100, default='anchor')
|
||||||
rel = models.ManyToManyField(Anchor)
|
rel = models.ManyToManyField(Anchor)
|
||||||
|
|
||||||
# Models to test generic relations
|
# Models to test generic relations
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from rest_framework.tests.models import *
|
||||||
class SubComment(object):
|
class SubComment(object):
|
||||||
def __init__(self, sub_comment):
|
def __init__(self, sub_comment):
|
||||||
self.sub_comment = sub_comment
|
self.sub_comment = sub_comment
|
||||||
|
|
||||||
|
|
||||||
class Comment(object):
|
class Comment(object):
|
||||||
def __init__(self, email, content, created):
|
def __init__(self, email, content, created):
|
||||||
|
@ -18,7 +18,7 @@ class Comment(object):
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return all([getattr(self, attr) == getattr(other, attr)
|
return all([getattr(self, attr) == getattr(other, attr)
|
||||||
for attr in ('email', 'content', 'created')])
|
for attr in ('email', 'content', 'created')])
|
||||||
|
|
||||||
def get_sub_comment(self):
|
def get_sub_comment(self):
|
||||||
sub_comment = SubComment('And Merry Christmas!')
|
sub_comment = SubComment('And Merry Christmas!')
|
||||||
return sub_comment
|
return sub_comment
|
||||||
|
@ -29,7 +29,7 @@ class CommentSerializer(serializers.Serializer):
|
||||||
content = serializers.CharField(max_length=1000)
|
content = serializers.CharField(max_length=1000)
|
||||||
created = serializers.DateTimeField()
|
created = serializers.DateTimeField()
|
||||||
sub_comment = serializers.Field(source='get_sub_comment.sub_comment')
|
sub_comment = serializers.Field(source='get_sub_comment.sub_comment')
|
||||||
|
|
||||||
def restore_object(self, data, instance=None):
|
def restore_object(self, data, instance=None):
|
||||||
if instance is None:
|
if instance is None:
|
||||||
return Comment(**data)
|
return Comment(**data)
|
||||||
|
@ -42,6 +42,7 @@ class ActionItemSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ActionItem
|
model = ActionItem
|
||||||
|
|
||||||
|
|
||||||
class BasicTests(TestCase):
|
class BasicTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.comment = Comment(
|
self.comment = Comment(
|
||||||
|
@ -73,7 +74,7 @@ class BasicTests(TestCase):
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_retrieve(self):
|
def test_retrieve(self):
|
||||||
serializer = CommentSerializer(instance=self.comment)
|
serializer = CommentSerializer(instance=self.comment)
|
||||||
self.assertEquals(serializer.data, self.expected)
|
self.assertEquals(serializer.data, self.expected)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
|
@ -104,7 +105,7 @@ class ValidationTests(TestCase):
|
||||||
'email': 'tom@example.com',
|
'email': 'tom@example.com',
|
||||||
'content': 'x' * 1001,
|
'content': 'x' * 1001,
|
||||||
'created': datetime.datetime(2012, 1, 1)
|
'created': datetime.datetime(2012, 1, 1)
|
||||||
}
|
}
|
||||||
self.actionitem = ActionItem('Some to do item',
|
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
|
"""Make sure that a boolean value with a 'False' value is not
|
||||||
mistaken for not having a default."""
|
mistaken for not having a default."""
|
||||||
data = {
|
data = {
|
||||||
'title':'Some action item',
|
'title': 'Some action item',
|
||||||
#No 'done' value.
|
#No 'done' value.
|
||||||
}
|
}
|
||||||
serializer = ActionItemSerializer(data, instance=self.actionitem)
|
serializer = ActionItemSerializer(data, instance=self.actionitem)
|
||||||
|
@ -295,11 +296,13 @@ class ManyToManyTests(TestCase):
|
||||||
self.assertEquals(len(ManyToManyModel.objects.all()), 2)
|
self.assertEquals(len(ManyToManyModel.objects.all()), 2)
|
||||||
self.assertEquals(instance.pk, 2)
|
self.assertEquals(instance.pk, 2)
|
||||||
self.assertEquals(list(instance.rel.all()), [])
|
self.assertEquals(list(instance.rel.all()), [])
|
||||||
|
|
||||||
|
|
||||||
class ReadOnlyManyToManyTests(TestCase):
|
class ReadOnlyManyToManyTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class ReadOnlyManyToManySerializer(serializers.ModelSerializer):
|
class ReadOnlyManyToManySerializer(serializers.ModelSerializer):
|
||||||
rel = serializers.ManyRelatedField(readonly=True)
|
rel = serializers.ManyRelatedField(readonly=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReadOnlyManyToManyModel
|
model = ReadOnlyManyToManyModel
|
||||||
|
|
||||||
|
@ -317,7 +320,6 @@ class ReadOnlyManyToManyTests(TestCase):
|
||||||
# A serialized representation of the model instance
|
# A serialized representation of the model instance
|
||||||
self.data = {'rel': [self.anchor.id], 'id': 1, 'text': 'anchor'}
|
self.data = {'rel': [self.anchor.id], 'id': 1, 'text': 'anchor'}
|
||||||
|
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
"""
|
"""
|
||||||
Attempt to update an instance of a model with a ManyToMany
|
Attempt to update an instance of a model with a ManyToMany
|
||||||
|
|
Loading…
Reference in New Issue
Block a user