为什么我的 Django 表单答案被多次保存并删除另一个数据库表的内容?

Why are my Django form answers being saved multiple times and deleting the contents of another DB table?

提问人:buryj 提问时间:11/17/2023 最后编辑:buryj 更新时间:11/17/2023 访问量:27

问:

我是 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 中定义的形式,但无论我做什么,我都无法让它以我想要的方式显示问题和答案。任何关于我为什么遇到问题的帮助或解释将不胜感激!我已经在这份问卷上卡住了一个星期,这让我发疯了。

django django 模型 django 表单

评论


答: 暂无答案