mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 01:47:59 +03:00 
			
		
		
		
	Merge pull request #3255 from jamesbeith/issues/#3254-display-value
Add a method to return the string value used in `choices` of a `RelatedField`
This commit is contained in:
		
						commit
						2d5e8dea15
					
				| 
						 | 
					@ -537,6 +537,14 @@ If you explicitly specify a relational field pointing to a
 | 
				
			||||||
``ManyToManyField`` with a through model, be sure to set ``read_only``
 | 
					``ManyToManyField`` with a through model, be sure to set ``read_only``
 | 
				
			||||||
to ``True``.
 | 
					to ``True``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The `display_value` method
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `__str__` (`__unicode__` on Python 2) method of the model will be called to generate string representations of the objects used to populate the `choices` property. These choices are used to populate select HTML inputs in the browsable API. To provide customized representations for such inputs, override `display_value` of a `RelatedField` subclass. This method will receive a model object, and should return a string suitable for representing it. For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class TrackPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
 | 
				
			||||||
 | 
					        def display_value(self, instance):
 | 
				
			||||||
 | 
					            return 'Track: %s' % (instance.title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Third Party Packages
 | 
					# Third Party Packages
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ class RelatedField(Field):
 | 
				
			||||||
        return OrderedDict([
 | 
					        return OrderedDict([
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                six.text_type(self.to_representation(item)),
 | 
					                six.text_type(self.to_representation(item)),
 | 
				
			||||||
                six.text_type(item)
 | 
					                self.display_value(item)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            for item in queryset
 | 
					            for item in queryset
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
| 
						 | 
					@ -160,6 +160,9 @@ class RelatedField(Field):
 | 
				
			||||||
    def iter_options(self):
 | 
					    def iter_options(self):
 | 
				
			||||||
        return iter_options(self.grouped_choices)
 | 
					        return iter_options(self.grouped_choices)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def display_value(self, instance):
 | 
				
			||||||
 | 
					        return six.text_type(instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StringRelatedField(RelatedField):
 | 
					class StringRelatedField(RelatedField):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ from django.utils import six
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from rest_framework import serializers
 | 
					from rest_framework import serializers
 | 
				
			||||||
from rest_framework.compat import DurationField as ModelDurationField
 | 
					from rest_framework.compat import DurationField as ModelDurationField
 | 
				
			||||||
from rest_framework.compat import unicode_repr
 | 
					from rest_framework.compat import OrderedDict, unicode_repr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def dedent(blocktext):
 | 
					def dedent(blocktext):
 | 
				
			||||||
| 
						 | 
					@ -546,6 +546,50 @@ class TestRelationalFieldMappings(TestCase):
 | 
				
			||||||
        self.assertEqual(unicode_repr(TestSerializer()), expected)
 | 
					        self.assertEqual(unicode_repr(TestSerializer()), expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayValueTargetModel(models.Model):
 | 
				
			||||||
 | 
					    name = models.CharField(max_length=100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self):
 | 
				
			||||||
 | 
					        return '%s Color' % (self.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayValueModel(models.Model):
 | 
				
			||||||
 | 
					    color = models.ForeignKey(DisplayValueTargetModel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestRelationalFieldDisplayValue(TestCase):
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        DisplayValueTargetModel.objects.bulk_create([
 | 
				
			||||||
 | 
					            DisplayValueTargetModel(name='Red'),
 | 
				
			||||||
 | 
					            DisplayValueTargetModel(name='Yellow'),
 | 
				
			||||||
 | 
					            DisplayValueTargetModel(name='Green'),
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_default_display_value(self):
 | 
				
			||||||
 | 
					        class TestSerializer(serializers.ModelSerializer):
 | 
				
			||||||
 | 
					            class Meta:
 | 
				
			||||||
 | 
					                model = DisplayValueModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        serializer = TestSerializer()
 | 
				
			||||||
 | 
					        expected = OrderedDict([('1', 'Red Color'), ('2', 'Yellow Color'), ('3', 'Green Color')])
 | 
				
			||||||
 | 
					        self.assertEqual(serializer.fields['color'].choices, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_custom_display_value(self):
 | 
				
			||||||
 | 
					        class TestField(serializers.PrimaryKeyRelatedField):
 | 
				
			||||||
 | 
					            def display_value(self, instance):
 | 
				
			||||||
 | 
					                return 'My %s Color' % (instance.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class TestSerializer(serializers.ModelSerializer):
 | 
				
			||||||
 | 
					            color = TestField(queryset=DisplayValueTargetModel.objects.all())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            class Meta:
 | 
				
			||||||
 | 
					                model = DisplayValueModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        serializer = TestSerializer()
 | 
				
			||||||
 | 
					        expected = OrderedDict([('1', 'My Red Color'), ('2', 'My Yellow Color'), ('3', 'My Green Color')])
 | 
				
			||||||
 | 
					        self.assertEqual(serializer.fields['color'].choices, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestIntegration(TestCase):
 | 
					class TestIntegration(TestCase):
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.foreign_key_target = ForeignKeyTargetModel.objects.create(
 | 
					        self.foreign_key_target = ForeignKeyTargetModel.objects.create(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user