如何使用django formsets创建一个包含问题和答案的调查应用程序?

时间:2015-08-02 16:47:02

标签: django django-models django-forms django-1.7

我需要创建一份调查表。不同类型的用户在调查中会有不同的问题集。

models.py

from django.contrib.auth.models import Group, User

from django.db import models

ANSWER_CHOICES = (
    ('0', 'No'),
    ('1', 'Yes')
)


class Survey(models.Model):
    name = models.CharField(max_length=100)
    group = models.ForeignKey(Group)

    def __str__(self):
        return self.name


class Feature(models.Model):
    name = models.CharField(max_length=150)
    survey = models.ForeignKey(Survey)

    def __str__(self):
        return self.name


class Rating(models.Model):
    rating = models.IntegerField(choices=ANSWER_CHOICES)
    feature = models.ForeignKey(Feature)
    rating_for = models.ForeignKey(User, related_name='rated_user')
    rating_by = models.ForeignKey(User, related_name='rated_by')

    def __str__(self):
        return str.format("%s - %s", self.feature, self.rating)

每个问题(功能)的答案(评级)是单选按钮的是或否。用户提交表单后,会将答案保存在评级表中。

实现这一目标的django方法是什么?

由于

forms.py

from django import forms
from django.forms import modelformset_factory, TextInput

from survey.models import Rating, Feature


class FeatureForm(forms.ModelForm):
    class Meta:
        model = Feature


class RatingForm(forms.ModelForm):
    class Meta:
    model = Rating


 FeatureFormSetBase = modelformset_factory(Feature, extra=0,
                                      widgets={'name':    TextInput(attrs={'readonly': True, })}
                                      )


class FeatureFormSet(FeatureFormSetBase):
    def add_fields(self, form, index):
        super(FeatureFormSet, self).add_fields(form, index)
        form.fields['is_checked'] = forms.BooleanField(required=False)

survey.html

 <form action="." method="post" accept-charset="utf-8">
        <ul class="list-group">
            {% for form in formset.forms %}
                <li class="list-group-item">
                    <div class="hidden"> {{ form.survey }}</div>
                    <span> {{ form.name }} </span>
                    <span> {{ form.id }} </span>
                    <span> {{ form.is_checked }} </span>
                </li>
            {% endfor %}

        </ul>
        <p>
            {{ formset.management_form }}
            {% csrf_token %}
            <button type="submit" name="action" value="save" class="btn btn-success">SAVE</button>
        </p>
    </form>

这是我的代码,它现在有效,但我不确定它是否是解决此问题的最佳方法?我在views.py中有很多代码来解析帖子数据......是否有更简洁的方法来实现这一目标?

view.py

def questionnaire(request):
q = Feature.objects.filter(survey__group=request.user.groups.all()[0]).select_related('survey')
if request.method == 'POST':
    action = request.POST.get('action')
    formset = FeatureFormSet(request.POST, queryset=q)

    if formset.is_valid():
        # iterate over all forms in the formset
        for form in formset.forms:
            if action == u'save':
                answer = form.cleaned_data.get('is_checked')
                print("Saving answer...")
                rating = Rating()
                rating.rating = answer
                rating.feature = form.cleaned_data.get('id')
                rating.rating_for = request.user
                rating.rating_by = request.user
                rating.save()

        redirect('useraccount_dashboard')

else:
    formset = FeatureFormSet(queryset=q)

return render_to_response('account_survey.html', {'formset': formset}, context_instance=RequestContext(request))

更新了views.py

def questionnaire(request, instance_id):
try:
    instance = SurveyInstance.objects.get(pk=instance_id, completed=False)
except SurveyInstance.DoesNotExist:
    raise Http404

if instance.rating_by != request.user:
    return HttpResponse('Unauthorized', status=401)

q = Feature.objects.filter(survey=instance.survey)
if request.method == 'POST':
    action = request.POST.get('action')
    formset = FeatureFormSet(request.POST, queryset=q)

    if formset.is_valid():
        # iterate over all forms in the formset
        for form in formset.forms:
            if action == u'save':
                answer = form.cleaned_data.get('is_checked')
                print("Saving answer...")
                rating = Rating()
                rating.rating = answer
                rating.feature = form.cleaned_data.get('id')
                rating.survey_instance = instance
                rating.save()

        instance.completed = True
        instance.save()
        messages.add_message(request, messages.INFO, 'Thank you for your feedback.')
        return redirect('useraccount_dashboard')

else:
    formset = FeatureFormSet(queryset=q)

return render_to_response('account_survey.html', {'formset': formset}, context_instance=RequestContext(request))

1 个答案:

答案 0 :(得分:1)

尝试使用form.save()而不是创建Rating对象,填写它的字段,然后保存。