Django考勤功能中insertion视图计算结果如何传递到files视图
Django跨视图传递临时计算结果实现方案
你遇到的是HTTP无状态特性导致的视图间数据无法直接共享问题,以下是3种常用的落地实现方案:
方案1:使用Session存储临时数据(推荐,实现最简单)
Django自带的session机制会将用户数据和当前会话绑定,不会出现多用户数据串扰问题,适合存储中等体量的临时计算结果。
代码修改:
- 修改
insertion视图,计算完出勤结果后序列化存入session:
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'] course_students = md.Student.objects.filter(course_id=lesson.course_id) present_students = [s for s in course_students if s.full_name in raw_text] absent_students = [s for s in course_students if s.full_name not in raw_text] # 新增:将计算结果序列化存入session,不能直接存模型对象 request.session['attendance_temp'] = { 'lesson_id': lesson.id, 'present_student_ids': [s.id for s in present_students], 'absent_student_ids': [s.id for s in absent_students] } 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)
- 修改
files视图,从session读取数据生成PDF:
def files(request): context = {} if request.method == 'POST': # 从session取临时出勤数据 attendance_temp = request.session.get('attendance_temp') if not attendance_temp: # 无有效数据时跳转回填页 return redirect('core:insertion') # 还原计算结果 lesson = md.Lesson.objects.get(id=attendance_temp['lesson_id']) present_students = md.Student.objects.filter(id__in=attendance_temp['present_student_ids']) absent_students = md.Student.objects.filter(id__in=attendance_temp['absent_student_ids']) # 此处编写你的PDF生成逻辑,生成后存储到media目录 # 生成完成后可删除临时session数据避免占用:del request.session['attendance_temp'] # 查询历史PDF文件存入context context.update({"active_gen": True}) return render(request, "core/files.html", context)
方案2:表单隐藏字段传递参数
适合不想依赖session的场景,将需要的参数通过预览页的隐藏表单提交到files视图。
代码修改:
- 修改
insertion.html中的确认表单,新增隐藏字段:
<form method="post" action="{% url "core:files" %}"> {% csrf_token %} <input type="hidden" name="lesson_id" value="{{ form.cleaned_data.lesson.id }}"> <input type="hidden" name="present_ids" value="{% for s in present_students %}{{ s.id }}{% if not forloop.last %},{% endif %}{% endfor %}"> <input type="hidden" name="absent_ids" value="{% for s in absent_students %}{{ s.id }}{% if not forloop.last %},{% endif %}{% endfor %}"> <button type="submit" class="btn btn-primary">OK</button> </form>
- 修改
files视图读取POST参数:
def files(request): context = {} if request.method == 'POST': lesson_id = request.POST.get('lesson_id') present_ids = request.POST.get('present_ids', '').split(',') absent_ids = request.POST.get('absent_ids', '').split(',') # 校验参数有效性后查询对应对象,生成PDF即可 context.update({"active_gen": True}) return render(request, "core/files.html", context)
注意:该方案参数对用户可见,敏感场景需要增加签名校验防止数据篡改。
方案3:临时数据库表存储
适合生产环境、需要留痕的场景,新增一个草稿状态的出勤记录表,insertion计算完后先存草稿,确认后再更新状态生成PDF。
内容的提问来源于stack exchange,提问作者André Carvalho
相关产品推荐
相关产品推荐

