2015-08-02 32 views
5

Mam wymóg utworzenia formularza ankiety. Różne typy użytkowników będą miały inny zestaw pytań do odpowiedzi w ankiecie.Jak używać zestawów formularzy django do tworzenia aplikacji ankiet z pytaniami i odpowiedziami?

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) 

Odpowiedź urządzenia (rating) dla każdego pytania (cecha) jest albo tak albo nie reprezentować za pomocą przycisków radiowych. Po przesłaniu formularza użytkownik zapisuje odpowiedzi w tabeli oceny.

Jaki jest sposób osiągnięcia tego django?

Dzięki


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> 

To kod mam i działa teraz, ale nie jestem pewien, czy jego najlepszy sposób na rozwiązanie tego problemu? Mam wiele kodu w views.py, aby parsować dane postów ... Czy istnieje lepszy sposób na osiągnięcie tego?

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)) 

AKTUALIZACJA 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)) 
+0

Twój kod wydaje się być w porządku. Co masz na myśli * "sposób django osiągnięcia tego" *? – xyres

+1

Po pierwsze, nie publikowali Państwo żadnego kodu z 'views.py', który wywołuje waszą obawę, a po drugie - jeśli szukacie wskazówek dotyczących optymalizacji; wtedy lepiej byłoby opublikować go na [codereview.stackexchange.com] (http://codereview.stackexchange.com) –

Odpowiedz

1

Spróbuj użyć form.save() zamiast tworzenia obiektu Rating, wypełniając to pole, a następnie zapisać.

+0

Po drobnych modyfikacjach, udało mi się zrobić to, co chciałem. –