Django中能否同时使用return redirect和return render?如何重运行视图?
问题解答
1. 基础疑问解答
- 同一个Django视图函数中不能同时使用
return render和return redirect:Django视图只要执行到任意return语句就会直接终止运行,返回对应响应,不可能同时返回两种结果。 - 你现有代码存在核心逻辑错误:你使用的
keyboard库是运行在Django服务端的,只能监听到部署服务的那台机器的键盘输入,完全获取不到用户浏览器端的按键操作,哪怕你实现了页面刷新也达不到打字练习的功能效果。 - Django视图是请求驱动的,只有收到新的HTTP请求才会执行,所以render返回后要重新运行视图,本质上就是要让前端发起新的请求到当前视图地址,刷新、跳转、异步请求都可以实现这个效果。
2. 可落地的实现方案
方案1:最小改动实现页面自动重载(仅适合临时测试)
如果你暂时不想调整现有逻辑结构,可以在返回的渲染模板里添加自动刷新指令,不需要修改视图的返回逻辑:
在type/main.html的<head>标签中加入如下代码,即可实现页面加载后自动刷新:
<!-- content后的数字代表刷新间隔,单位为秒 --> <meta http-equiv="refresh" content="1">
该方案无法解决服务端监听键盘的核心逻辑问题,仅能测试页面重载效果。
方案2:符合Web开发逻辑的正确实现(推荐)
把按键监听逻辑移到前端,通过请求触发视图重跑,无需跳转即可实现效果:
步骤1:修改视图逻辑,移除服务端键盘监听
from django.shortcuts import render import os def text_display(request): char_no = request.session.get('char_no', -1) file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'text1.txt') with open(file_path, 'r', encoding='utf-8') as f: file_contents = f.read() # 处理前端传来的按键校验请求 if request.method == "POST": user_key = request.POST.get("user_key", "") char_no += 1 request.session['char_no'] = char_no if char_no >= len(file_contents): return render(request,'type/main.html',{"key_press":"Test is over", "text": file_contents}) # 校验按键是否正确 if user_key == file_contents[char_no]: ctx = {'text': file_contents, 'key_press':'You pressed the right key.'} else: ctx = {'text': file_contents, 'key_press':'You pressed the wrong key.'} return render(request, 'type/main.html', ctx) # 首次进入页面的初始化逻辑 request.session['char_no'] = -1 ctx = {'text': file_contents, 'key_press':'请开始输入'} return render(request, 'type/main.html', ctx)
步骤2:前端添加按键监听逻辑,每次按键触发视图重跑
在type/main.html中添加如下JS代码,用户每次按键就会异步发起请求到当前视图,拿到新的渲染结果直接替换页面,等价于刷新页面的效果:
<script> document.addEventListener('keydown', function(e) { e.preventDefault(); const form = new FormData(); form.append('user_key', e.key); fetch(window.location.href, { method: 'POST', body: form, headers: { 'X-CSRFToken': '{{ csrf_token }}' } }).then(res => res.text()).then(html => { document.documentElement.innerHTML = html; }) }) </script>
内容的提问来源于stack exchange,提问作者Abhyuday Vaish
相关产品推荐
相关产品推荐

