Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django multiple form factory

What is the best way to deal with multiple forms? I want to combine several forms into one. For example, I want to combine ImangeFormSet and EntryForm into one form:

class ImageForm(forms.Form):
    image = forms.ImageField()
ImageFormSet = formset_factory(ImageForm)

class EntryForm(forms.Form):
    title = forms.CharField(max_length=100)

result_form = combine(EntryForm, ImageFormSet) # here it goes

I found 2 years old presentation introducing multipleform_factory() method, but I am not sure that it's the best way: http://www.slideshare.net/kingkilr/forms-getting-your-moneys-worth

like image 486
Vladimir Mihailenco Avatar asked Aug 31 '10 19:08

Vladimir Mihailenco


2 Answers

An idea (not checked if it works):

class MySuperForm(CombinedForm):
    includes = (ImageForm, EntryForm, )

You see here how the form is built. You can make your own Form by extending from BaseForm and supplying another __metaclass__.

class CombinedForm(BaseForm):
  __metaclass__ = DeclarativeFieldsMetaclassFromMultipleClasses

In DeclarativeFieldsMetaclassFromMultipleClasses you do basically the same as here, except you sum up the declared fields from the classes on

class DeclarativeFieldsMetaclassFromMultipleClasses(type):
  def __new__(cls, name, bases, attrs):
    for clazz in attrs['includes']:
      attrs['base_fields'] += get_declared_fields(bases, clazz.attrs)
    new_class = super(DeclarativeFieldsMetaclassFromMultipleClasses,cls).__new__(cls, name, bases, attrs)
    if 'media' not in attrs:
      new_class.media = media_property(new_class)
    return new_class
like image 177
Andre Bossard Avatar answered Oct 04 '22 15:10

Andre Bossard


It doesn't matter how many forms are placed in template, because individual forms don't render form tag. So, your template goes like this

<form id='xxxx' action='' method=POST>  
  {{my_first_formset}}  
  {{my_second_form}}  
</form>  

and in view.py

my_formset = MyFormset(request.POST)  
my_form = MyForm(request.POST)  
if my_formset.is_valid() and my_form.is_valid():  
   process...
like image 21
Narendra Kamma Avatar answered Oct 04 '22 17:10

Narendra Kamma