django - Django 验证特定问题的答案
问题描述
概述:我想建立一个问答网站,用户必须在其中输入每个问题的正确答案。为此,我制作了 3 个模型:
class ProblemSet(models.Model):
id = models.IntegerField(primary_key=True)
class Problem(models.Model):
id = models.IntegerField(primary_key=True)
problem_set = models.ForeignKey(ProblemSet, on_delete=models.CASCADE)
question = models.TextField()
solution = models.TextField()
class Solve(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
problem_set = models.ForeignKey(ProblemSet, on_delete=models.CASCADE)
problem_id = models.ForeignKey(Problem, on_delete= models.CASCADE)
在求解模型中,如果有任何条目表示特定用户已解决该问题 ID。所以,我使用了通用的表单视图:
class IndexView(FormView):
form_class = ProblemForm
template_name = 'home/index.html'
success_url = reverse_lazy('index')
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated:
inner_qs = "fetch ids that are solved from Solve model"
problem_obj = Problem.objects\
.exclude(id__in=inner_qs)\
.order_by('id').first()
else:
#do something
context['question'] = problem_obj.question
return context
问题形式为:
from django import forms
class ProblemForm(forms.Form):
solution = forms.CharField(widget=forms.TextInput())
如何验证用户输入的答案是否正确?我确实在 def form_valid(self, form) 函数中获得了解决方案字段的值,但我应该如何处理它?我应该在 context 中传递 question_id 并在 form_valid 中查询数据库,还是应该将解决方案本身传递给 context 并在 form_valid() 方法中访问上下文数据以防止双重查询,但在这种方法中,我不确定这是否安全,因为我不不希望将解决方案传递给客户。
有什么优雅的方法可以做到这一点吗?
PS 在将用户输入的解决方案与该问题的数据库中的解决方案进行比较后,我在 Solve 表中添加一个条目,表示该特定用户已解决问题 ID。
解决方案
正在处理两个单独的FormView
请求:首先是学生获取带有问题要回答的表单时的 GET 请求。然后是学生提交问题答案时的 POST 请求。
现在 HTTP 是无状态的,因此您需要以某种方式跟踪第一个请求中提出的问题,以便您知道在接收 POST 请求时回答了哪个问题。
我想说的最简单的方法是实际上将 包含question_id
在表单本身中,作为隐藏的输入字段。这里没有真正的安全问题:question_id
即使隐藏也可以被学生操纵,但有什么意义呢?
所以这就是我要做的:
- 添加
problem
一个ModelChoiceField
带有HiddenInput
小部件的ProblemForm
.problem = forms.ModelChoiceField(queryset=Problem.objects.all(), widget=forms.HiddenInput())
problem
在你的get_inital()
方法中设置一个初始值IndexView
:def get_problem(self): # use also in get_context_data() to add the question if hasattr(self, 'problem'): return self.problem if self.request.user.is_authenticated: inner_qs = "fetch ids that are solved from Solve model" self.problem = Problem.objects\ .exclude(id__in=inner_qs)\ .order_by('id').first() return self.problem def get_initial(self): initial = super().get_initial() initial['problem'] = self.get_problem()} return initial
- 当表单被提交并且有效时,您会看到这
form.cleaned_data['problem']
是提交的问题。所以你可以在form_valid()
方法中使用它:def form_valid(self, form): problem = form.cleaned_data['problem'] # check that it hasn't been solved by the user already if problem.answer == form.cleaned_data['solution']: # create solve object for the user return redirect(...)
另一种方法是不将其包含在表单中,而是重新获取problem
in form_valid
(请注意,当表单将提交的内容映射到实际实例以填充其problem
时,上述方法中也会获取)。problem_id
problem
cleaned_data
推荐阅读
- aws-code-deploy - AWS Inspector 将 codedeploy-agent 报告为不受限制的守护进程
- c++ - 为什么存在 C++ 'auto' 不能代表多种类型的限制
- powershell - Get-MsalToken 错误 AADSTS7000218:请求正文必须包含以下参数:“client_assertion”或“client_secret”
- css - 如何使用 scss 在 Angular 11 项目中定位多个浏览器
- python - 手臂上的非法指令
- azure - 迁移 Azure 防火墙 VM
- spring-kafka - 如何配置 kafka 批处理使用者以使用 SeekToCurrentBatchErrorHandler 重试预定义的次数?
- kubernetes - 无法在 GCP 中创建 Kubernetes 集群
- php - Laravel Sanctum 多守卫奇怪的会话问题(用户共享会话/以多个用户身份登录)
- css - 使用 CSS 禁用制表位?