2

I think what I need to do is really the opposite of an inlineformset.

Say I have:

from django.db import models
class Type(models.Model):
    description = models.CharField(max_length=50)
    status = models.ForeignKey(Status)
    def __unicode__(self):
        return self.description

class ColorType(models.Model):
    type = models.ForeignKey(Type)
    color = models.ForeignKey('Color')
    status = models.ForeignKey(Status)
    def __unicode__(self):
        return u'%s %s' % (self.type, self.color)

class Color(models.Model):
    description = models.CharField(max_length=50)
    status = models.ForeignKey(Status)
    types = models.ManyToManyField(type, through=ColorType)
    def __unicode__(self):
        return self.description

class Chair(models.Model):
    description = models.CharField(max_length=50)
    status = models.ForeignKey(Status)
    colorType = models.ForeignKey(ColorType)

Now I need a form to edit a chair in which I enter Color and Type separatedly (Like showing a modelformset of ColorType). If the combination doesn't exist the application has to create the necessary instance of ColorType (and assigning it a desfault status) and assign it to the chair.

I think the whole situation is common, I should be missing something...

2 Answers 2

1

I did my search and, sadly, it's not currently possible to have more than one model per form using only Django. This being said, you are not the only one who wanted to do that.

  • There's a SO answer here which make good suggestions.
  • If you still want to to it, you can roll your own using something like this, but a little different because this version accepts one form or the other, not both at once.
  • If you don't want to code it yourself, django-multiform is a Django library that offers a generic way to do what you want. Of course, you would need to change the save method to apply for your use-case (ColorType combination, etc.)
Sign up to request clarification or add additional context in comments.

Comments

1

I will post my own solution. Finally I did the trick just by using the InlineFormsets.

In forms.py:

class ChairForm(forms.ModelForm):
    class Meta:
        model = Chair
        exclude = ('colorType')

class ColorTypeForm(forms.ModelForm):
    class Meta:
        model = ColorType
        exclude = ('status')

In views.py:

def ChairUpdate(request, chair_id):
    chair = get_object_or_404(Chair, pk=chair_id)

    form = ChairForm(instance=chair)
    ColorTypeInlineFormset = inlineformset_factory(ColorType, Chair, formset=ColorTypeForm)

    if request.method == 'POST':
        form = ChairForm(request.POST, instance=chair)
        if form.is_valid():
            chair = form.save(commit=False)
            colorTypeInlineFormset = ColorTypeInlineFormset(request.POST,)
            # colorTypeInlineFormset.is_valid()

            color = Color.objects.get(id=request.POST['color'])
            type = Type.objects.get(id=request.POST['type'])

            ct,created = ColorType.objects.get_or_create(color=color,type=type,defaults={'status':Status.objects.get(id=1)})
            chair.colorType = ct

            # marcaModeloInlineFormset.save(commit=False)
            arma.save()
            return HttpResponseRedirect(reverse('success_page'))

    colorTypeInlineFormset = ColorTypeInlineFormset(instance=chair.colorType)


    return render(request, "chair_form.html", {
        'chair': chair,
        'form': form,
        'colorType_formset': colorTypeInlineFormset,
        'action': "Update"
    })

Comments

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.