views:

41

answers:

1

I have a multiple ModelForm classes that each represent a different Model. I would like to have a generic 'create' function that loads the specified model form based on a URL parameter. It is possible to load a model dynamically with this:

model_name = 'TestModel'
m = get_model('AppLabel', model_name)

Does anyone know how I can achieve the same for ModelForms, something like:

modelform_name = 'TestModelForm'
f = get_form('AppLabel', modelform_name)
if f.is_valid():
    ...

I can not think of a way to do this with generic views - they require the ModelForm to be passed, rather than just its name. If I get the model with get_model then pass that to the generic view it will display a form but I am unable to exclude model fields.

TIA for any tips

A: 

When you create a ModelForm it does not register itself with its model's app. (Based on experience and a quick browse through the source).

Here are some otheroptions I can think of:

  1. All ModelForm classes exist in a single module: Use getattr on that module based on the string.

  2. ModelForm's are spread out among many models and you have a reasonable (<30) amount of forms: Create a dictionary mapping from form strings you expect to ModelForm classes. For example:

    from some_app.forms import FirstModelForm
    from another_app.forms import SecondModelForm
    from additional_app.forms import FirstModelForm as AdditionalAppFirstModelForm # Will allow for managing conflicting names easily.
    
    
    form_mapping = {
        'FirstModelForm': FirstModelForm,
        'SecondModelForm': SecondForm,
        'AdditionalAppFirstModelForm': AdditionalAppFirstModelForm,
    }
    
    
    request_form_class = request.POST.get('form_class')
    f = form_mapping.get(request_form_class)(request.POST)
    
    
    if f.is_valid():
        f.save()
    
  3. You're dealing with a lot of forms: Create a baseclass for your ModelForm, or replace the BaseModelFormMetaclass at runtime. You'll have to deal with issues such as name conflicts, duplicate ModelForms for the same Model "automagically", so prepare for some headaches. It would be pretty rad if you could pull it off.

Personally (as you can probably see), I'd just go with option #2.

sdolan
Fantastic answer, option #2 works perfectly. Thank you!
Mike
@Mike: You're very welcome. Remember from the "Zen of Python" (`import this`): "Explicit is better than implicit.". The #3 would be a require way to much "voodoo" to be considered close to explicit. Also, be sure to add some error checking when you get the form class and raise the appropriate `Http404`. It'll save you some headaches in the future.
sdolan