Несколько разных форм в одном представлении Django
Я хотел узнать, есть ли способ иметь несколько различных форм в одном представлении и нажать одну кнопку отправки для сохранения информации. У меня есть следующие формы, первая - это общая форма, которая должна быть создана первой:
class GeneralForm(forms.ModelForm):
name = forms.CharField(max_length=50)
TYPE_CHOICES = (
("C","C"),
("E","E")
)
STATUS_CHOICES = (
("A", "A"),
("F", "F"),
)
type=forms.ChoiceField(choices=STATUS_CHOICES)
number=forms.CharField(max_length=50)
TURN_CHOICES = (
("1", "1"),
("2", "2"),
("3", "3")
)
turn = forms.ChoiceField(choices=TURN_CHOICES)
class Meta:
model = models.General
fields=["name","type","number","turn"]
Второму нужен экземпляр первого, и третьему тоже:
class TypeOneForm(forms.ModelForm):
num_chairs=forms.IntegerField()
num_instalations = forms.IntegerField()
total = forms.IntegerField()
num_programs = forms.IntegerField()
class Meta:
model = models.TypeOne
fields=["num_chairs","num_instalations","total","billetes_cien"]
class TypeTwoForm(forms.ModelForm):
num_available_seats=forms.IntegerField()
num_available_instalations = forms.IntegerField()
total = forms.IntegerField()
num_new_programs = forms.IntegerField()
class Meta:
model = models.TypeTwo
fields=["num_available_seats", "num_available_instalations","total","num_programs" ]
Вот мои модели:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class General(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
name = models.CharField(max_length=100)
TYPE_CHOICES = {
"C": "C",
"E": "E",
}
type = models.CharField(max_length=10, choices=TYPE_CHOICES)
STATUS_CHOICES = {
"A": "A",
"F": "F",
}
status = models.CharField(max_length=10, choices=STATUS_CHOICES)
number = models.CharField(max_length=100)
TURN_CHOICES = {
"1": "1",
"2": "2",
"3": "3",
}
turn = models.CharField(max_length=10, choices=TURN_CHOICES)
def __str__(self):
return self.name
class One(models.Model):
one = models.OneToOneField(General, on_delete=models.CASCADE, primary_key=True)
num_chairs = models.IntegerField(default=0)
num_installations = models.IntegerField(default=0)
total = models.IntegerField(default=0)
num_programs = models.IntegerField(default=0)
class Two(models.Model):
two = models.OneToOneField(General, on_delete=models.CASCADE, primary_key=True)
num_available_seats = models.IntegerField(default=0)
num_available_installations = models.IntegerField(default=0)
total = models.IntegerField(default=0)
num_new_programs = models.IntegerField(default=0)
Вот мои представления, но я также не уверен, как написать представление создания и представление обновления для этого конкретного случая.
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
)
from .models import General, One,Two
# Create your views here.
class GeneralListView(ListView):
model = General
template_name = "testing/user_testing.html"
context_object_name = 'generals'
class GeneralDetailView(DetailView):
model = General
class GeneralCreateView(LoginRequiredMixin, CreateView):
model = General
fields = '__all__'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class GeneralUpdateView(LoginRequiredMixin, UpdateView):
pass
Я читал, что могу использовать наборы форм, но не уверен, могу ли я использовать разные формы вместо нескольких экземпляров одной формы.
Инструмент, который вы здесь ищете, - это префиксный аргумент классов форм. Вам придется переопределить некоторые методы представлений, такие как get_form и, возможно, get_form_class, поскольку представления, основанные на классах, по умолчанию не рассчитаны на прием более одного типа форм. Вам также может понадобиться переопределить метод post в представлениях, чтобы загрузить данные из почтового запроса в формы.
Аргумент prefix означает, что данные формы, отправляемые в ваше приложение django, будут «namespaced», поэтому класс формы будет загружать из запроса только те данные post, которые ему нужны.
В зависимости от того, как вы отображаете свои формы, вам может понадобиться убедиться, что префикс также отображается в атрибуте name HTML-ввода.
По моему опыту, переопределить весь код представления, основанного на модели, будет сложнее: возможно, вы воспользуетесь более общим классом FormView, но вам придется повторить большую часть логики CreateView и UpdateView для обработки и сохранения (например, вызов form.save() в методе form_valid в FormView)
Мне всегда нравилось CCBV для распутывания порядка вызова методов представления, основанного на классах.
Еще одно замечание: вы всегда можете вывести на страницу более одной формы, но сделать так, чтобы отправленные данные попадали в разные представления. Если формы зависят друг от друга, возможно, будет проще написать одну форму, которая будет обрабатывать очищенные данные в экземпляры модели и сохранять их. Иными словами, в зависимости от сценария использования и опыта, который вы хотите получить от пользователей, вам нужно будет принять решение о том, как обрабатывать форму.