这是我想要实现的一个过于简单的例子。让我们说我有这两个模型:
class Question(models.Model):
text = models.CharField(max_length=255)
class Answer(models.Model):
text = models.CharField(max_length=255)
question = models.ForeignKey(Question)
让我们说我在数据库中有成千上万的问题,但我希望每个用户只回答几个随机问题。所以,我的想法是创建一个动态表单。像这样:
class QuestionnaireForm(forms.Form):
def __init__(self, *args, **kwargs):
super(QuestionnaireForm, self).__init__(*args, **kwargs)
questions = list(Question.objects.all())
random.shuffle(questions) # it successfully validates without this line
questions = questions[:3]
for q in questions:
self.fields[q.text] = forms.CharField()
当我这样做时,我会根据需要随机提出三个问题,但表格不会验证。如果我评论出洗牌,一切都很好,但是每次我都会得到同样的问题。
从我所看到的情况来看,似乎Django在表单提交时再次调用__init__方法,因此重复洗牌并得到不同的问题。我试着仔细阅读文档,但是我没有设法解决这个问题的原因。
答案 0 :(得分:1)
questions = Question.objects.all().order_by('?')[:3]
要验证表单,它需要使用以下内容恢复相同的查询集:
questions = Question.objects.filter(pk__in=request.POST.getlist('ids'))
并将其形成。认为您还需要保存相同的顺序 - 然后您可以在表单中整理此列表。
<强>更新强>
您应该以某种方式在请求之间保存状态。您可以添加隐藏字段,添加URL参数,设置cookie,在用户的个人资料中保存信息 - 由您自己选择。 Tipical方式是设置隐藏输入(通常是默认的django ModelForm行为)。
因此,在第一次请求时,当您显示表单时 - 您将获得查询集,例如按pk
对其进行排序,将其置于表单并添加带ID的隐藏字段。当用户通过回答发出POST请求时 - 您将使用此ID恢复您的查询集,再次以相同的方式对其进行排序并将其置于表单中进行验证。