Skip to content

Commit

Permalink
fix read_only related field metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Jannon Frank committed May 28, 2015
1 parent 6634ce0 commit add2825
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 8 deletions.
17 changes: 9 additions & 8 deletions rest_framework/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,14 @@ def get_field_info(self, field):
if value is not None and value != '':
field_info[attr] = force_text(value, strings_only=True)

if hasattr(field, 'choices'):
field_info['choices'] = [
{
'value': choice_value,
'display_name': force_text(choice_name, strings_only=True)
}
for choice_value, choice_name in field.choices.items()
]
if 'read_only' in field_info and not field_info['read_only']:
if hasattr(field, 'choices'):
field_info['choices'] = [
{
'value': choice_value,
'display_name': force_text(choice_name, strings_only=True)
}
for choice_value, choice_name in field.choices.items()
]

return field_info
82 changes: 82 additions & 0 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from __future__ import unicode_literals
from django.db import models
from django.test import TestCase
from django.core.validators import MinValueValidator, MaxValueValidator, MinLengthValidator
from rest_framework import exceptions, metadata, serializers, status, views, versioning
from rest_framework.request import Request
from rest_framework.renderers import BrowsableAPIRenderer
Expand Down Expand Up @@ -212,3 +215,82 @@ def test_null_boolean_field_info_type(self):
options = metadata.SimpleMetadata()
field_info = options.get_field_info(serializers.NullBooleanField())
assert field_info['type'] == 'boolean'


class TestModelSerializerMetadata(TestCase):
def test_read_only_primary_key_related_field(self):
"""
On generic views OPTIONS should return an 'actions' key with metadata
on the fields that may be supplied to PUT and POST requests. It should
not fail when a read_only PrimaryKeyRelatedField is present
"""
class Parent(models.Model):
integer_field = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(1000)])
children = models.ManyToManyField('Child')
name = models.CharField(max_length=100, blank=True, null=True)

class Child(models.Model):
name = models.CharField(max_length=100)

class ExampleSerializer(serializers.ModelSerializer):
children = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
class Meta:
model = Parent

class ExampleView(views.APIView):
"""Example view."""
def post(self, request):
pass

def get_serializer(self):
return ExampleSerializer()

view = ExampleView.as_view()
response = view(request=request)
expected = {
'name': 'Example',
'description': 'Example view.',
'renders': [
'application/json',
'text/html'
],
'parses': [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
'actions': {
'POST': {
'id': {
'type': 'integer',
'required': False,
'read_only': True,
'label': 'ID'
},
'children': {
'type': 'field',
'required': False,
'read_only': True,
'label': 'Children'
},
'integer_field': {
'type': 'integer',
'required': True,
'read_only': False,
'label': 'Integer field',
'min_value': 1,
'max_value': 1000
},
'name': {
'type': 'string',
'required': False,
'read_only': False,
'label': 'Name',
'max_length': 100
}
}
}
}

assert response.status_code == status.HTTP_200_OK
assert response.data == expected

0 comments on commit add2825

Please sign in to comment.