Hamfri
Hamfri

Reputation: 2219

Dynamically update ModelForm's Meta class fields using views

I am trying to create a dynamic form after checking some condition in the view and i am not sure how to approach it. How do i populate the fields attribute in the forms Meta class from my views?

Below are my views.py and my forms.py files.

views.py

How do i populate the fields list in forms.py from my views?

    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponse
    from django import forms

    from .models import Master, Label, Assosiative
    from .forms import LabelForm, MzasterForm, AssosiativeForm

    def master(request,pk):
        associate = get_object_or_404(Assosiative, pk=pk)
        form = MasterForm(request.POST or None)
        if associate.short_text1 == 1:
            form.fields['short_text1'] = forms.CharField(label='Short text 1')
        if associate.short_text2 == 1:
            form.fields['short_text2'] = forms.CharField(label='Short text 2')
        if associate.short_text3 == 1:
            form.fields['short_text3'] = forms.CharField(label='Short text 3')
        if associate.short_text4 == 1:
            form.fields['short_text4'] = forms.CharField(label='Short text 4')
        if associate.num_field1 == 1:
            form.fields['num_field1'] = forms.CharField(label='Number field 1')
        if associate.num_field2 == 1:
            form.fields['num_field2'] = forms.CharField(label='Number field 2')
        if form.is_valid():
            try:
                short_text1 = form.cleaned_data['short_text1']
                short_text2 = form.cleaned_data['short_text2']
                short_text3 = form.cleaned_data['short_text3']
                short_text4 = form.cleaned_data['short_text4']
                num_field1 = form.cleaned_data['num_field1']
                num_field2 = form.cleaned_data['num_field2']
                form.save()
            except Exception, ex:
        return HttpResponse("Error %s" %str(ex))
        return render(request, 'master.html', {'form':form,}) 

forms.py

I am not sure what to do here so that i can populate the fields from my views

    def masterForm(fields_list, *args, **kwargs):
        class MasterForm(forms.ModelForm):
            class Meta:
                model = Master
                fields = fields_list
            def __init__(self):
                super(MasterForm, self).__init__(*args, **kwargs)
         return MasterForm()
    joke = masterForm(('short_text1',))

Upvotes: 0

Views: 1876

Answers (2)

Hamfri
Hamfri

Reputation: 2219

To create form dynamically after checking some condition

views.py

    def master(request, pk):
        associate = get_object_or_404(Assosiative, pk=pk)
        MasterForm = get_form_class(associate)
        form = MasterForm(request.POST or None)
        if form.is_valid():
            form.save()
            messages.add_message(request, messages.INFO, 'Your Form has been posted successfully')
            return HttpResponseRedirect('/')
        return render(request, 'master.html', locals())

Dynamically add form fields to the fields list class Meta in forms.py

    def get_form_class(associate, *args, **kwargs):
        class MasterForm(forms.ModelForm):
            def __init__(self, *args, **kwargs):
                super(MasterForm,self).__init__(*args, **kwargs)
            class Meta:
                model = Master
                fields = [] #initialize an empty fields list
                # Append items to the fields list after checking some condition
                if associate.short_text1 == 1:
                    fields.append('short_text1')
                if associate.short_text2 == 1:
                    fields.append('short_text2')
                if associate.short_text3 == 1:
                    fields.append('short_text3')
                if associate.short_text4 == 1:
                    fields.append('short_text4')
                if associate.num_field1 == 1:
                    fields.append('num_field1')
                if associate.num_field2 == 1:
                    fields.append('num_field2')            
         return MasterForm

Upvotes: 0

Alasdair
Alasdair

Reputation: 308809

As in this question, you can define a method that creates the form class. Looking at your view, you seem to be creating fields one by one based on associate, instead of creating a list of fields. Therefore, I would use associate as an argument to your get_form_class method.

def get_form_class(fields_list):
    class MasterForm(ModelForm):
        class Meta:
            model = Master
            fields = fields_list
        ...
    return MasterForm

Then, in your view, use the get_form to create the form class dynamically, then instantiate it.

def master(request, pk):
    associate = get_object_or_404(Assosiative, pk=pk)
    fields_list = []
    if associate.short_text1 == 1:
        fields_list.append('short_text1')
    if associate.short_text2 == 1:
        fields_list.append('short_text2')
    MasterForm = get_form_class(fields_list)
    form = MasterForm(request.POST or None)
    if form.is_valid():
        ...

Upvotes: 2

Related Questions