在 Django 中创建预览屏幕
Create a preview screen in Django
我有一个接收文本的 Django 表单(我从 Google 课堂复制:一堆学生评论)。我使用这些评论来提高学生的出勤率。我想要实现的是:
通过 GET 访问 /insertion/
url 用户收到页面表单作为响应,选择 class (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 现在是个谜。我无法得到的是如何在 files
视图中访问我在 insertion
视图中所做的昂贵计算。我该怎么做?
这是一个使用 session
框架的解决方案。
我们将在会话中保存计算,稍后在另一个视图中访问这些值。
对于初学者,我们将只保存学生的 ID (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
setting to use the PickleSerializer
. See notes about session serialization。
您可以将主键作为隐藏字段中的表单数据提交。只需根据您的主键选择合适的分隔符即可(例如,如果您使用 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>
然后在视图中,您可以从表单数据中获取视图中的 PK,然后请求。
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)
我有一个接收文本的 Django 表单(我从 Google 课堂复制:一堆学生评论)。我使用这些评论来提高学生的出勤率。我想要实现的是:
通过 GET 访问
/insertion/
url 用户收到页面表单作为响应,选择 class (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 现在是个谜。我无法得到的是如何在 files
视图中访问我在 insertion
视图中所做的昂贵计算。我该怎么做?
这是一个使用 session
框架的解决方案。
我们将在会话中保存计算,稍后在另一个视图中访问这些值。
对于初学者,我们将只保存学生的 ID (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
setting to use the PickleSerializer
. See notes about session serialization。
您可以将主键作为隐藏字段中的表单数据提交。只需根据您的主键选择合适的分隔符即可(例如,如果您使用 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>
然后在视图中,您可以从表单数据中获取视图中的 PK,然后请求。
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)