我有一个 Item 模型,其中有 Row 模型中的前键。
models.py
from django.db import models
from django.urls import reverse
from django.utils import timezone
class Item(models.Model):
item_name = models.CharField(max_length=100, unique=True, validators=[validate_test])
number_of_questions = models.IntegerField(default=0)
number_of_read_questions = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('uni_checker:main_editor')
class Row(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
row_name = models.CharField(max_length=100, validators=[validate_test])
is_completed = models.BooleanField(default=False)
deadline = models.DateField(default=timezone.now())
我正在寻找可以在一页上创建类似内容的解决方案:
Item1_name:
- Row1_name;
- Row2_name;
- Row3_name;
Item2_name:
- Row4_name;
- Row5_name;
- Row6_name;
对于创建对象,我将 CreateView 与 form_class = Item 一起使用,并将上下文变量 formset 与 Row 表单一起使用。
问题是,我不仅不知道如何验证表单中的数据,还不知道如何验证表单集中的数据。 如果我在 row_name 字段中输入了无效数据,它只会保存 Item 对象,而不会保存 Row 对象或显示错误。
我知道视图类或表单创建中有问题,但是我找不到正确的方法。
views.py
from django.views.generic import ListView
from .models import Item
from django.urls import reverse
from .forms import ExampleFormSetHelper, CreateRowFormSet, ItemForm
from crispy_forms.layout import Submit
class ItemCreateView(CreateView):
model = Item
template_name = "uni_checker/item_create.html"
form_class = ItemForm
def get_context_data(self, **kwargs):
data = super(ItemCreateView, self).get_context_data(**kwargs)
helper = ExampleFormSetHelper()
helper.add_input(Submit("submit", "Save"))
data["helper"] = helper
if self.request.POST:
data['formset'] = CreateRowFormSet(self.request.POST)
else:
data['formset'] = CreateRowFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
formset = context['formset']
if formset.is_valid() and form.is_valid():
form.save()
for temp_form in formset:
instance = temp_form.save(commit=False)
instance.item = form.save()
instance.save()
return super(ItemCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('uni_checker:main_editor')
forms.py
from django import forms
from django.forms.formsets import BaseFormSet
from .models import Item, Row
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field
from django.forms import inlineformset_factory
class ExampleFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(ExampleFormSetHelper, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.layout = Layout(
Field('row_name', required=True),
Field('deadline', required=True),
)
self.render_required_fields = True
self.form_tag = False
class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = '__all__'
def __init__(self, *args, **kwargs):
super(ItemForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_method = 'post'
self.helper.render_required_fields = True
self.helper.form_tag = False
CreateRowFormSet = inlineformset_factory(Item, Row, fields='__all__', extra=3)
UpdateRowFormSet = inlineformset_factory(Item, Row, fields='__all__', extra=0)
template.html
{% extends "uni_checker/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<form class="uniForm" method="post">
{% csrf_token %}
{% crispy form %}
{% crispy formset helper %}
</form>
{% endblock %}