我正在尝试在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 %}
答案 0 :(得分:1)
您的DiscQuestionForm
没有字段。 disc_response
被定义为表单的属性,但是对于Django,它不是字段,因为它没有添加到self.fields
中。而且form
并没有在for循环的模板中定义,只有question
(即表单)定义了,因此{{ question }}
将在表单中打印任何字段。
但是问题是,每个question
表单字段都将具有相同的“名称”属性,因为它们没有前缀以使其唯一。
您应该仔细阅读this document才能理解ModelForm
和modelformset
。基本上,您需要:
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 %}