Skip to content

Commit a97c989

Browse files
author
Jannon Frank
committed
fix read_only related field metadata
1 parent d4dd22f commit a97c989

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

rest_framework/metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def get_field_info(self, field):
127127
if value is not None and value != '':
128128
field_info[attr] = force_text(value, strings_only=True)
129129

130-
if hasattr(field, 'choices'):
130+
if not field_info.get('read_only') and hasattr(field, 'choices'):
131131
field_info['choices'] = [
132132
{
133133
'value': choice_value,

tests/test_metadata.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
from __future__ import unicode_literals
2+
from django.db import models
3+
from django.test import TestCase
4+
from django.core.validators import MinValueValidator, MaxValueValidator
25
from rest_framework import exceptions, metadata, serializers, status, views, versioning
36
from rest_framework.request import Request
47
from rest_framework.renderers import BrowsableAPIRenderer
@@ -212,3 +215,83 @@ def test_null_boolean_field_info_type(self):
212215
options = metadata.SimpleMetadata()
213216
field_info = options.get_field_info(serializers.NullBooleanField())
214217
assert field_info['type'] == 'boolean'
218+
219+
220+
class TestModelSerializerMetadata(TestCase):
221+
def test_read_only_primary_key_related_field(self):
222+
"""
223+
On generic views OPTIONS should return an 'actions' key with metadata
224+
on the fields that may be supplied to PUT and POST requests. It should
225+
not fail when a read_only PrimaryKeyRelatedField is present
226+
"""
227+
class Parent(models.Model):
228+
integer_field = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(1000)])
229+
children = models.ManyToManyField('Child')
230+
name = models.CharField(max_length=100, blank=True, null=True)
231+
232+
class Child(models.Model):
233+
name = models.CharField(max_length=100)
234+
235+
class ExampleSerializer(serializers.ModelSerializer):
236+
children = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
237+
238+
class Meta:
239+
model = Parent
240+
241+
class ExampleView(views.APIView):
242+
"""Example view."""
243+
def post(self, request):
244+
pass
245+
246+
def get_serializer(self):
247+
return ExampleSerializer()
248+
249+
view = ExampleView.as_view()
250+
response = view(request=request)
251+
expected = {
252+
'name': 'Example',
253+
'description': 'Example view.',
254+
'renders': [
255+
'application/json',
256+
'text/html'
257+
],
258+
'parses': [
259+
'application/json',
260+
'application/x-www-form-urlencoded',
261+
'multipart/form-data'
262+
],
263+
'actions': {
264+
'POST': {
265+
'id': {
266+
'type': 'integer',
267+
'required': False,
268+
'read_only': True,
269+
'label': 'ID'
270+
},
271+
'children': {
272+
'type': 'field',
273+
'required': False,
274+
'read_only': True,
275+
'label': 'Children'
276+
},
277+
'integer_field': {
278+
'type': 'integer',
279+
'required': True,
280+
'read_only': False,
281+
'label': 'Integer field',
282+
'min_value': 1,
283+
'max_value': 1000
284+
},
285+
'name': {
286+
'type': 'string',
287+
'required': False,
288+
'read_only': False,
289+
'label': 'Name',
290+
'max_length': 100
291+
}
292+
}
293+
}
294+
}
295+
296+
assert response.status_code == status.HTTP_200_OK
297+
assert response.data == expected

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy