Django 2.0:如何在 1 个视图中保存 3 个 ModelForms
Django 2.0: How to save 3 ModelForms in 1 view
如何从一个视图中保存来自 3 个 FormModel 的输入?
您好 Whosebug,这是我第一次 post 来到这里。我刚开始在 Python/Django 中学习编码,所以我的代码可能根本不正确,对此深表歉意。
经过三天的搜索和大量代码的尝试,我希望有知识的人:)
我想做什么:
一张大表:用户填写个人字段、档案字段和第二人的信息。 (部分内容目前未正确保存)
Views.py 2 个 ModelForms 的一个视图,并再次为 c_person 重用一个视图。
Models.py 2 个模型(一个档案和一个人的数据模型)。
Forms.py 2 个模型表单(一个来自档案,一个来自个人,在视图中重复使用个人表单)。
dossier.html 数据给出了表格的概念(删除了很多代码)。
<div class="column is-one-fifth">
<label class="label is-small">Firstname</label>
{{ person_form.first_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Preposition</label>
{{ person_form.preposition }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Lastname</label>
{{ person_form.last_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Address</label>
{{ person_form.address }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Firstname</label>
{{ cperson_form.first_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Lastname</label>
{{ cperson_form.last_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Number</label>
{{ cperson_form.number }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Status</label>
{{ dossier_form.status }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Operator</label>
<div class=select>{{ dossier_form.operator }}</div>
</div>
models.py
class Person(models.Model):
number = models.IntegerField(unique=True, null=True, blank=True)
first_name = models.CharField(max_length=35, null=True, blank=True)
last_name = models.CharField(max_length=35, null=True, blank=True)
initials = models.CharField(max_length=10, null=True, blank=True)
preposition = models.CharField(max_length=10, null=True, blank=True)
address = models.CharField(max_length=80, null=True, blank=True)
address_number = models.CharField(max_length=5, null=True, blank=True)
email = models.EmailField(null=True, blank=True)
phone_number = models.IntegerField(null=True, blank=True)
@property
def full_name(self):
"Returns the person's full name"
full_name = (self.last_name + ', ' + self.first_name)
# Need to check this, django return 'None' if no preposition is used
if self.preposition:
full_name = full_name + ' ' + self.preposition
return full_name
def __str__(self):
return self.first_name + ' ' + self.last_name
class Dossier(models.Model):
# Core
status = models.ForeignKey('DossierStatus', null=True, on_delete=models.SET_NULL)
operator = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
d_person = models.ForeignKey('Person', related_name='d_person', null=True, on_delete=models.SET_NULL, blank=True)
c_person = models.ForeignKey(Person, related_name='c_person', null=True, on_delete=models.SET_NULL, blank=True)
def __int__(self):
return self.id
def get_absolute_url(self):
return reverse('dossier_edit', kwargs={'pk': self.pk})
forms.py
class PersForm(forms.ModelForm):
class Meta:
model = Person
fields = ['number', 'first_name', 'preposition', 'last_name', 'initials', 'address', 'address_number', 'email', 'phone_number']
class DossierForm(forms.ModelForm):
class Meta:
model = Dossier
fields = '__all__'
views.py
def dossier(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
dossier_form = DossierForm(request.POST, request.FILES)
dossier_form_valid = dossier_form.is_valid()
person_form = PersForm(request.POST)
person_form_valid = person_form.is_valid()
cperson_form = PersForm(request.POST)
cperson_form_valid = cperson_form.is_valid()
# check whether it's valid:
if dossier_form_valid and person_form_valid and cperson_form_valid:
print("succes")
# process the data
person_save = person_form.save()
dossier_save = dossier_form.save(commit=False)
cperson_save = cperson_form.save(commit=False)
dossier_save.person_save = person_save
cperson_save.dossier_save = dossier_save
cperson_save.save()
# redirect to a new URL:
return HttpResponseRedirect('/data/index/')
else:
print("failure")
print(dossier_form.errors)
print(person_form.errors)
# if a GET (or any other method) we'll create a blank form
else:
dossier_form = DossierForm()
person_form = PersForm()
cperson_form = PersForm()
return render(request, 'dossier.html',
{'title': 'Nieuwe aanvraag', 'dossier_form': dossier_form,
'person_form': person_form, 'cperson_form': cperson_form})
这里的问题是只有一个人的表单数据被保存到数据库中。
我在这段代码上尝试了很多不同的变体:
person_save = person_form.save()
dossier_save = dossier_form.save(commit=False)
cperson_save = cperson_form.save(commit=False)
dossier_save.person_save = person_save
cperson_save.dossier_save = dossier_save
cperson_save.save()
在模型表单中将 commit
参数传递给 save()
方法时,它会将您的模型保存在数据库中。我看到这里的 commit
术语有点误导,因为它听起来像 提交数据库事务 ,但它纯粹是定义模型的 save()
方法是否将是叫不叫。
您要做的是使用 django.models.db.transaction
.
将所有这些代码包装在一个数据库事务中
首先将其导入您的视图:
from django.db.models import transaction
那么你可以这样使用它:
if dossier_form_valid and person_form_valid and cperson_form_valid:
print("succes")
# process the data
with transaction.atomic():
d_person = person_form.save()
c_person = cperson_form.save()
dossier = dossier_form.save(commit=False)
dossier.d_person = d_person
dossier.c_person = c_person
dossier.save()
模型形式 save()
方法 returns 它代表的 Django 模型实例。所以它将它重命名为 dossier
而不是 dossier_save
,等等
在 dossier_form
中你可以使用 commit=False
因为你有更多的数据与 dossier
相关联,这样你就可以避免多次调用 save()
方法.但是为了让对象持久保存在数据库中,在添加额外数据后,您需要调用 dossier.save()
.
之类的保存方法
transaction.atomic()
块内的所有内容都将在单个数据库事务中执行,如果发生错误,Django 将自动回滚。
Vitor 的响应是正确的,但是,导入已更改为:
from django.db.models import transaction
已更改为:
from django.db import transaction
如何从一个视图中保存来自 3 个 FormModel 的输入?
您好 Whosebug,这是我第一次 post 来到这里。我刚开始在 Python/Django 中学习编码,所以我的代码可能根本不正确,对此深表歉意。
经过三天的搜索和大量代码的尝试,我希望有知识的人:)
我想做什么:
一张大表:用户填写个人字段、档案字段和第二人的信息。 (部分内容目前未正确保存)
Views.py 2 个 ModelForms 的一个视图,并再次为 c_person 重用一个视图。 Models.py 2 个模型(一个档案和一个人的数据模型)。 Forms.py 2 个模型表单(一个来自档案,一个来自个人,在视图中重复使用个人表单)。
dossier.html 数据给出了表格的概念(删除了很多代码)。
<div class="column is-one-fifth">
<label class="label is-small">Firstname</label>
{{ person_form.first_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Preposition</label>
{{ person_form.preposition }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Lastname</label>
{{ person_form.last_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Address</label>
{{ person_form.address }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Firstname</label>
{{ cperson_form.first_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Lastname</label>
{{ cperson_form.last_name }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Number</label>
{{ cperson_form.number }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Status</label>
{{ dossier_form.status }}
</div>
<div class="column is-one-fifth">
<label class="label is-small">Operator</label>
<div class=select>{{ dossier_form.operator }}</div>
</div>
models.py
class Person(models.Model):
number = models.IntegerField(unique=True, null=True, blank=True)
first_name = models.CharField(max_length=35, null=True, blank=True)
last_name = models.CharField(max_length=35, null=True, blank=True)
initials = models.CharField(max_length=10, null=True, blank=True)
preposition = models.CharField(max_length=10, null=True, blank=True)
address = models.CharField(max_length=80, null=True, blank=True)
address_number = models.CharField(max_length=5, null=True, blank=True)
email = models.EmailField(null=True, blank=True)
phone_number = models.IntegerField(null=True, blank=True)
@property
def full_name(self):
"Returns the person's full name"
full_name = (self.last_name + ', ' + self.first_name)
# Need to check this, django return 'None' if no preposition is used
if self.preposition:
full_name = full_name + ' ' + self.preposition
return full_name
def __str__(self):
return self.first_name + ' ' + self.last_name
class Dossier(models.Model):
# Core
status = models.ForeignKey('DossierStatus', null=True, on_delete=models.SET_NULL)
operator = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
d_person = models.ForeignKey('Person', related_name='d_person', null=True, on_delete=models.SET_NULL, blank=True)
c_person = models.ForeignKey(Person, related_name='c_person', null=True, on_delete=models.SET_NULL, blank=True)
def __int__(self):
return self.id
def get_absolute_url(self):
return reverse('dossier_edit', kwargs={'pk': self.pk})
forms.py
class PersForm(forms.ModelForm):
class Meta:
model = Person
fields = ['number', 'first_name', 'preposition', 'last_name', 'initials', 'address', 'address_number', 'email', 'phone_number']
class DossierForm(forms.ModelForm):
class Meta:
model = Dossier
fields = '__all__'
views.py
def dossier(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
dossier_form = DossierForm(request.POST, request.FILES)
dossier_form_valid = dossier_form.is_valid()
person_form = PersForm(request.POST)
person_form_valid = person_form.is_valid()
cperson_form = PersForm(request.POST)
cperson_form_valid = cperson_form.is_valid()
# check whether it's valid:
if dossier_form_valid and person_form_valid and cperson_form_valid:
print("succes")
# process the data
person_save = person_form.save()
dossier_save = dossier_form.save(commit=False)
cperson_save = cperson_form.save(commit=False)
dossier_save.person_save = person_save
cperson_save.dossier_save = dossier_save
cperson_save.save()
# redirect to a new URL:
return HttpResponseRedirect('/data/index/')
else:
print("failure")
print(dossier_form.errors)
print(person_form.errors)
# if a GET (or any other method) we'll create a blank form
else:
dossier_form = DossierForm()
person_form = PersForm()
cperson_form = PersForm()
return render(request, 'dossier.html',
{'title': 'Nieuwe aanvraag', 'dossier_form': dossier_form,
'person_form': person_form, 'cperson_form': cperson_form})
这里的问题是只有一个人的表单数据被保存到数据库中。 我在这段代码上尝试了很多不同的变体:
person_save = person_form.save()
dossier_save = dossier_form.save(commit=False)
cperson_save = cperson_form.save(commit=False)
dossier_save.person_save = person_save
cperson_save.dossier_save = dossier_save
cperson_save.save()
在模型表单中将 commit
参数传递给 save()
方法时,它会将您的模型保存在数据库中。我看到这里的 commit
术语有点误导,因为它听起来像 提交数据库事务 ,但它纯粹是定义模型的 save()
方法是否将是叫不叫。
您要做的是使用 django.models.db.transaction
.
首先将其导入您的视图:
from django.db.models import transaction
那么你可以这样使用它:
if dossier_form_valid and person_form_valid and cperson_form_valid:
print("succes")
# process the data
with transaction.atomic():
d_person = person_form.save()
c_person = cperson_form.save()
dossier = dossier_form.save(commit=False)
dossier.d_person = d_person
dossier.c_person = c_person
dossier.save()
模型形式 save()
方法 returns 它代表的 Django 模型实例。所以它将它重命名为 dossier
而不是 dossier_save
,等等
在 dossier_form
中你可以使用 commit=False
因为你有更多的数据与 dossier
相关联,这样你就可以避免多次调用 save()
方法.但是为了让对象持久保存在数据库中,在添加额外数据后,您需要调用 dossier.save()
.
transaction.atomic()
块内的所有内容都将在单个数据库事务中执行,如果发生错误,Django 将自动回滚。
Vitor 的响应是正确的,但是,导入已更改为:
from django.db.models import transaction
已更改为:
from django.db import transaction