Saving multiple models from one form in django

I am new to django and am trying to develop a web app for a farm management. My form i want to register a farm. i have three models, which are related and i want them to be save to the database from on function.

The model has three models as Phonenumbers, address and farm.
Model.py

from django.db import models
from django.contrib.auth.models import User
from datetime import datetime, date
class Farms(models.Model):
    farm_name = models.CharField(max_length=200, blank = True)
    recorded_by = models.ForeignKey(User, default= None, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return self.farm_name

COUNTRY_CHOICES = (
    ('Nig','Nigeria'),
    ('AF', 'Afghanistan'),
    ('AL' ,'Albania'),
    ('DZ' , 'Algeria'),
    ('AX' , 'Aland'),
    ('AS' , 'American'),
    ('AI' , 'Anguilla'),
    ( 'AD' , 'Andorra'),
    ('AO' , 'Angola'),
    ('AN' ,' Antilles - Netherlands'),
)
class Address(models.Model):

    street_name = models.CharField(max_length = 200, blank = True)
    street_no = models.CharField(max_length = 50, blank = True)
    city = models.CharField(max_length = 200)
    state = models.CharField(max_length = 200)
    country = models.CharField(max_length = 200, choices=COUNTRY_CHOICES, default='Nig')
    farms = models.ForeignKey(Farms, on_delete=models.CASCADE)

class Telephone(models.Model):
    phonenumber = models.CharField(max_length = 200)
    farms= models.ForeignKey(Farms, on_delete=models.CASCADE)

    def __str__(self):
        return self.phonenumber

Form.py
from django import forms
from .import models

class CreateFarmsForm(forms.ModelForm):
    class Meta:
        model = models.Farms
        fields = ['farm_name']

class TelephoneCreateForm(forms.ModelForm):
    class Meta:
        model = models.Telephone
        fields = ['phonenumber']
        labels = {
            'phonenumber': 'Phone Number'
        }

class AddressCreateForm(forms.ModelForm):
    class Meta:
        model = models.Address
        fields = ['street_name', 'street_no', 'city', 'state','country']
        labels = {
            'street_name': 'Street Name',
            'street_no': 'street No'
        }

class DateInput(forms.DateInput):
    input_type = "date"

    def __init__(self, **kwargs):
        kwargs["format"] = "%Y-%m-%d"
        super().__init__(**kwargs)

Farm.html
{% extends "livestock/livestock_base.html" %}
{% load crispy_forms_tags %}
 {% block livestock%}
                      <div class="card-body">
                             <div class="row">
                                 <div class="col-md-6 offset-3 ">
                          <form class="" action="" method="post">
                               {% csrf_token %}
                                  <div class="row">
                              <div class="form-group col-md-8 ">
                              {{farm_form.farm_name | as_crispy_field}}
                                  </div>
                              <div class="form-group col-md-4">
                                   {{phone_form.phonenumber | as_crispy_field}}
                                  </div>
                                      </div>
                              <div class="row">
                              <div class="form-group col-md-8 ">
                              {{address_form.street_name | as_crispy_field}}
                                  </div>
                                  <div class="form-group col-md-4 ">
                              {{address_form.street_no | as_crispy_field}}
                                  </div>
                                  </div>
                                <div class="row">
                              <div class="form-group col-md-6">
                              {{address_form.city | as_crispy_field}}
                                  </div>
                                    <div class="form-group col-md-6">
                              {{address_form.state | as_crispy_field}}
                                  </div>
                                  </div>
                              <div class="form-group ">
                              {{address_form.country | as_crispy_field}}
                                  </div>
                              <div class="form-group">
                                <button type="submit" class="btn btn-primary btn-block btn-sm" >Submit</button>
                                </div>
                          </form>
                                 </div>
                             </div>
                      </div>
{% endblock livestock%}

Views.py

def farm_name(request):
    if request.method == 'POST':
        farm_form = forms.CreateFarmsForm(request.POST)
        phone_form = forms.TelephoneCreateForm(request.POST)
        address_form = forms.AddressCreateForm(request.POST)
        if farm_form.is_valid and phone_form.is_valid and address_form.is_valid:
            farm=farm_form.save(commit=False)
            farm.recorded_by = request.user
       
            phone=phone_form.save(False)
            phone.farm = farm
            phone.save()
            address = address_form.save(False)
            address.farm = farm
            address.save()
            
    farm_form = forms.CreateFarmsForm()
    phone_form = forms.TelephoneCreateForm()
    address_form = forms.AddressCreateForm()
    context = {'farm_form':farm_form, 'phone_form':phone_form, 'address_form':address_form,}
    return render(request, "livestock/farm_name.html", context)

I have been on it for the past two days. please i need some help to continue.

What is the issue or error that has you stalled at this point? Are you getting some error message indicating a problem? Or is something happening that you’re not expecting to see happen?

You mean is_valid() - the parentheses are necessary to call the function, otherwise this staement is always true.

2 Likes

The issue was resolved. i replaced false with commit=false

I would suggest the following;

  • Rename the model Farms to Farm
  • Call the app name to farms, for me it makes more sense
  • put some comment on what you are doing (especially in the views, this helps begginers like me to understand what’s going on)

I rewrite your code for me to understand the problem and send push it to gitHub in case somebody is interested in knowing how this works :slightly_smiling_face:

Greetings,

Further extending the above question - for example, if I have one more model “Produce” with a 1-many relationship between “Address” and “Produce”.

How can I implement a Produce model form - where the user can select Farm and Address from the dropdown to enter and save Produce detail - on one form?

(Note: There is no direct relationship between Farm and Produce model - Farm can access the Produce model by inner join with Address.)

Regards,