保存 django 父子表单
Saving django parent and child form
我有一个页面,用户可以在其中输入与两个模型相关的详细信息 - 一个代表患者,另一个代表该患者服用的药物。我设计了界面,以便用户可以动态添加多种药物。
但是,我不确定如何在用户提交时同时保存药物和患者的条目。在下面的当前设置中,我没有成功保存患者数据,因为我收到错误“save() prohibited to prevent data loss due to unsaved related object 'patient'.”
models.py
class Patient(TimeStampedModel):
patient_id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)
name = models.CharField("Patient Name", max_length=255)
class Med(TimeStampedModel):
med_name = models.CharField("MedName", max_length=20)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
forms.py
from django.forms import inlineformset_factory, ModelForm
from .models import Med, Patient
MedFormSet = inlineformset_factory(Patient, Med, fields=("med_name",), extra=1)
class PatientForm(ModelForm):
class Meta:
model = Patient
fields = ['name', 'sex']
views.py
from .forms import MedFormSet, PatientForm
from .models import Patient, Med
class MedAddView(TemplateView):
model = Patient
template_name = "../templates/patient/med_add.html"
def get(self, *args, **kwargs):
# Create an instance of the formset
patient_form = PatientForm
formset = MedFormSet(queryset=Med.objects.none())
return self.render_to_response({'med_formset': formset, 'patient_form':patient_form})
def post(self, *args, **kwargs):
form = PatientForm(data=self.request.POST)
formset = MedFormSet(data=self.request.POST)
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
return redirect('patient:med_list')
MedAddview html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add a new med</h1>
<form id="form-container" method="POST">
{% csrf_token %}
{{patient_form}}
{{med_formset.management_form}}
{% for form in med_formset %}
<div class="med-form">
{{form.as_p}}
</div>
{% endfor %}
<button id="add-form" type="button">Add Another Med</button>
<button type="submit">Create Meds</button>
</form>
<script>
let medForm = document.querySelectorAll(".med-form")
let container = document.querySelector("#form-container")
let addButton = document.querySelector("#add-form")
let totalForms = document.querySelector("#id_form-TOTAL_FORMS")
let formNum = medForm.length-1
addButton.addEventListener('click', addForm)
function addForm(e){
e.preventDefault()
let newForm = medForm[0].cloneNode(true)
let formRegex = RegExp(`form-(\d){1}-`,'g')
formNum++
newForm.innerHTML = newForm.innerHTML.replace(formRegex, `form-${formNum}-`)
container.insertBefore(newForm, addButton)
totalForms.setAttribute('value', `${formNum+1}`)
}
</script>
{% endblock %}
试试这个代码它会起作用
def post(self, *args, **kwargs):
form = PatientForm(data=self.request.POST)
formset = MedFormSet(data=self.request.POST)
if form.is_valid():
patient_instance = form.save()
if formset.is_valid():
med_name = formset.save(commit = False)
for med in med_name:
med.patient = patient_instance
med.save()
return redirect('patient:med_list')
我有一个页面,用户可以在其中输入与两个模型相关的详细信息 - 一个代表患者,另一个代表该患者服用的药物。我设计了界面,以便用户可以动态添加多种药物。
但是,我不确定如何在用户提交时同时保存药物和患者的条目。在下面的当前设置中,我没有成功保存患者数据,因为我收到错误“save() prohibited to prevent data loss due to unsaved related object 'patient'.”
models.py
class Patient(TimeStampedModel):
patient_id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)
name = models.CharField("Patient Name", max_length=255)
class Med(TimeStampedModel):
med_name = models.CharField("MedName", max_length=20)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
forms.py
from django.forms import inlineformset_factory, ModelForm
from .models import Med, Patient
MedFormSet = inlineformset_factory(Patient, Med, fields=("med_name",), extra=1)
class PatientForm(ModelForm):
class Meta:
model = Patient
fields = ['name', 'sex']
views.py
from .forms import MedFormSet, PatientForm
from .models import Patient, Med
class MedAddView(TemplateView):
model = Patient
template_name = "../templates/patient/med_add.html"
def get(self, *args, **kwargs):
# Create an instance of the formset
patient_form = PatientForm
formset = MedFormSet(queryset=Med.objects.none())
return self.render_to_response({'med_formset': formset, 'patient_form':patient_form})
def post(self, *args, **kwargs):
form = PatientForm(data=self.request.POST)
formset = MedFormSet(data=self.request.POST)
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
return redirect('patient:med_list')
MedAddview html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h1>Add a new med</h1>
<form id="form-container" method="POST">
{% csrf_token %}
{{patient_form}}
{{med_formset.management_form}}
{% for form in med_formset %}
<div class="med-form">
{{form.as_p}}
</div>
{% endfor %}
<button id="add-form" type="button">Add Another Med</button>
<button type="submit">Create Meds</button>
</form>
<script>
let medForm = document.querySelectorAll(".med-form")
let container = document.querySelector("#form-container")
let addButton = document.querySelector("#add-form")
let totalForms = document.querySelector("#id_form-TOTAL_FORMS")
let formNum = medForm.length-1
addButton.addEventListener('click', addForm)
function addForm(e){
e.preventDefault()
let newForm = medForm[0].cloneNode(true)
let formRegex = RegExp(`form-(\d){1}-`,'g')
formNum++
newForm.innerHTML = newForm.innerHTML.replace(formRegex, `form-${formNum}-`)
container.insertBefore(newForm, addButton)
totalForms.setAttribute('value', `${formNum+1}`)
}
</script>
{% endblock %}
试试这个代码它会起作用
def post(self, *args, **kwargs):
form = PatientForm(data=self.request.POST)
formset = MedFormSet(data=self.request.POST)
if form.is_valid():
patient_instance = form.save()
if formset.is_valid():
med_name = formset.save(commit = False)
for med in med_name:
med.patient = patient_instance
med.save()
return redirect('patient:med_list')