18

On Django 1.2.1 I'm using ModelForm and generating a form with radiobuttons:

class myModelForm(ModelForm):    
    class Meta:
        model = myModel
        widgets = {
            'choose': RadioSelect(),
        } 


This generates an extra input with bogus value:

<li><input type="radio" id="id_choose_0" value="" name="choose1" /> ---------</li>
<li><input type="radio" id="id_choose_1" value="1" name="choose1" /> First choice</li>


I understand that I can get rid of the auto-generated empty input field by setting a default:

myChoices = (
    ("1", "First choice"),("2", "Second choice"),("3", "Third choice"),
)    

class myModel(models.Model):
    choose = models.CharField(max_length=1, choices=myChoices, default=1...


So in this case the first choice is selected:

<li><input checked="checked" type="radio" id="id_choose_1" value="1" name="choose1" /> First choice</li>
<li><input type="radio" id="id_choose_2" value="2" name="choose2" /> Second choice</li>

But how do I render my form without a checked input attribute?

(and without the auto-generated one)

amoeba
  • 571
  • 4
  • 13

3 Answers3

17

This is kind of a hacky solution, but I've tested it to work: simply set the default for the field to a value that isn't one of the choices (I recommend setting it to None). When rendering the form, Django won't know which input to mark as checked, so it will leave all of them unchecked (without throwing an error). And the fact that there is a default means there will be no auto-generated input field.

Aram Dulyan
  • 2,386
  • 17
  • 13
  • 1
    It works and I don't think it's especially hacky, unless someone else comes with a more insight solution (since I find documentation lacking in this area) I will mark this as the correct answer. Thanks – amoeba Jul 17 '10 at 16:08
12

In Django 1.6 (didn't test it in other versions) all you need is default=None:

class myModel(models.Model):
    choose = models.CharField(..., default=None)

class myModelForm(ModelForm):
    class Meta:
        model = myModel
        widgets = {
            'choose': RadioSelect(),
        }
allcaps
  • 10,945
  • 1
  • 33
  • 54
  • This works in 1.6.2 but if you also pass `blank=True` as an argument on `forms.RadioSelect` it will leave the default option "-------" in place even if you use `default=None`. You have to remove `blank=True` – Deepend May 13 '15 at 11:39
  • 1
    @Deepend `blank=True` is a core **model** field argument. The forms equivalent is `required=False`. But that is weird on a RadioSelect since the user can't deselect radiobuttons. Anyway, blank isn't a form thing. If you create a modelform than blank=True in the model becomes required=False in the form. You can set required=True on the modelform field without touching blank=True in the model by redefining the field in the modelform. https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/ – allcaps May 13 '15 at 21:18
4

The previous solution wouldn't work for me.

Therefore I just slice out the first widget's choice.

class myModelForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.fields['choose'].choices = self.fields['choose'].choices[1:]

    class Meta:
        model = myModel
        widgets = {
            'choose': RadioSelect(),
        } 
vinyll
  • 11,017
  • 2
  • 48
  • 37
  • For `ModelChoiceField` you can use this `self.fields['choose'].choices = [(c.id, c.field_name_to_display) for c in self.fields['choose'].queryset]` – Mark Mishyn Jun 13 '17 at 18:27