Django - 从随机数据库条目创建动态表单

时间:2016-05-26 05:16:17

标签: python django forms django-forms django-validation

这是我想要实现的一个过于简单的例子。让我们说我有这两个模型:

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__方法,因此重复洗牌并得到不同的问题。我试着仔细阅读文档,但是我没有设法解决这个问题的原因。

1 个答案:

答案 0 :(得分:1)

Random ordering

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恢复您的查询集,再次以相同的方式对其进行排序并将其置于表单中进行验证。