Repository: encode/django-rest-framework

Issue:
Web browseable API doesn't have blank option on drop down list box 
A model with a foreign key attribute which has been set to blankable and nullable. And a serializer which has arguments of read_only=False and required=False.

When viewed with the web browseable API we get a drop box which automatically selects the first available foreignkey.  Testing with an independant REST post application it was determined that the model was happy to post a null attribute.

Perhaps the correct user experience would be to have a null option in the drop box??

![image](https://f.cloud.github.com/assets/6656808/2144754/9e9fda20-938f-11e3-81f3-0d3a9f62417c.png)



Discussion:
Yep. That sounds reasonable. A Django Forms ChoiceField adds (and in absence of a default selects) a extra null option. 

Sounds correct to me too yup.

Just to be thorough, perhaps it should only do this if the attribute is blank=True and null=True in the model.  I am not sure how the behaviour should change depending on the serializer options.

Shouldn't dep on the model field, but rather if required=False on the serializer (Which in the case of model serializers gets set automatically based on the model fields, so same end result)

Awesome, I figured that was the case, thanks for clarifying!

This should already be handled: when a `ChoiceField` is initialised, an extra empty field is prepended to the list of choices if the field is not required: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L512-L517

@keyCutter: which version of DRF did you see this with?

Perhaps that init code for ChoiceField also needs to be replicated for serializer relation fields?

djangorestframework-2.2.6


Resolving patch:
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -59,6 +59,8 @@ def __init__(self, *args, **kwargs):
         super(RelatedField, self).__init__(*args, **kwargs)
 
         if not self.required:
+            # Accessed in ModelChoiceIterator django/forms/models.py:1034
+            # If set adds empty choice.
             self.empty_label = BLANK_CHOICE_DASH[0][1]
 
         self.queryset = queryset


Test patch:
diff --git a/rest_framework/tests/test_relations.py b/rest_framework/tests/test_relations.py
--- a/rest_framework/tests/test_relations.py
+++ b/rest_framework/tests/test_relations.py
@@ -2,8 +2,10 @@
 General tests for relational fields.
 """
 from __future__ import unicode_literals
+from django import get_version
 from django.db import models
 from django.test import TestCase
+from django.utils import unittest
 from rest_framework import serializers
 from rest_framework.tests.models import BlogPost
 
@@ -118,3 +120,25 @@ class Meta:
             (serializers.ModelSerializer,), attrs)
         with self.assertRaises(AttributeError):
             TestSerializer(data={'name': 'foo'})
+
+@unittest.skipIf(get_version() < '1.6.0', 'Upstream behaviour changed in v1.6')
+class RelatedFieldChoicesTests(TestCase):
+    """
+    Tests for #1408 "Web browseable API doesn't have blank option on drop down list box"
+    https://github.com/tomchristie/django-rest-framework/issues/1408
+    """
+    def test_blank_option_is_added_to_choice_if_required_equals_false(self):
+        """
+
+        """
+        post = BlogPost(title="Checking blank option is added")
+        post.save()
+
+        queryset = BlogPost.objects.all()
+        field = serializers.RelatedField(required=False, queryset=queryset)
+
+        choice_count = BlogPost.objects.count()
+        widget_count = len(field.widget.choices)
+
+        self.assertEqual(widget_count, choice_count + 1, 'BLANK_CHOICE_DASH option should have been added')
+