'saving data into two tables at the same time with a single form

I would like to save data in two tables at the same time using a single form in Django. Any help would be appreciated.

class Category(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    def __str__(self):
        return self.name

class Stock(models.Model):
   id = models.AutoField(primary_key=True)
   category = models.ForeignKey(Category, on_delete=models.CASCADE,blank=True)
   item_name = models.CharField(max_length=100, blank=True, null=True)
   quantity = models.IntegerField(default='0',blank=True, null=True)

class StockHistory(models.Model):
   id = models.AutoField(primary_key=True)
   category = models.ForeignKey(Category, on_delete=models.CASCADE,blank=True)
   item_name = models.CharField(max_length=100, blank=True, null=True)
   quantity = models.IntegerField(default='0',blank=True, null=True)


Solution 1:[1]

You can use two forms in a single view. It is not advised to save two different objects in a single modelform as it will get difficult to maintain and scale. What you can do is create two different form and then in your template, load both the form inside a single <form> tag. Then inside your view you can check for the validity of both the forms and respond accordingly.

You can refer here for more explanation.

Edit: in forms.py

class StockForm(forms.ModelForm):
    class Meta:
        fields = ['item_name', 'category', 'quantity']

class StockHistoryForm(forms.ModelForm):
    class Meta:
        fields = ['item_name', 'category', 'quantity']

in views.py

def your_view(request):
    stock_form = StockForm()
    if request.method == 'POST':
        stock_form = StockForm(request.POST)
        stock_history_form = StockHistoryForm(request.POST) #corrected here
        if stock_form.is_valid() and stock_history_form.is_valid():
            stock_form.save()
            stock_form_history.save()
            return HttpResponse("Saved")
    return render(request, 'your_html.html', {'form': stock_form})

Now you can render the form inside your template, and it will save both the objects with the same data. If you need only the item_name field is same for the form then you can do this

in forms.py

class StockForm(forms.ModelForm):
    class Meta:
        fields = ['item_name', 'category', 'quantity']

class StockHistoryForm(forms.ModelForm):
    class Meta:
        fields = ['category', 'quantity'] //remove item_name from fields

in views.py

def your_view(request):
    stock_form = StockForm()
    stock_history_form = StockHistoryForm() //added this
    if request.method == 'POST':
        stock_form = StockForm(request.POST)
        stock_history_form == StockHistoryForm(request.POST)
        if stock_form.is_valid() and stock_history_form.is_valid():
            stock = stock_form.save() //changes here
            stock_form_history.save(item_name=stock.item_name) //changes here
            return HttpResponse("Saved")
    return render(request, 'your_html.html', {'stock_form': stock_form, 'stock_history_form':stock_history_form}) //changes here

Then inside your HTML you can load both the forms under the same <form> tag.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 abhishek