{"id":433,"date":"2013-02-15T11:08:38","date_gmt":"2013-02-15T15:08:38","guid":{"rendered":"http:\/\/dashdrum.com\/blog\/?p=433"},"modified":"2013-02-15T11:08:38","modified_gmt":"2013-02-15T15:08:38","slug":"django-emptychoicefield","status":"publish","type":"post","link":"https:\/\/dashdrum.com\/blog\/2013\/02\/django-emptychoicefield\/","title":{"rendered":"Django EmptyChoiceField"},"content":{"rendered":"<p>On my current project, I was faced with an interesting problem. My form includes a ChoiceField that is not required. However, the Django ChoiceField doesn&#8217;t allow for no choice. What was happening instead was a de facto default to the first option in the choice list unless the user picked another value &#8211; no way to select nothing.<\/p>\n<p>A quick search turned up the EmptyChoiceField from Git user davidbgk &#8211; <a href=\"https:\/\/gist.github.com\/davidbgk\/651080\">https:\/\/gist.github.com\/davidbgk\/651080<\/a>, and it worked very well. In my form, I used the field type thusly:<\/p>\n<pre><code>suitability = EmptyChoiceField(required=False,empty_label=u\"---------\",choices=Suitability)\n<\/code><\/pre>\n<p>In David&#8217;s code, the empty label choice is prepended to the list when the field is not required and the empty_label parameter has a value. However, I wanted to see if I could make the EmptyChoiceField work more like the ModelChoiceField.<\/p>\n<ol>\n<li>The empty_label parameter defaults to <code>u\"---------<\/code><\/li>\n<li>A required field has the empty field choice prepended to the list, unless an initial value is provided.<\/li>\n<li>When the field is not required, the empty field choice is always included, regardless of whether an initial value exists.<\/li>\n<\/ol>\n<p>Here is my version of the field &#8211; <a href=\"https:\/\/gist.github.com\/dashdrum\/4960474\">https:\/\/gist.github.com\/dashdrum\/4960474<\/a>:<\/p>\n<pre><code>from django.forms import ChoiceField\n\n''' Based on https:\/\/gist.github.com\/davidbgk\/651080 \n    modified to mirror the functionality of ModelChoiceField '''\n\nclass EmptyChoiceField(ChoiceField):\n    def __init__(self, choices=(), empty_label=u\"---------\", required=True, widget=None, label=None,\n                       initial=None, help_text=None, *args, **kwargs):\n\n        # prepend an empty label unless the field is required AND\n        # an initial value is supplied\n\n        if required and (initial is not None):\n            pass # don't prepend the empty label\n        else:\n            choices = tuple([(u'', empty_label)] + list(choices))\n\n        super(EmptyChoiceField, self).__init__(choices=choices, required=required, widget=widget,\n                                               label=label, initial=initial, help_text=help_text,  \n                                               *args, **kwargs)\n<\/code><\/pre>\n<p>My invocation of the field only changes in that I no longer need to specify a label text:<\/p>\n<pre><code>suitability = EmptyChoiceField(required=False,choices=Suitability)\n<\/code><\/pre>\n<p>By changing the default value of the empty&#95;label, I have broken backward compatibility, although I have a tough time seeing a reason to use this field with the empty&#95;label set to None on purpose. I&#8217;ll probably send a pull request back to the original author, but I will note that he may not want to merge it.<\/p>\n<p>Hope this post helps someone else faced with a similar dilemma.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>On my current project, I was faced with an interesting problem. My form includes a ChoiceField that is not required. However, the Django ChoiceField doesn&#8217;t allow for no choice. What was happening instead was a de facto default to the first option in the choice list unless the user picked another value &#8211; no way &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/dashdrum.com\/blog\/2013\/02\/django-emptychoicefield\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Django EmptyChoiceField&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-433","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/433","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/comments?post=433"}],"version-history":[{"count":3,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/433\/revisions"}],"predecessor-version":[{"id":436,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/433\/revisions\/436"}],"wp:attachment":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/media?parent=433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/categories?post=433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/tags?post=433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}