Данные отображаются перед отправкой формы в Django 4.1
общество!
Моя цель - создать приложение, которое принимает некоторые данные от пользователя, выполняет машинное обучение и показывает результаты. Я хочу знать, был ли результат правильным для каждого предсказания. Поэтому я пытаюсь реализовать систему обратной связи, где пользователь мог бы отметить ответ как "правильный" или "неправильный", если он хочет это сделать.
Точнее говоря, у меня есть две кнопки: "предсказание похоже на истинное" и "предсказание было неверным". После нажатия на одну из этих кнопок у меня появляется всплывающий диалог с 3 чекбоксами, где пользователь может предоставить дополнительную информацию (это не обязательно).
forms.py
с этими флажками выглядит следующим образом:
from django import forms
class checkboxForm(forms.Form):
is_winner_reason_true = forms.BooleanField(required=False, label="The first place in importance coincides with reality", label_suffix='')
is_top5_reason_true = forms.BooleanField(required=False, label="Top 5 includes friends with high importance", label_suffix='')
is_other_reason_true = forms.BooleanField(required=False, label="Other", label_suffix='')
class checkboxFormFalsePred(forms.Form):
is_winner_reason_false = forms.BooleanField(required=False, label="The other person should come first in importance", label_suffix='')
is_top5_reason_false = forms.BooleanField(required=False, label="Top 5 includes friends with low importance", label_suffix='')
is_other_reason_false = forms.BooleanField(required=False, label="Other", label_suffix='')
Я хочу получить данные от нажатия на одну из двух кнопок (значение будет либо True
, либо False
), а затем, если пользователь решил оставить дополнительный отзыв, получить данные и от этого отзыва.
models.py
выглядит следующим образом:
from django.db import models
from allauth.socialaccount.models import SocialAccount
# Create your models here.
class ResultInfo(models.Model):
uid = models.ForeignKey(SocialAccount, on_delete=models.CASCADE)
friend_id = models.CharField(max_length = 16)
status = models.BooleanField() # whether the answer is True or False
status_description = models.CharField(max_length = 16, null=True, blank=True) # the additional info about the answer
result_info = models.JSONField()
Обратите внимание, что status_description
предназначен для получения дополнительных данных из 3 флажков. Первоначально он поставляется в виде словаря и выглядит как {'is_winner_reason_true': False, 'is_top5_reason_true': False, 'is_other_reason_true': False}
. Позже я преобразую его в ОДНУ категорию для хранения в базе данных в виде столбца status_description
.
Я создал AJAX вызовы для форм, чтобы предотвратить обновление страницы после отправки формы. Это делает свою работу, хотя и с 2-секундной задержкой.
Вот мой кусок HTML:
Кусок кода из views.py
:
if (request.method == 'POST') and (request.POST.get('content_id', None) == "looks-like-true"):
res_verif_form = checkboxForm(request.POST)
if (res_verif_form.is_valid()):
print(res_verif_form.cleaned_data)
return HttpResponse('success')
if (request.method == 'POST') and (request.POST.get('content_id', None) == "false-prediction"):
res_verif_form_false_pred = checkboxFormFalsePred(request.POST)
if (res_verif_form_false_pred.is_valid()):
print(res_verif_form_false_pred.cleaned_data)
res_verif_form = checkboxForm()
res_verif_form_false_pred = checkboxFormFalsePred()
Теперь возникает проблема.
Данные из дополнительных вопросов распечатываются после нажатия на одну из двух кнопок, но ДО отправки формы с этими дополнительными вопросами. Кроме того, после отправки формы я вообще не получаю никакой печатной информации. Только "POST /id4564365/results/ HTTP/1.1" 200 86111
в моей cmd.
Я пытался удалить эти строки:
$(document).ready(
$('.looks-like-true').click(function(){
$.ajax({
type:"POST",
url: "./",
data: {'content_id': $(this).attr('name'),'operation':'ans_submit','csrfmiddlewaretoken': '{{ csrf_token }}'},
success: function(response){
console.log("Success")
}
});
})
);
$(document).ready(
$('.false-prediction').click(function(){
$.ajax({
type:"POST",
url: "./",
data: {'content_id': $(this).attr('name'),'operation':'ans_submit','csrfmiddlewaretoken': '{{ csrf_token }}'},
success: function(response){
console.log("Success")
}
});
})
);
Затем я изменил views.py
на следующий вид:
if (request.method == 'POST'):
res_verif_form = checkboxForm(request.POST)
if (res_verif_form.is_valid()):
print(res_verif_form.cleaned_data)
return HttpResponse('success')
if (request.method == 'POST'):
res_verif_form_false_pred = checkboxFormFalsePred(request.POST)
if (res_verif_form_false_pred.is_valid()):
print(res_verif_form_false_pred.cleaned_data)
Что ж, это сработало. Теперь мои данные печатаются после отправки формы. Но проблема в том, что я не получаю данные от первых двух кнопок.
замените вход submit в модальной форме на обычную кнопку:
<input type="submit" value="Send" class="show-more-close-button">
<button class="show-more-close-button">Send</button>
~~
and link the eventListener to that button
Есть несколько способов решить эту проблему. Решение, которое я собираюсь предложить вам, включает в себя AJAX, хотя он не обязательно требуется для того, что вы хотите. Причина в том, что это именно то, что вы пытаетесь использовать, и потому что так проще получить желаемый результат.
Я начну с forms.py
, который кажется излишним. reason
- это переменная, основанная на пользовательском вводе, предоставляемом кнопками, поскольку к этой переменной можно получить доступ, а метки можно обрабатывать с помощью JavaScript, нет необходимости в двух формах:
class checkBoxForm(forms.Form):
is_winner = forms.BooleanField(
required=False,
label="The first place in importance coincides with reality",
label_suffix=''
)
is_top5 = forms.BooleanField(
required=False,
label="Top 5 includes friends with high importance",
label_suffix=''
)
is_other = forms.BooleanField(
required=False,
label="Other",
label_suffix=''
)
Даже с некоторыми изменениями в template.html
я старался сохранить как можно больше от вашего оригинального кода (хотя, честно говоря, я бы изменил некоторые имена).
В следующей части HTML, checkBoxForm
используется для простого отображения модальных входов, как вы делали изначально, но обратите внимание, что форма еще не отправлена:
<button class="looks-like-true" name="looks-like-true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>
<span class="looks-like-true-content">
Looks like true
</span>
</button>
<button class="false-prediction" name="false-prediction">
<span class="false-prediction-content">
Prediction is incorrect
</span>
</button>
<dialog class="verification-modal">
<p>Thanks for the feedback! What do you like about the prediction? </p><p>(Answer is optional, but more information would help us improve the predictive model)</p>
<div class="modal-checkboxes">
{{form.as_p}}
<button id="send-form" >Send</button>
</div>
</dialog>
Вместо этого форма отправляется через JavaScript (jQuery), собирая данные и отправляя их с помощью AJAX. Получение csrftoken
путем следования документации о как использовать CSRF защиту с AJAX и правильной установки ее на запрос header
:
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script>
const verifyModal = document.querySelector('.verification-modal');
let reason = null;
function getCookie(name) {
...
}
$('.looks-like-true').click(function() {
reason = true;
$("label[for='id_is_winner']").text("The first place in importance coincides with reality");
$("label[for='id_is_top5']").text("Top 5 includes friends with high importance");
verifyModal.showModal();
});
$('.false-prediction').click(function() {
reason = false;
$("label[for='id_is_winner']").text("The other person should come first in importance");
$("label[for='id_is_top5']").text("Top 5 includes friends with low importance");
verifyModal.showModal();
});
$('#send-form').click(function() {
is_winner = document.querySelector('#id_is_winner').checked;
is_top5 = document.querySelector('#id_is_top5').checked;
is_other = document.querySelector('#id_is_other').checked;
url = '/your/url/'
const csrftoken = getCookie('csrftoken');
headers = {'X-CSRFToken': csrftoken, 'Content-Type': 'application/json'}
data = {
'reason': reason,
'is_winner': is_winner,
'is_top5': is_top5,
'is_other': is_other,
}
$.ajax({
type:"POST",
url: url,
headers: headers,
data: JSON.stringify(data),
success: function(response){
console.log(response.msg);
verifyModal.close();
// reload or redirect or update page using JS...
location.reload();
// window.location.replace("https://stackoverflow.com/a/506004/7100120");
}
});
});
</script>
views.py
from .forms import checkBoxForm
from django.http import JsonResponse
import json
def your_view_name(request):
if request.method == 'POST':
data = json.loads(request.body)
reason = data.pop('reason')
print(f'Reason: {reason}')
print(f'Status Description: {data}')
# Output Sample
# Reason: True
# Status Description: {'is_winner': True, 'is_top5': False, 'is_other': True}
return JsonResponse({'msg': 'success'})
form = checkBoxForm()
context = {
'form': form,
}
return render(request, 'your_template.html', context)