#python #django #django-views #django-templates #frontend
Вопрос:
У меня есть форма Django, которая получает текст (который я копирую из класса Google: кучу комментариев студентов). Я использую эти комментарии для оценки посещаемости студентов. Чего я хочу достичь, так это:
- Доступ
/insertion/
к URL-адресу через GET пользователь получает форму страницы в качестве ответа, чтобы выбрать класс (class01, class02 и т.д.) И пропустить текст - Когда пользователь нажимает представить в таком виде (метод POST), это перенаправить на тот же
/insertion/
URL, но теперь форма будет привязана к данным, прислана, и страницы показывает превью страницы (на основе логической переменной я, проходя через контекста), показывая, что студенты присутствуют, а какие отсутствуют на основе текста прошлого года. На этой странице под текстом типа «если все в порядке, нажмите кнопку»ОК», появится новая кнопка «Отправить». - После нажатия этой кнопки » ОК » будет сгенерирован pdf-файл, и пользователь будет перенаправлен на
/files/
URL-адрес, чтобы просмотреть сгенерированный pdf-файл и предыдущий сгенерированный pdf-файл.
views.py
def insertion(request):
context = {}
if request.method == 'GET':
form = AttendanceDataForm()
context.update({"form": form})
if request.method == 'POST':
form = AttendanceDataForm(request.POST)
context.update({"form": form})
if form.is_valid():
lesson = form.cleaned_data['lesson']
raw_text = form.cleaned_data['raw_text']
# Get course students
course_students = md.Student.objects.filter(course_id=lesson.course_id)
# Get present students based on raw text informed
present_students = [s for s in course_students if s.full_name in raw_text]
# Get absent students based on raw text informed
absent_students = [s for s in course_students if s.full_name not in raw_text]
context.update({
"present_students": present_students,
"absent_students": absent_students,
"render_preview": True
})
context.update({"active_freq": True})
return render(request, 'core/insertion.html', context)
def files(request):
context = {}
if request.method == 'POST':
# How can I access all expensive calculation I did in the previous view?
context.update({"active_gen": True})
return render(request, "core/files.html", context)
insertion.html
<div class="row">
<div class="col-12 col-md-6">
<h3>Informar Frequência</h3>
{% crispy form %}
</div>
<div class="col-12 col-md-6">
{% if render_preview %}
<div class="container">
<div class="row p-4 bg-white rounded mt-4">
<div class="col-12 col-sm-6">
<h5>Alunos presentes</h5>
<ul class="previewer-list">
{% for student in present_students %}
<li>{{ student.id }} - {{ student.full_name }}</li>
{% endfor %}
</ul>
</div>
<div class="col-12 col-sm-6">
<h5>Alunos ausentes</h5>
<ul class="previewer-list">
{% for student in absent_students %}
<li>{{ student.id }} - {{ student.full_name }}</li>
{% endfor %}
</ul>
</div>
</div>
<p class="mt-3">If everything's ok, hit the OK button</p>
<form method="post" action="{% url "core:files" %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary">OK</button>
</form>
</div>
{% endif %}
</div>
</div>
Я мог бы приступить к реализации 1 и 2, но 3 сейчас-это загадка. Чего я не мог понять, так это того, как я могу получить доступ к дорогостоящим расчетам, которые я делал в insertion
представлении в files
представлении. Как я могу это сделать?
Комментарии:
1. Вы можете достичь этого с
FormPreview
помощью fromdjango-formtools
— docs
Ответ №1:
Вот решение с использованием session
фреймворка.
Мы сохраним вычисления в сеансе и позже получим доступ к этим значениям в другом представлении.
Для начала мы просто сохраним идентификаторы ( pk
) учащихся вместо экземпляров учащихся, потому что они не сериализуемы в формате JSON [См. Примечание ниже].
def insertion(request):
# do expensive calucations ...
present_ids = [s.pk for s in present_students]
absent_ids = [s.pk for s in absent_students]
request.session['attendance_data'] = {
'present_ids': present_ids,
'absent_ids': absent_ids
}
def files(request):
attendance_data = request.session.get('attendance_data')
if not attendance_data:
# show error or something else ...
pass
present_students = md.Student.objects.filter(
pk__in=attendance_data['present_ids']
)
absent_students = md.Student.objects.filter(
pk__in=attendance_data['absent_ids']
)
# generate the pdf ...
Примечание: При желании вы также можете сохранить экземпляры учащихся в сеансе, но вам придется изменить SESSION_SERIALIZER
настройки, чтобы использовать PickleSerializer
. См.Примечания о сериализации сеанса.
Ответ №2:
Вы можете отправить первичные ключи в виде данных формы в скрытых полях. Просто выберите подходящий разделитель на основе вашего первичного ключа (например, не разделяйте дефисом, если вы используете первичный ключ GUID).
<form method="post" action="{% url "core:files" %}">
{% csrf_token %}
<input type="hidden"
name="present"
value="{% for s in present_students %}{{ s.pk }},{% endfor %}"
>
<input type="hidden"
name="absent"
value="{% for s in absent_students %}{{ s.pk }},{% endfor %}"
>
<button type="submit" class="btn btn-primary">OK</button>
</form>
Затем в представлении вы можете выбрать PKS в представлении из данных формы, а затем запросить.
def files(request):
context = {}
if request.method == 'POST':
present_pks = request.POST.pop('present').split(',')[:-1]
absent_pks = request.POST.pop('absent').split(',')[:-1]
# do type conversions if needed
...
# Because we already have the pks separated, we can combine them
# for the query in order to do just 1 query
course_students = md.Student.objects.filter(pk__in=present_pks absent_pks).all()
absent_students = []
present_students = []
for student in course_students:
if student.pk in absent_pks:
absent_students.append(student)
else:
present_students.append(student)