Tuesday, January 24, 2017

Re: Multiple forms in the same template

HI
sorry I wanted to shorten the code before, to not post too much.
Here the code:

views.py
class MFormsView(LoginRequiredMixin, StaffuserRequiredMixin, UpdateView, MFView):

    template_name
= 'temps/cnfg_form.html'
    form_classes
= {
       
'abc': abcForm,
       
'md': mdForm,
   
}

    breadcrumbs
= ['cnfg_ovw']

   
def get_initial(self):
       
return {'pk': self.kwargs['pk']}

   
def get_success_url(self):
       
return reverse('cnfg_ovw')

   
def post(self, request, *args, **kwargs):
       
return super(MFormsView, self).post(request, *args, **kwargs)


   
def get(self, request, *args, **kwargs):

       
return super(MFormsView, self).get(request, *args, **kwargs)

   
def forms_valid(self, form):
       
if 'save' in self.request.POST.keys():
            change_settings
(form=form, **self.kwargs)
           
return HttpResponseRedirect(self.get_success_url())

       
elif 'reset_to_default' in self.request.POST.keys():
            reset_to_default
(form=form, **self.kwargs)
           
return HttpResponseRedirect(reverse('updt_cnfg', kwargs={'pk': self.kwargs['pk']}))

   
def get_object(self, queryset=None):
       
self.object = ConfigSetting.objects.all().filter(config__settings__pk=self.kwargs['pk']).get()
       
return self.object

   
def get_queryset(self):
       
self.queryset = ConfigSetting.objects.all().filter(config__settings__pk=self.kwargs['pk'])
       
return self.queryset

   
def get_context_data(self, **kwargs):
        context
= super(MFormsView, self).get_context_data(**kwargs)
       
if self.object.label not in ['default']:
            context
['label'] = "custom config"
       
else:
            context
['label'] = self.object.label

       
return context


mfview
.py
from django.views.generic.base import View, TemplateResponseMixin
from django.views.generic.edit import FormMixin, ProcessFormView


class MFMixin(FormMixin):
    form_classes
= {}

   
def get_form_classes(self):
       
return self.form_classes

   
def get_forms(self, form_classes):
       
return dict([(key, klass(**self.get_form_kwargs())) \
           
for key, klass in form_classes.items()])

   
def forms_valid(self, forms):
       
return super(MFMixin, self).form_valid(forms)

   
def forms_invalid(self, forms):
       
return self.render_to_response(self.get_context_data(forms=forms))


class ProcesMFView(ProcessFormView):

   
def get(self, request, *args, **kwargs):
        form_classes
= self.get_form_classes()
        forms
= self.get_forms(form_classes)
       
return self.render_to_response(self.get_context_data(forms=forms))


   
def post(self, request, *args, **kwargs):

        form_classes
= self.get_form_classes()
        forms
= self.get_forms(form_classes)

       
if all([form.is_valid() for form in forms.values()]):
           
return self.forms_valid(forms)
       
else:
           
return self.forms_invalid(forms)

class BaseMFView(MFMixin, ProcesMFView):

class MFView(TemplateResponseMixin, BaseMFView):



forms
.py
class abcForm(ModelForm):
   
def __init__(self, *arg, **kwargs):
       
super(abcForm, self).__init__(*arg, **kwargs)
        c
= model_to_dict(self.instance.abc_setting)
       
for k, v in self.fields.items():
            setattr
(v, 'initial', c[k])
           
           
if k in ['c']:
                setattr
(v, 'label', "Active settings")
           
       
self.prefix = "abc"

   
class Meta:
        model
= abcSetting
        fields
= ['a', 'b', 'c', 'f',]



class mdForm(ModelForm):
   
def __init__(self, *arg, **kwargs):
       
super(mdForm, self).__init__(*arg, **kwargs)
        c
= model_to_dict(self.instance.md_setting)
       
for k, v in self.fields.items():
            setattr
(v, 'initial', c[k])
           
       
self.prefix = "md"

   
class Meta:
        model
= mdSetting
        fields
= ['k', 'r',]


In the template it is then used like:
<div class="col-md-3">{{ forms.abc.f }}</div>

As you can see in the ProcesMFView.get, the get_context_data gets the dictionary form_classes:

form_classes = {
        'abc': abcForm,
        'md': mdForm,
    }

It seems that the Django code is then not able to get the fields and runs into this error.

Thanks for any hints.
schaf


Am Dienstag, 24. Januar 2017 12:12:50 UTC+1 schrieb Melvyn Sopacua:

Hello,

 

Assuming the fields issue is resolved. If not, please show the abcForm.

 

On Monday 23 January 2017 08:14:09 scha...@gmail.com wrote:

 

> I guess I first need to fully understand the Django ModelForm and how

> a template can handle two independent forms. Maybe I also have to

> change the concept?

> data from different models have to be displayed on one template and

> for that 2 ModelForms were generated and added to a main view, but

> this does notwork in 1.9 till now.

 

The generic class-based views support common patterns, but in a way that more complex patterns can be built. Yours is a more complex pattern.

The defaults always assume a one on one relation between a ListView/DetailView and a Model and also one Form with one FormView.

 

Under the hood, Model forms are handled like this:

* add the form instance to the template context (using get_context_data) so it can be rendered

* deligate to form_valid or form_invalid based on the form's is_valid() method, if the request method is put or post (using ProcessFormView post and put)

* call save() on the ModelForm to save the object(s) (using form_valid)

 

What I'm not seeing in your code is how ModelFormMixin ties in. I'm going to guess that ProcessFormView is not the ProcessFormView from django.views.generic.edit.

Could you run the django shell (python manage.py shell) import the view and show it's MRO? For example:

>>> from kernel.views import ModelJSONEncoder

>>> ModelJSONEncoder.__mro__

(<class 'kernel.views.ModelJSONEncoder'>, <class 'django.core.serializers.json.DjangoJSONEncoder'>, <class 'json.encoder.JSONEncoder'>, <class 'object'>)

 

--

Melvyn Sopacua

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/763a8eb3-0ce5-4ddd-8e6a-318a75b475c9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment