0

I'm building an app in which I have a model with several manytomany fields and some foreignkey fields, and I need a view that allows me to create all in one page and let me enter multiply times for the manytomanyfields, but I don't know how to deal with a lot of forms in the same page/view.

main model

class Client(models.Model):
    company_name = models.CharField(max_length=255, blank=True, null=True)
    payment_method = models.CharField(max_length=64, null=True, blank=True)
    owner = models.CharField(max_length=100, blank=True, null=True)
    operation = models.CharField(max_length=50, blank=True, null=True)
    value = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
    currency = models.CharField(max_length=55, null=True, blank=True)

    address = models.ManyToManyField(Address, blank=True)
    contact = models.ManyToManyField(Contact, blank=True)
    relationship = models.ManyToManyField(Relationship, blank=True)
    attachment = models.ManyToManyField(Attachment, blank=True)

    billing = models.ForeignKey(Billing, null=True, blank=True, on_delete=models.CASCADE)
    delivery = models.ForeignKey(Delivery, null=True, blank=True, on_delete=models.CASCADE)

    author = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True)

    note = models.TextField(blank=True, null=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.company_name

others models

class Address(models.Model):
    address = models.CharField(max_length=256, null=True, blank=True)
    number = models.PositiveIntegerField(null=True, blank=True)
    district = models.CharField(max_length=32, null=True, blank=True)
    city = models.CharField(max_length=32, null=True, blank=True)
    country = models.CharField(choices=COUNTRY_CHOICES, max_length=64, null=True, blank=True)

    def __str__(self):
        return self.address


class Contact(models.Model):
    name = models.CharField(max_length=256, blank=False, null=True)
    sector = models.CharField(max_length=64, blank=True, null=True)
    email = models.EmailField(max_length=256, blank=True, null=True)
    phone = PhoneField(blank=True, null=True)
    cellphone = PhoneField(blank=True, null=True)
    role = models.CharField(max_length=155, blank=True, null=True)
    nfe = models.BooleanField(verbose_name='NFE', default=False)

    def __str__(self):
        return self.name


class Relationship(models.Model):
    company = models.CharField(max_length=256, blank=False, null=True)
    agent = models.ForeignKey(Vendedor, on_delete=models.DO_NOTHING, blank=True, null=True)
    type = models.CharField(choices=TYPE_CHOICES, max_length=32, blank=True, null=True)
    contact = models.CharField(max_length=128, blank=True, null=True)

    def __str__(self):
        return self.company


class Attachment(models.Model):
    file = models.FileField(upload_to='post/img/%Y/%m/%d', blank=True, null=True)
    note = models.CharField(verbose_name='Observação', max_length=256, blank=True, null=True)
    author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.note


class BankAccount(models.Model):
    bank = models.CharField(max_length=64, blank=False, null=True)
    type = models.CharField(max_length=32, blank=False, null=True)
    payment_method = models.CharField(max_length=64, blank=True, null=True)

    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.bank


class Billing(models.Model):
    name = models.CharField(max_length=256, blank=True, null=True)
    address = models.ForeignKey(Address, null=True, blank=True, on_delete=models.CASCADE)
    email = models.EmailField(max_length=256, blank=True, null=True)
    phone = PhoneField(blank=True, null=True)
    contact = models.CharField(max_length=256, blank=True, null=True)

    def __str__(self):
        return self.name


class Delivery(models.Model):
    name = models.CharField(max_length=256, blank=True, null=True)
    address = models.ForeignKey(Address, null=True, blank=True, on_delete=models.CASCADE)
    email = models.EmailField(max_length=256, blank=True, null=True)
    phone = PhoneField(blank=True, null=True)
    contact = models.CharField(max_length=256, blank=True, null=True)

    def __str__(self):
        return self.name

does anyone know what is the best way to deal with this?

Will
  • 1
  • [This](https://stackoverflow.com/a/1395866/15116314) is a good answer on handling mutiple forms on same page in django. – Vishwas Patel Feb 12 '21 at 06:05

1 Answers1

0

Make a python file forms.py and make model forms for all the models you have. Then in views make a function with all the forms. Then in the html file call the different forms together using jinja2. Here is a simple example:

models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.

class UserProfileInfo(models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE)
    Your_website = models.URLField(blank = True)
    profile_pic = models.ImageField(upload_to="profile_pics", blank = True)
    def __str__(self):
        return self.user.username

This model is connected to the django user model by OneToOneField. Then in forms.py I have created all the model forms for the models.

from django import forms
from django.contrib.auth.models import User
from basic.models import UserProfileInfo
from django.core import validators

    class userform(forms.ModelForm):
        password = forms.CharField(widget=forms.PasswordInput())
        re_enter_password = forms.CharField(widget=forms.PasswordInput())
        class Meta():
            model = User
            fields = ("username", "email", "password")
    
    class UserProfileInfoForm(forms.ModelForm):
    
        class Meta():
            model = UserProfileInfo
            fields = ('Your_website', "profile_pic")

Then make the view with both the model forms.

def register(request):
    registered = False

    if request.method == 'POST':
        user_form = forms.userform(data = request.POST)
        profile_form = forms.UserProfileInfoForm(data = request.POST)

        if user_form.is_valid() and profile_form.is_valid():

            user = user_form.save()
            user.set_password(user.password)
            user.save()

            profile = profile_form.save(commit=False)
            profile.user = user

            if 'profile_pic' in request.FILES:
                profile.profile_pic = request.FILES['profile_pic']

            profile.save()

            registered = True
        else:
            print(user_form.errors, profile_form.errors)
    else:
        user_form = forms.userform()
        profile_form = forms.UserProfileInfoForm()

In the html file call both the forms like this:

<div class="container">
  <form method="post" enctype="multipart/form-data" class="all_forms">
    {% csrf_token %}
    {{ user_form.as_p }}
    {{ profile_form.as_p }}
    <input type="submit" class="btn btn-primary" value="Register Now!">
  </form>
</div>

This way you don't have to create multiple forms for the models, the user will be asked only one form where all the models will get their separate response from one form.

Dharman
  • 21,838
  • 18
  • 57
  • 107
Girik1105
  • 76
  • 4