views:

52

answers:

1

I have a factory method that generates django form classes like so:

def get_indicator_form(indicator, patient):
    class IndicatorForm(forms.Form):
        #These don't work!
        indicator_id = forms.IntegerField(initial=indicator.id, widget=forms.HiddenInput())
        patient_id = forms.IntegerField(initial=patient.id, widget=forms.HiddenInput())

        def __init__(self, *args, **kwargs):
            forms.Form.__init__(self, *args, **kwargs)
            self.indicator = indicator
            self.patient = patient

    #These do!
    setattr(IndicatorForm, 'indicator_id',  forms.IntegerField(initial=indicator.id, widget=forms.HiddenInput()))
    setattr(IndicatorForm, 'patient_id', forms.IntegerField(initial=patient.id, widget=forms.HiddenInput()))

    for field in indicator.indicatorfield_set.all():
        setattr(IndicatorForm, field.name, copy(field.get_field_type()))

    return type('IndicatorForm', (forms.Form,), dict(IndicatorForm.__dict__))

I'm trying to understand why the top form field declarations don't work, but the setattr method below does work. I'm fairly new to python, so I suspect it's some language feature that I'm misunderstanding. Can you help me understand why the field declarations at the top of the class don't add the fields to the class?

In a possibly related note, when these classes are instantiated, instance.media returns nothing even though some fields have widgets with associated media.

Thanks, Pete

+1  A: 

Try this:

def get_indicator_form(indicator, patient):
    class IndicatorForm(forms.Form):
        indicator_id = forms.IntegerField(initial=indicator.id, widget=forms.HiddenInput())
        patient_id = forms.IntegerField(initial=patient.id, widget=forms.HiddenInput())

        def __init__(self, *args, **kwargs):
            forms.Form.__init__(self, *args, **kwargs)
            self.indicator = indicator
            self.patient = patient

    for field in indicator.indicatorfield_set.all():
        IndicatorForm.base_fields[field.name] = field.get_field_type()

    return IndicatorForm
SmileyChris
Thanks, this worked. As Chris explained to me in IRC, It has to do with the DeclaritiveFieldsMetaClass of the forms.Form class eating up the fields in my original code before they were converted to dict.
slypete