提问人:buryj 提问时间:11/17/2023 最后编辑:buryj 更新时间:11/17/2023 访问量:27
为什么我的 Django 表单答案被多次保存并删除另一个数据库表的内容?
Why are my Django form answers being saved multiple times and deleting the contents of another DB table?
问:
我是 Django 的完全初学者,我创建了一种单选形式 - 每个问题都是从我数据库的 Questions 表中动态填充的。提交表单时,应将每个问题的各种详细信息保存到数据库的分数表中。Scores 具有指向 id_question 列的 Questions 和 id_company 上的 Companies 表的外键。
目前,我可以在 print 语句中显示正确的值,但将它们另存为实例会产生混合结果。每个实例都使用不同的值多次保存,或者每个实例都取一个值。我尝试移动我的 save() 的位置,修改循环和我的数据的存储方式,但同样的问题不断重复。我也尝试过访问cleaned_data但它通常是空的。
最重要的是,在提交表格并保存分数后,所有问题数据都会从数据库中删除。行和 id 不会被删除,但其他列会被赋予一个 null 值。
我觉得我完全错了,但我无法理解 Django 关于表单的文档以及如何将其应用于我的项目。
当用户提交时,应在“分数”表中为表单的每个问题创建一个新行。应包括以下信息:id_company、id_question、答案、initialScore。
这是我 form.py(你可以看到我尝试过的其他一些东西被注释掉了):
from django import forms
from .custom_models import Questions, Scores, Companies
from django.utils import timezone
import re
class QuestionForm(forms.ModelForm):
class Meta:
model = Questions
fields = ['questionnb', 'wording', 'answer1', 'answer2', 'answer3', 'answer4']
# id_company = forms.IntegerField(widget=forms.HiddenInput())
answers = forms.ChoiceField(
choices=[('answer1', 'Answer 1'), ('answer2', 'Answer 2'), ('answer3', 'Answer 3'), ('answer4', 'Answer 4')],
widget=forms.RadioSelect(),
required=False
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['questionnb'].required = False
self.fields['wording'].required = False
# self.fields['id_company'].required = False
def save(self, commit=True):
instance = super().save(commit=False)
selected_answers = getattr(self, 'selected_answers', None)
id_question = instance.id
id_question_instance = Questions.objects.get(id = id_question)
score = instance.score
id_company = self.initial['id_company']
id_company_instance = Companies.objects.get(id = id_company)
details_list = [] # Initialize an empty list to store details
for question_key, answer_value in selected_answers.items():
questionnb = question_key
answer = answer_value
details_list.append(f"{questionnb}, {answer}")
# Save the answer to Scores model
if commit and answer is not None:
Scores.objects.create(
id_company= id_company_instance,
id_question=id_question_instance,
answer=answer,
initialscore=score if answer == 'Oui' else 0,
createdat=timezone.now(),
updatedat=timezone.now()
)
if commit:
instance.save()
return instance
# Print details outside the loop
print(id_question, score, id_company_instance.id)
for details in details_list:
print(details)
# Save the answer to Scores model
# if commit and answer is not None:
# Scores.objects.create(
# id_company= id_company_instance,
# id_question=question_instance,
# answer=answer,
# initialscore=question_instance.score if answer == 'Oui' else 0,
# createdat=timezone.now(),
# updatedat=timezone.now()
# )
# instance.save()
# return instance
来自 views.py 的相关代码:
@login_required
def questionnaire(request):
if request.method == 'GET':
questions = Questions.objects.all().order_by('questionnb')
questions_list = [QuestionForm(instance=question, initial={'id_company': request.user.company.id}) for question in questions]
return render(request, 'form.html', {'questions_list': questions_list})
if request.method == 'POST':
forms = [QuestionForm(request.POST, instance=Questions.objects.get(pk=question.id), initial={'id_company': request.user.company.id}) for question in Questions.objects.all()]
post_data = QueryDict(request.body.decode('utf-8'))
# print(post_data)
if all(form.is_valid() for form in forms):
for form in forms:
if form.is_valid():
form.selected_answers = {}
for questionnb, answer in post_data.items():
if questionnb != 'csrfmiddlewaretoken' and questionnb != None:
form.selected_answers[questionnb] = answer
form.save()
else:
for form in forms:
for field, errors in form.errors.items():
messages.error(request, f"Error in {field}: {', '.join(errors)}")
return render(request, 'form.html', {'questions_list': forms})
return redirect('dashboard')
# @login_required
# def questionnaire(request):
# questions = Questions.objects.all().order_by('questionnb')
# form = QuestionForm
# questions_list = [QuestionForm(instance=question, initial={'id_company': request.user.company.id}) for question in questions]
# if request.method == 'GET':
# return render(request, 'form.html', {'questions_list': questions_list})
# if request.method == 'POST':
# post_data = request.POST # Use request.POST directly
# for key, value in post_data.items():
# if key != 'csrfmiddlewaretoken' and value == 'Oui' or value == 'Non':
# current_answer = value
# if key != 'csrfmiddlewaretoken' and value == None:
# current_answer = 'Error'
# # Update the 'answers' field for the current question form
# form = QuestionForm(request.POST, instance=questions[key], initial={'id_company': request.user.company.id, 'question_id': questions[key].id})
# form.cleaned_data['answers'] = current_answer if current_answer in ['Oui', 'Non'] else 'Error'
# # Save the form and handle other logic as needed
# form.save()
# return redirect('dashboard')
# # Always return an HttpResponseRedirect after successfully dealing
# # with POST data. This prevents data from being posted twice if a
# # user hits the Back button.
# return HttpResponseRedirect("dashboard")
# post_data = QueryDict(request.body.decode('utf-8'))
# print(post_data)
# forms = [QuestionForm(request.POST, instance=question, initial={'id_company': request.user.company.id, 'post_data': post_data}) for question in Questions.objects.all()]
# if all(form.is_valid() for form in forms):
# for form in forms:
# form.save()
# return redirect('dashboard')
# else:
# for form in forms:
# for field, errors in form.errors.items():
# messages.error(request, f"Error in {field}: {', '.join(errors)}")
# return render(request, 'form.html', {'questions_list': forms})
表单.html:
{% extends 'base.html' %}
{% block title %} Questionnaire {% endblock %}
{% block content %}
<form method="post" action="{% url 'questionnaire' %}" class="w-5/6 flex flex-col text-justify">
{% csrf_token %}
<h1 class="text-center">Etat des Lieux</h1>
{% for question in questions_list %}
<div class="{% if question.questionnb.value|length > 3 %} ml-20 {%else%} ml-5 {%endif%} p-2 mb-2">
<div class="flex mb-2">
<p class="pe-2 text-base text-1.5xl font-medium text-gray-900">{{ question.questionnb.value }}</p>
<p id="question_{{ question.questionnb.value }}_">{{ question.wording.value }}</p>
</div>
<div class="ml-3">
{% if question.answer1.value is not None%}
<input class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" type="radio" id="question_{{ question.questionnb.value }}_1" name="question_{{ question.questionnb.value }}" value="{{ question.answer1.value|default_if_none:"" }}">
<label class="text-gray-700" for="question_{{ question.questionnb.value }}_1">{{ question.answer1.value }}</label>
{% endif %}
{% if question.answer2.value is not None%}
<input class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" type="radio" id="question_{{ question.questionnb.value }}_2" name="question_{{ question.questionnb.value }}" value="{{ question.answer2.value|default_if_none:"" }}">
<label class="text-gray-700" for="question_{{ question.questionnb.value }}_2">{{ question.answer2.value }}</label>
{% endif %}
{% if question.answer3.value is not None%}
<input class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" type="radio" id="question_{{ question.questionnb.value }}_3" name="question_{{ question.questionnb.value }}" value="{{ question.answer3.value|default_if_none:"" }}">
<label class="text-gray-700" for="question_{{ question.questionnb.value }}_3">{{ question.answer3.value }}</label>
{% endif %}
{% if question.answer4.value is not None%}
<input class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" type="radio" id="question_{{ question.questionnb.value }}_4" name="question_{{ question.questionnb.value }}" value="{{ question.answer4.value|default_if_none:"" }}">
<label class="text-gray-700" for="question_{{ question.questionnb.value }}_4">{{ question.answer4.value }}</label>
{% endif %}
</div>
</div>
{% endfor %}
<button class="btn-red-lg w-56 mx-auto my-6" type="submit" value="submit">Envoyer</button>
</form>
{% endblock %}
和我的模型:
class Questions(models.Model):
questionnb = models.CharField(db_column='questionNb', max_length=10) # Field name made lowercase.
wording = models.CharField(max_length=500)
answer1 = models.CharField(max_length=255, blank=True, null=True)
answer2 = models.CharField(max_length=255, blank=True, null=True)
answer3 = models.CharField(max_length=255, blank=True, null=True)
answer4 = models.CharField(max_length=255, blank=True, null=True)
score = models.IntegerField(blank=True, null=True)
id_theme = models.ForeignKey('Themes', models.DO_NOTHING, db_column='id_theme')
createdat = models.DateTimeField(db_column='createdAt') # Field name made lowercase.
updatedat = models.DateTimeField(db_column='updatedAt') # Field name made lowercase.
class Meta:
managed = False
db_table = 'questions'
verbose_name_plural = "Questions"
class Scores(models.Model):
id_company = models.ForeignKey(Companies, models.DO_NOTHING, db_column='id_company')
id_question = models.ForeignKey(Questions, models.DO_NOTHING, db_column='id_question')
answer = models.CharField(max_length=255)
initialscore = models.IntegerField(db_column='initialScore', blank=True, null=True) # Field name made lowercase.
score = models.IntegerField(blank=True, null=True)
createdat = models.DateTimeField(db_column='createdAt') # Field name made lowercase.
updatedat = models.DateTimeField(db_column='updatedAt') # Field name made lowercase.
class Meta:
managed = False
db_table = 'scores'
verbose_name_plural = "Scores"
我意识到我实际上并没有在我的模板中包含我在 form.py 中定义的形式,但无论我做什么,我都无法让它以我想要的方式显示问题和答案。任何关于我为什么遇到问题的帮助或解释将不胜感激!我已经在这份问卷上卡住了一个星期,这让我发疯了。
答: 暂无答案
评论