8

How do I create fields in ModelForm on the go?

For example, I want to create 3 textboxes (because there are 3 entries in the database table)

 ID  Name   Value 
------------------
 1   Alpha  10   
 2   Beta   91    
 3   Char   800  

How do I display it in this way to the user? Does it involve the _init definition? Is it possible to do a for loop of objects in your model form class to retrieve its values and convert them to a field to be displayed? Appreciate any suggestions.

Alpha 

[textbox]
______
Beta

[textbox]

____

etc..

[Submit]

Here is what I tried to do in the def init of the modelform:

self.fields['myfield'].widget = forms.Textarea()

Can't seem to give me the output, do mind my weak understanding of certain django concepts.

3 Answers 3

18

I think that your best bet is, in this case, to stick to Model formsets. For any other case, you can just append new fields to the fields attribute, inside your form's __init__.

def __init__(self, *args, *kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields.update({
        'foo': forms.CharField(widget=forms.Textarea()),
        'bar': forms.CharField(widget=forms.Textarea()),
    })

Remember that, in this case, you have to call the parent's __init__ first, so you'll have the .fields available.

Sign up to request clarification or add additional context in comments.

1 Comment

Formsets are the simple answer here.
7

You can also dynamically define form fields using the django.forms.models.ModelFormMetaclass (used by django.forms.models.modelform_factory). This will create a ModelForm class using the fields you specify rather than updating the fields 'on the fly' in the init.

from django import forms
from django.forms.models import ModelForm, ModelFormMetaclass


model = MyModel
fields = {
    'myfield': forms.CharField(widget=forms.Textarea())
}

meta_attrs = {
    'model': model,
}

Meta = type('Meta', (object, ), meta_attrs)

form_class_attrs = {
    'Meta': Meta, 
}

form_class_attrs.update(fields)

MyModelForm = ModelFormMetaclass('MyModelForm', (ModelForm, ), form_class_attrs)

Comments

3

Yes you want to override the __init__, something like:

def __init__(self, *args, **kwargs):
    super(MyModelForm, self).__init__(*args, **kwargs)
    for foo, bar in jelly:
        self.fields[foo] = forms.CharField(widget=forms.Textarea())

See lots more info here - it all pretty much applies to ModelForm as well.

1 Comment

You can add queryset to the forms.CharField to get retrieve the values from database dynamically

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.