views:

1531

answers:

2

I'm currently have an issue, and likely overlooking something very trivial. I have a field in my model that should allow for multiple choices via a checkbox form (it doesn't have to be a checkbox in the admin screen, just in the form area that the end-user will see). Currently I have the field setup like so:

# Type of Media
MEDIA_CHOICES = (
    ('1', 'Magazine'),
    ('2', 'Radio Station'),
    ('3', 'Journal'),
    ('4', 'TV Station'),
    ('5', 'Newspaper'),
    ('6', 'Website'),
)
media_choice = models.CharField(max_length=25,
    choices=MEDIA_CHOICES)

I need to take that and make a checkbox selectable field in a form out of it though. When I create a ModelForm, it wants to do a drop down box. So I naturally overrode that field, and I get my checkbox that I want. However, when the form's submitted, it would appear that nothing useful is saved when I look at the admin screen. The database does however show that I have a number of things selected, which is a positive sign. However, how can I get that to reflect in the admin screen properly?

Edit: FWIW I'll gladly accept documentation links as answers, because it would seem I'm just glossing over something obvious.

+6  A: 

In such a case, the easiest way is to put the choices into a separate model and then use a ManyToMany relationship. After that, you simply override the ModelForm's widget for that field to use forms.CheckboxSelectMultiple and Django will automatically do the right thing. If you insist to use a CharField, you'll probably have to do something like this snippet.

@ 2. comment: how are you overriding the widget? This is how I do it and it works flawlessly:

class SomeModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(SomeModelForm, self).__init__(*args, **kwargs)
        self.fields['some_field'].widget = forms.CheckboxSelectMultiple()
piquadrat
Thanks for the tip. Didn't want to use ManyToMany because I'd be creating about 6 models for information that will always be static. Seemed unnecessary.
f4nt
Also, fwiw, that doesn't seem to work. The field renders blank when I use CheckBoxSelectMultiple form. If I use MultipleChoiceField, with the Checkbox widget that sorta works, but only if I supply the form with a list of choices. Then I have to go mapping data back with overriden clean function. Maybe that's the correct way, but it "feels" wrong, and typically when something "feels" wrong, it is. Just trying to verify I'm not overdoing it here.
f4nt
Well I wasn't doing it right, so thanks for setting me straight there, however now I have this:in Models.py:media_type = models.ManyToManyField(MediaChoice)in Forms.py: def __init__(self, *args, **kwargs): super(MediaContactForm, self).__init__(*args, **kwargs) self.fields['media_type'].widget = forms.CheckboxSelectMultiple()
f4nt
gah.. formatting got hosed...
f4nt
well I can see the choices showing up properly if I dump out the contents of the form. There must be something wrong in my templates I guess. Certain widgets show fine, but this one doesn't. Not sure why yet.
f4nt
How do you render the form? Have you tried something like this? <table>{{ form.as_table }}</table>
piquadrat
The HTML of the form is rather customized, so I have to output each field individually. The odd part is that if I don't override it, it works fine. I override it, and it doesn't render, but the choices *are* there.
f4nt
Got it! Thank you soooooo much for your help. Formatting is gunna hose it, but here's the fix:self.fields['media_type'].widget = forms.CheckboxSelectMultiple(choices=self.fields['media_type'].choices)
f4nt
A: 

I've just started to look into widgets assignment with ModelForms. In a lot of examples I've seen, piquadrat's included, the Form's __ init __ method is overridden.

I find this a little confusing, and just overriding the desired field is more natural for me:

class SomeModelForm(forms.ModelForm):
    some_field = forms.CharField(choices=MEDIA_CHOICES,
                                 widget=forms.CheckboxSelectMultiple)
    class Meta:
        model=SomeModel

Note: I'm using Django 1.1.

monkut