简体   繁体   中英

Django formset with manytomany through intermediate model

I want to save data to an intermediary model and do some calculations in the model (by overriding model save). The problem I have is with formsets not able to save to the intermediary model.

The intermediary model is created only when there is M2M relationship (that's understood I guess).

I have 4 models like so:

Category(models.Model):
    name = models.CharField(..)

Tax(models.Model):
   name = models.CharField(..)
   rate = models.DecimalField(..)

CategoryItem(models.Model):
    category = models.ForeignKey(Category)
    taxes = models.ManyToManyField(Tax, through='CategoryItemTax', through_fields=('item', 'tax'))
    quantity = models.DecimalField(..)
    price = models.DecimalField(..)

# intermediary model below
CategoryItemTax(models.Model):
    category = models.ForeignKey(Category)
    tax = models.ForeignKey(Tax)
    item = models.ForeignKey(CategoryItem)
    rate = models.DecimalField(..) #derived from tax object in the model
    total_tax = models.DecimalField(..) #calculated in model save

My I have a Category model form with CategoryItem formset. My views.py as below:

class FormsetMixin(object):
    object = None

    def post(self, request, *args, **kwargs):
        if getattr(self, 'is_update_view', False):
            self.object = self.get_object()
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        formset_class = self.get_formset_class()
        formset = self.get_formset(formset_class)
        if form.is_valid() and formset.is_valid():
            return self.form_valid(form, formset)
        else:
            return self.form_invalid(form, formset)

    # THE SAVE METHOD
    def form_valid(self, form, formset):
        self.object = form.save()
        formset.instance = self.object
        instances = formset.save(commit=False)
        for i in instances:
            CategoryItemTax.objects.create(category=self.object, item=i, tax=i)
            CategoryItemTax.save()

class CategoryCreateView(FormsetMixin, CreateView):
    template_name='..'
    model = Category
    form_class = CategoryForm
    formset_class = CategoryItemFormSet

Forms.py as below

class CategoryForm(forms.ModelForm):

    class Meta:
        model = Category

class CategoryItemForm(forms.ModelForm)
    class Meta:
        model = CategoryItem

CategoryItemFormSet = inlineformset_factory(Category, CategoryItem, form=CategoryItemForm, extra=1)

Unfortunately I get the below error:

Cannot set values on a ManyToManyField which specifies an intermediary model.
Use category.CategoryItemTax's Manager instead

Edit your view like this,

def form_valid(self, form, formset):
    self.object = form.save()
    formset.instance = self.object
    instances = formset.save(commit=False) 
    for each in instances:
        each.category = self.object
        each.save()
        item = CategoryItemTax.objects.create(category=self.object, item=each)
        item.save()

Many to many related objects must be saved first inorder to associate with another instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM