Django中的表单渲染列表

时间:2019-05-13 16:56:05

标签: python django

我正在尝试在Django中创建一个基本的性格测试,作为工作中的概念验证。我是Django(和python)的新手,来自C#.NET背景。

我试图列出一个表单对象列表(填充有从数据库中存储的问题对象中提取的信息),然后将它们显示在HTML中。

这只是部分工作;我可以在for循环中单独渲染表单属性(例如,通过调用question.pk),但是使用标准Django {{form}}标签则无法渲染任何内容,而尝试提交表单列表会破坏整个事情。 / p>

我非常确定处理一大堆html中填充的一堆表单对象是一个问题,但是我不确定如何解决它。

我已经对表单集进行了一些研究,但是我找不到任何方法来使用数据库中的信息来预先填充表单项。

谢谢!

forms.py中的DISCQuestionForm:

class DISCQuestionForm(forms.Form):
    # create new form object from database question object
    def __init__(
            self,
            pk,
            disc_query,
            dom_answer,
            infl_answer,
            stead_answer,
            con_answer,
            ):
        super().__init__()
        self.pk = pk
        self.disc_query = disc_query
        self.dom_answer = dom_answer
        self.infl_answer = infl_answer
        self.stead_answer = stead_answer
        self.con_answer = con_answer
        self.disc_response = forms.DecimalField(
            max_value=4,
            widget=forms.NumberInput
            )

views.py中的

disc_create方法

# Create a new DISC assessment for current user
def disc_create(request, pk):
    profile = User.objects.get(pk=pk)
    user = int(profile.pk)
    name = profile.name
    rawquestionset = DISCQuestion.objects.all()

    discformset = []
    for item in rawquestionset:
        question = DISCQuestionForm(
            pk=item.pk,
            disc_query=item.disc_query,
            dom_answer=item.dom_answer,
            infl_answer=item.infl_answer,
            stead_answer=item.stead_answer,
            con_answer=item.con_answer,
        )
        discformset.append(question)

    if request.method == 'POST':
        questionset = discformset[request.POST]
        if questionset.is_valid():
            dom = 0
            infl = 0
            stead = 0
            con = 0

            for discquestion in questionset:
                if discquestion.disc_response == discquestion.dom_answer:
                    dom += 1
                if discquestion.disc_response == discquestion.infl_answer:
                    infl += 1
                if discquestion.disc_response == discquestion.stead_answer:
                    stead += 1
                if discquestion.disc_response == discquestion.con_answer:
                    con += 1

            disctest = DISCTest(
                user=user,
                name=name,
                dom=dom,
                infl=infl,
                stead=stead,
                con=con,
            )
            disctest.save()
    else:
        questionset = discformset

    context = {
        "pk": user,
        "name": name,
        "discquestionset": questionset
    }

    return render(request, "disc_create.html", context)

models.py中的DISCTest和DISCQuestion模型:

class DISCTest(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    name = user.name
    created_on = models.DateTimeField(auto_now_add=True)
    dom = models.DecimalField(max_digits=3, decimal_places=0)
    infl = models.DecimalField(max_digits=3, decimal_places=0)
    stead = models.DecimalField(max_digits=3, decimal_places=0)
    con = models.DecimalField(max_digits=3, decimal_places=0)


class DISCQuestion(models.Model):
    disc_query = models.TextField()
    disc_response = models.DecimalField(max_digits=1, decimal_places=0, null=True)
    dom_answer = models.DecimalField(max_digits=1, decimal_places=0)
    infl_answer = models.DecimalField(max_digits=1, decimal_places=0)
    stead_answer = models.DecimalField(max_digits=1, decimal_places=0)
    con_answer = models.DecimalField(max_digits=1, decimal_places=0)

最后是模板中的disc_create.html:

{% extends "base.html" %}

{% block page_content %}
<div class="col-md-8 offset-md-2">
    <h1>Take your DISC assessment</h1>
    <hr>
    <h3>Insert instructions here</h3>
    <hr>
    <form action="/assessment/create/{{pk}}/" method="post">
        {% csrf_token %}
        <div>
            {% for question in discquestionset %}
                <p>{{question.pk}}</p>
                <p>{{ question.disc_query }}</p>
                {{ form }}
            {% endfor %}
        </div>
        <button type="submit">Submit</button>
    </form>
</div>
{% endblock %}

1 个答案:

答案 0 :(得分:1)

您的DiscQuestionForm没有字段。 disc_response被定义为表单的属性,但是对于Django,它不是字段,因为它没有添加到self.fields中。而且form并没有在for循环的模板中定义,只有question(即表单)定义了,因此{{ question }}将在表单中打印任何字段。

但是问题是,每个question表单字段都将具有相同的“名称”属性,因为它们没有前缀以使其唯一。

您应该仔细阅读this document才能理解ModelFormmodelformset。基本上,您需要:

class DISCQuestionForm(forms.ModelForm):
    class Meta:
        model = DISCQuestion

    def __init__(...):
        ...

使用modelformset_factory创建一个适当的ModelFormSet,提交时可以用request.POST初始化。

DISCQuestionFormSet = modelformset_factory(DISCQuestionForm, form = DISCQuestionForm)  # note DISCQuestionForm not needed if you don't customise anything in your form.

并在您看来:

formset = DISCQuestFormSet(request.POST or None)

然后您可以在模板中循环浏览表单集中的表单:

{% for form in formset %}{{ form }}{% endfor %}