0

I am trying to add validation to my Django forms.

I want to require at least one child model for my inlineformset.

I am using the following as a reference: Inline Form Validation in Django

I am still getting an error

line 454, in formset_factory return type(form.name + str('FormSet'), (formset,), attrs) TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

from django.forms import inlineformset_factory
from .models import *
from django.forms.models import BaseInlineFormSet
from django import forms
class PropertyForm(forms.ModelForm):
    class Meta:
        model = Property
        exclude = ()


class UnitForm(forms.ModelForm):
    class Meta:
        model = Unit
        exclude = ()

class CustomUnitFormset(BaseInlineFormSet):
    def is_valid(self):
        return super(CustomUnitFormset, self).is_valid() and \
               not any([bool(e) for e in self.errors])

    def clean(self):
        # get forms that actually have valid data
        count = 0
        for form in self.forms:
            try:
                if form.cleaned_data and not form.cleaned_data.get('DELETE', False):
                    count += 1
            except AttributeError:
                pass
        if count < 1:
            raise forms.ValidationError('You must have at least one unit')

UnitFormSet = inlineformset_factory(Property, Unit, form=PropertyForm,
                                    formset='CustomUnitFormset',
                                    extra=0,
                                    min_num=1,
                                    validate_min=True,
                                    validate_max=True,
                                    max_num=10,
                                    )

view.py

 class PropertyUnitCreate(LoginRequiredMixin, CreateView):
    model = Property
    fields = ['address']
    success_url = reverse_lazy('property-list')

    def get_context_data(self, **kwargs):
        data = super(PropertyUnitCreate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['units'] = UnitFormSet(self.request.POST)
        else:
            data['units'] = UnitFormSet()
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        units = context['units']
        form.instance.user = self.request.user
        with transaction.atomic():
            self.object = form.save()
            if units.is_valid():
                units.instance = self.object
                units.save()


        return super(PropertyUnitCreate, self).form_valid(form)

I have also tried to understand the inheritance issues explained here:Triple inheritance causes metaclass conflict... Sometimes

My view logic comes from https://medium.com/@adandan01/django-inline-formsets-example-mybook-420cc4b6225d

But I dont see where i have a class inheriting from two classes that would cause this error. Everything works fine if i remove the " formset='CustomUnitFormset', "

Can someone explain the reason for the error and how i could prevent this? Could i be managing my forms.py file better?

Tyberius
  • 34
  • 9

1 Answers1

0

You need to pass the actual formset class, not a string, to the factory.

UnitFormSet = inlineformset_factory(Property, Unit, form=PropertyForm,
                                    formset=CustomUnitFormset, ...)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895