Commit dbb6ae08b95dcfedba9bb12a135875a5aec65efc
1 parent
e6cdad58
Exists in
master
and in
5 other branches
Criado o templete de atualizar enquete #77
Showing
6 changed files
with
253 additions
and
177 deletions
Show diff stats
poll/models.py
@@ -14,7 +14,7 @@ class Poll(Activity): | @@ -14,7 +14,7 @@ class Poll(Activity): | ||
14 | verbose_name_plural = _('Polls') | 14 | verbose_name_plural = _('Polls') |
15 | 15 | ||
16 | def __str__(self): | 16 | def __str__(self): |
17 | - return str(self.question) + str("/") + str(self.topic) | 17 | + return str(self.name) + str("/") + str(self.topic) |
18 | 18 | ||
19 | class Answer(models.Model): | 19 | class Answer(models.Model): |
20 | answer = models.CharField(_("Answer"), max_length = 200) | 20 | answer = models.CharField(_("Answer"), max_length = 200) |
@@ -27,4 +27,4 @@ class Answer(models.Model): | @@ -27,4 +27,4 @@ class Answer(models.Model): | ||
27 | verbose_name_plural = _('Answers') | 27 | verbose_name_plural = _('Answers') |
28 | 28 | ||
29 | def __str__(self): | 29 | def __str__(self): |
30 | - return str(self.question) + str("/") + str(self.topic) | 30 | + return str(self.answer) + str("/") + str(self.poll) |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +from rolepermissions.permissions import register_object_checker | ||
2 | +from amadeus.roles import SystemAdmin | ||
3 | + | ||
4 | +@register_object_checker() | ||
5 | +def edit_poll(role, user, poll): | ||
6 | + if (role == SystemAdmin): | ||
7 | + return True | ||
8 | + | ||
9 | + if (user in poll.topic.subject.professors.all()): | ||
10 | + return True | ||
11 | + | ||
12 | + return False |
@@ -0,0 +1,173 @@ | @@ -0,0 +1,173 @@ | ||
1 | +{% extends "topic/index.html" %} | ||
2 | + | ||
3 | +{% load i18n widget_tweaks dict_access static%} | ||
4 | + | ||
5 | +{% block style %} | ||
6 | + <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> | ||
7 | +{% endblock %} | ||
8 | + | ||
9 | +{% block content %} | ||
10 | +<!-- Modal (remember to change the ids!!!) --> | ||
11 | +<div class="modal fade" id="poll" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | ||
12 | + <div class="modal-dialog" role="document"> | ||
13 | + <div class="modal-content"> | ||
14 | + | ||
15 | + <!-- Modal Header --> | ||
16 | + <div class="modal-header"> | ||
17 | + | ||
18 | + <!-- Put your title here!!! --> | ||
19 | + <h4 class="modal-title" id="myModalLabel">{% trans "Create a Poll" %}</h4> | ||
20 | + | ||
21 | + </div> | ||
22 | + <!-- Modal Body --> | ||
23 | + <div class="modal-body"> | ||
24 | + | ||
25 | + <!-- Put ONLY your content here!!! --> | ||
26 | + <div class="conteiner"> | ||
27 | + <div class="row form-group"> | ||
28 | + <div class="col-md-1"> | ||
29 | + </br> | ||
30 | + <label><span class="glyphicon glyphicon-hand-right"></span></label> | ||
31 | + </div> | ||
32 | + <div class="col-md-10"> | ||
33 | + <div class="has-success"> | ||
34 | + <input form="form" type="text" name="{{form.name.name}}" {% if form.name.value != None %}value="{{form.name.value}}" {% endif %} class="form-control" placeholder='{% trans "Question?" %}'> | ||
35 | + <span class="help-block">{% trans "A Question to be answered" %}</span> | ||
36 | + </div> | ||
37 | + </div> | ||
38 | + {% if form.name.errors %} | ||
39 | + <div class="col-md-10 not_submited"> | ||
40 | + </br> | ||
41 | + <div class="alert alert-danger alert-dismissible" role="alert"> | ||
42 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | ||
43 | + <span aria-hidden="true">×</span> | ||
44 | + </button> | ||
45 | + <ul> | ||
46 | + {% for error in form.name.errors %} | ||
47 | + <li>{{ error }}</li> | ||
48 | + {% endfor %} | ||
49 | + </ul> | ||
50 | + </div> | ||
51 | + </div> | ||
52 | + {% endif %} | ||
53 | + </div> | ||
54 | + <form id="form" class="" action="" method="post"> | ||
55 | + {% csrf_token %} | ||
56 | + {% for key in keys %} | ||
57 | + <div class="row form-group"> | ||
58 | + <div class="col-md-1"> | ||
59 | + </br> | ||
60 | + <label><span class="glyphicon glyphicon-move"></span></label> | ||
61 | + </div> | ||
62 | + <div class="col-md-10"> | ||
63 | + <div class="has-success is-empty"> | ||
64 | + <input type="text" name="{{key}}" class="form-control" placeholder='{% trans "Answer" %}' value="{{ answers|value:key }}"> | ||
65 | + <span class="help-block">{% trans "Possible answer for the question" %}</span> | ||
66 | + </div> | ||
67 | + </div> | ||
68 | + <div class="col-md-1"> | ||
69 | + </br> | ||
70 | + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label> | ||
71 | + </div> | ||
72 | + </div> | ||
73 | + {% empty %} | ||
74 | + <div class="row form-group"> | ||
75 | + <div class="col-md-1"> | ||
76 | + </br> | ||
77 | + <label><span class="glyphicon glyphicon-move"></span></label> | ||
78 | + </div> | ||
79 | + <div class="col-md-10"> | ||
80 | + <div class="has-success is-empty"> | ||
81 | + <input type="text" name="1" class="form-control" placeholder='{% trans "Answer" %}'> | ||
82 | + <span class="help-block">{% trans "Possible answer for the question" %}</span> | ||
83 | + </div> | ||
84 | + </div> | ||
85 | + <div class="col-md-1"> | ||
86 | + </br> | ||
87 | + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label> | ||
88 | + </div> | ||
89 | + </div> | ||
90 | + {% endfor %} | ||
91 | + </form> | ||
92 | + </br> | ||
93 | + </div> | ||
94 | + <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button> | ||
95 | + <div class="row form-group"> | ||
96 | + <input form="form" class="form-control" type="date" name="{{form.limit_date.name}}" {% if form.limit_date.value != None %}value="{% if form.limit_date.value.year %}{{form.limit_date.value|date:'Y-m-d'}}{% else %}{{form.limit_date.value}}{% endif %}"{% endif %}> | ||
97 | + {% if form.limit_date.errors %} | ||
98 | + <div class="not_submited"> | ||
99 | + </br> | ||
100 | + <div class="alert alert-danger alert-dismissible" role="alert"> | ||
101 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | ||
102 | + <span aria-hidden="true">×</span> | ||
103 | + </button> | ||
104 | + <ul> | ||
105 | + {% for error in form.limit_date.errors %} | ||
106 | + <li>{{ error }}</li> | ||
107 | + {% endfor %} | ||
108 | + </ul> | ||
109 | + </div> | ||
110 | + </div> | ||
111 | + {% endif %} | ||
112 | + </div> | ||
113 | + | ||
114 | + </div> | ||
115 | + | ||
116 | + <!-- Modal Footer --> | ||
117 | + <div class="modal-footer"> | ||
118 | + | ||
119 | + <!-- Don't remove that!!! --> | ||
120 | + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | ||
121 | + | ||
122 | + <!-- Put curtom buttons here!!! --> | ||
123 | + <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button> | ||
124 | + </div> | ||
125 | + | ||
126 | + </div> | ||
127 | + </div> | ||
128 | +</div> | ||
129 | +<script type="text/javascript"> | ||
130 | +// Este js tem que ficar aqui se não a tag "trans" não vai funcionar | ||
131 | +$(window).ready(function() { // utilizado para abrir o modal quando tiver tido algum erro no preenchimento do formulario | ||
132 | + if($('.not_submited').length){ | ||
133 | + $('#poll').modal('show'); | ||
134 | + } | ||
135 | +}); | ||
136 | +$( "#form" ).sortable({ // utilizado para fazer a re-organização das respostas | ||
137 | + delay: 100, | ||
138 | + distance: 5, | ||
139 | + update: function( event, ui ) { | ||
140 | + var cont = 1; | ||
141 | + $("#form div div div input").each(function(){ | ||
142 | + $(this).attr('name',cont++); | ||
143 | + }); | ||
144 | + }, | ||
145 | +}); | ||
146 | +name = 2; | ||
147 | +$("#add").click(function() { // utilizado para adicionar um novo campo de resposta | ||
148 | + //Obs: não funcionar se estiver importado no head, só funciona se estiver no final do arquivo | ||
149 | + $("#form").append('\ | ||
150 | + <div class="row form-group">\ | ||
151 | + <div class="col-md-1">\ | ||
152 | + </br>\ | ||
153 | + <label><span class="glyphicon glyphicon-move"></span></label>\ | ||
154 | + </div>\ | ||
155 | + <div class="col-md-10">\ | ||
156 | + <div class="has-success is-empty">\ | ||
157 | + <input type="text" name="1" class="form-control" placeholder="{% trans "Answer" %}">\ | ||
158 | + <span class="help-block">{% trans "Possible answer for the question" %}</span>\ | ||
159 | + </div>\ | ||
160 | + </div>\ | ||
161 | + <div class="col-md-1">\ | ||
162 | + </br>\ | ||
163 | + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>\ | ||
164 | + </div>\ | ||
165 | + </div>'); | ||
166 | + var cont = 1; | ||
167 | + $("#form div div div input").each(function(){ | ||
168 | + $(this).attr('name',cont++); | ||
169 | + }); | ||
170 | +}); | ||
171 | +</script> | ||
172 | +<a href="" data-toggle="modal" data-target="#poll">modal</a> | ||
173 | +{% endblock content %} |
poll/templates/poll/poll.html
@@ -1,173 +0,0 @@ | @@ -1,173 +0,0 @@ | ||
1 | -{% extends "topic/index.html" %} | ||
2 | - | ||
3 | -{% load i18n widget_tweaks dict_access static%} | ||
4 | - | ||
5 | -{% block style %} | ||
6 | - <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> | ||
7 | -{% endblock %} | ||
8 | - | ||
9 | -{% block content %} | ||
10 | -<!-- Modal (remember to change the ids!!!) --> | ||
11 | -<div class="modal fade" id="poll" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | ||
12 | - <div class="modal-dialog" role="document"> | ||
13 | - <div class="modal-content"> | ||
14 | - | ||
15 | - <!-- Modal Header --> | ||
16 | - <div class="modal-header"> | ||
17 | - | ||
18 | - <!-- Put your title here!!! --> | ||
19 | - <h4 class="modal-title" id="myModalLabel">{% trans "Create a Poll" %}</h4> | ||
20 | - | ||
21 | - </div> | ||
22 | - <!-- Modal Body --> | ||
23 | - <div class="modal-body"> | ||
24 | - | ||
25 | - <!-- Put ONLY your content here!!! --> | ||
26 | - <div class="conteiner"> | ||
27 | - <div class="row form-group"> | ||
28 | - <div class="col-md-1"> | ||
29 | - </br> | ||
30 | - <label><span class="glyphicon glyphicon-hand-right"></span></label> | ||
31 | - </div> | ||
32 | - <div class="col-md-10"> | ||
33 | - <div class="has-success"> | ||
34 | - <input form="form" type="text" name="{{form.name.name}}" {% if form.name.value != None %}value="{{form.name.value}}" {% endif %} class="form-control" placeholder='{% trans "Question?" %}'> | ||
35 | - <span class="help-block">{% trans "A Question to be answered" %}</span> | ||
36 | - </div> | ||
37 | - </div> | ||
38 | - {% if form.name.errors %} | ||
39 | - <div class="col-md-10 not_submited"> | ||
40 | - </br> | ||
41 | - <div class="alert alert-danger alert-dismissible" role="alert"> | ||
42 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | ||
43 | - <span aria-hidden="true">×</span> | ||
44 | - </button> | ||
45 | - <ul> | ||
46 | - {% for error in form.name.errors %} | ||
47 | - <li>{{ error }}</li> | ||
48 | - {% endfor %} | ||
49 | - </ul> | ||
50 | - </div> | ||
51 | - </div> | ||
52 | - {% endif %} | ||
53 | - </div> | ||
54 | - <form id="form" class="" action="" method="post"> | ||
55 | - {% csrf_token %} | ||
56 | - {% for key in keys %} | ||
57 | - <div class="row form-group"> | ||
58 | - <div class="col-md-1"> | ||
59 | - </br> | ||
60 | - <label><span class="glyphicon glyphicon-move"></span></label> | ||
61 | - </div> | ||
62 | - <div class="col-md-10"> | ||
63 | - <div class="has-success is-empty"> | ||
64 | - <input type="text" name="{{key}}" class="form-control" placeholder='{% trans "Answer" %}' value="{{ answers|value:key }}"> | ||
65 | - <span class="help-block">{% trans "Possible answer for the question" %}</span> | ||
66 | - </div> | ||
67 | - </div> | ||
68 | - <div class="col-md-1"> | ||
69 | - </br> | ||
70 | - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label> | ||
71 | - </div> | ||
72 | - </div> | ||
73 | - {% empty %} | ||
74 | - <div class="row form-group"> | ||
75 | - <div class="col-md-1"> | ||
76 | - </br> | ||
77 | - <label><span class="glyphicon glyphicon-move"></span></label> | ||
78 | - </div> | ||
79 | - <div class="col-md-10"> | ||
80 | - <div class="has-success is-empty"> | ||
81 | - <input type="text" name="1" class="form-control" placeholder='{% trans "Answer" %}'> | ||
82 | - <span class="help-block">{% trans "Possible answer for the question" %}</span> | ||
83 | - </div> | ||
84 | - </div> | ||
85 | - <div class="col-md-1"> | ||
86 | - </br> | ||
87 | - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label> | ||
88 | - </div> | ||
89 | - </div> | ||
90 | - {% endfor %} | ||
91 | - </form> | ||
92 | - </br> | ||
93 | - </div> | ||
94 | - <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button> | ||
95 | - <div class="row form-group"> | ||
96 | - <input form="form" class="form-control" type="date" name="{{form.limit_date.name}}" {% if form.limit_date.value != None %}value="{{form.limit_date.value}}"{% endif %}> | ||
97 | - {% if form.limit_date.errors %} | ||
98 | - <div class="not_submited"> | ||
99 | - </br> | ||
100 | - <div class="alert alert-danger alert-dismissible" role="alert"> | ||
101 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | ||
102 | - <span aria-hidden="true">×</span> | ||
103 | - </button> | ||
104 | - <ul> | ||
105 | - {% for error in form.limit_date.errors %} | ||
106 | - <li>{{ error }}</li> | ||
107 | - {% endfor %} | ||
108 | - </ul> | ||
109 | - </div> | ||
110 | - </div> | ||
111 | - {% endif %} | ||
112 | - </div> | ||
113 | - | ||
114 | - </div> | ||
115 | - | ||
116 | - <!-- Modal Footer --> | ||
117 | - <div class="modal-footer"> | ||
118 | - | ||
119 | - <!-- Don't remove that!!! --> | ||
120 | - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | ||
121 | - | ||
122 | - <!-- Put curtom buttons here!!! --> | ||
123 | - <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button> | ||
124 | - </div> | ||
125 | - | ||
126 | - </div> | ||
127 | - </div> | ||
128 | -</div> | ||
129 | -<script type="text/javascript"> | ||
130 | -// Este js tem que ficar aqui se não a tag "trans" não vai funcionar | ||
131 | -$(window).ready(function() { // utilizado para abrir o modal quando tiver tido algum erro no preenchimento do formulario | ||
132 | - if($('.not_submited').length){ | ||
133 | - $('#poll').modal('show'); | ||
134 | - } | ||
135 | -}); | ||
136 | -$( "#form" ).sortable({ // utilizado para fazer a re-organização das respostas | ||
137 | - delay: 100, | ||
138 | - distance: 5, | ||
139 | - update: function( event, ui ) { | ||
140 | - var cont = 1; | ||
141 | - $("#form div div div input").each(function(){ | ||
142 | - $(this).attr('name',cont++); | ||
143 | - }); | ||
144 | - }, | ||
145 | -}); | ||
146 | -name = 2; | ||
147 | -$("#add").click(function() { // utilizado para adicionar um novo campo de resposta | ||
148 | - //Obs: não funcionar se estiver importado no head, só funciona se estiver no final do arquivo | ||
149 | - $("#form").append('\ | ||
150 | - <div class="row form-group">\ | ||
151 | - <div class="col-md-1">\ | ||
152 | - </br>\ | ||
153 | - <label><span class="glyphicon glyphicon-move"></span></label>\ | ||
154 | - </div>\ | ||
155 | - <div class="col-md-10">\ | ||
156 | - <div class="has-success is-empty">\ | ||
157 | - <input type="text" name="1" class="form-control" placeholder="{% trans "Answer" %}">\ | ||
158 | - <span class="help-block">{% trans "Possible answer for the question" %}</span>\ | ||
159 | - </div>\ | ||
160 | - </div>\ | ||
161 | - <div class="col-md-1">\ | ||
162 | - </br>\ | ||
163 | - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>\ | ||
164 | - </div>\ | ||
165 | - </div>'); | ||
166 | - var cont = 1; | ||
167 | - $("#form div div div input").each(function(){ | ||
168 | - $(this).attr('name',cont++); | ||
169 | - }); | ||
170 | -}); | ||
171 | -</script> | ||
172 | -<a href="" data-toggle="modal" data-target="#poll">modal</a> | ||
173 | -{% endblock content %} |
poll/urls.py
@@ -4,5 +4,6 @@ from . import views | @@ -4,5 +4,6 @@ from . import views | ||
4 | 4 | ||
5 | urlpatterns = [ | 5 | urlpatterns = [ |
6 | url(r'^create/$', views.CreatePoll.as_view(), name='create_poll'), | 6 | url(r'^create/$', views.CreatePoll.as_view(), name='create_poll'), |
7 | + url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdatePoll.as_view(), name='update_poll'), | ||
7 | 8 | ||
8 | ] | 9 | ] |
poll/views.py
@@ -16,14 +16,14 @@ from core.mixins import NotificationMixin | @@ -16,14 +16,14 @@ from core.mixins import NotificationMixin | ||
16 | from users.models import User | 16 | from users.models import User |
17 | from courses.models import Course, Topic | 17 | from courses.models import Course, Topic |
18 | 18 | ||
19 | -class CreatePoll(generic.CreateView): | 19 | +class CreatePoll(LoginRequiredMixin,generic.CreateView): |
20 | 20 | ||
21 | # login_url = reverse_lazy("core:home") | 21 | # login_url = reverse_lazy("core:home") |
22 | # redirect_field_name = 'next' | 22 | # redirect_field_name = 'next' |
23 | model = Poll | 23 | model = Poll |
24 | form_class = PollForm | 24 | form_class = PollForm |
25 | context_object_name = 'poll' | 25 | context_object_name = 'poll' |
26 | - template_name = 'poll/poll.html' | 26 | + template_name = 'poll/create_update.html' |
27 | # queryset = Course.objects.all() | 27 | # queryset = Course.objects.all() |
28 | success_url = reverse_lazy('core:home') | 28 | success_url = reverse_lazy('core:home') |
29 | # def get_queryset(self): | 29 | # def get_queryset(self): |
@@ -64,3 +64,66 @@ class CreatePoll(generic.CreateView): | @@ -64,3 +64,66 @@ class CreatePoll(generic.CreateView): | ||
64 | context['subject'] = course.subjects.all()[0] | 64 | context['subject'] = course.subjects.all()[0] |
65 | context['subjects'] = course.subjects.all() | 65 | context['subjects'] = course.subjects.all() |
66 | return context | 66 | return context |
67 | + | ||
68 | +class UpdatePoll(LoginRequiredMixin,generic.UpdateView): | ||
69 | + | ||
70 | + login_url = reverse_lazy("core:home") | ||
71 | + redirect_field_name = 'next' | ||
72 | + model = Poll | ||
73 | + form_class = PollForm | ||
74 | + context_object_name = 'poll' | ||
75 | + template_name = 'poll/create_update.html' | ||
76 | + success_url = reverse_lazy('core:home') | ||
77 | + | ||
78 | + def dispatch(self, *args, **kwargs): | ||
79 | + poll = get_object_or_404(Poll, slug = self.kwargs.get('slug')) | ||
80 | + if(not has_object_permission('edit_poll', self.request.user, poll)): | ||
81 | + return self.handle_no_permission() | ||
82 | + return super(UpdatePoll, self).dispatch(*args, **kwargs) | ||
83 | + | ||
84 | + def get_object(self, queryset=None): | ||
85 | + return get_object_or_404(Poll, slug = self.kwargs.get('slug')) | ||
86 | + | ||
87 | + def form_invalid(self, form,**kwargs): | ||
88 | + context = super(UpdatePoll, self).form_invalid(form) | ||
89 | + answers = {} | ||
90 | + for key in self.request.POST: | ||
91 | + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date'): | ||
92 | + answers[key] = self.request.POST[key] | ||
93 | + | ||
94 | + keys = sorted(answers) | ||
95 | + context.context_data['answers'] = answers | ||
96 | + context.context_data['keys'] = keys | ||
97 | + return context | ||
98 | + | ||
99 | + def form_valid(self, form): | ||
100 | + poll = self.object | ||
101 | + poll = form.save(commit = False) | ||
102 | + poll.answers.all().delete() | ||
103 | + poll.save() | ||
104 | + | ||
105 | + | ||
106 | + for key in self.request.POST: | ||
107 | + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date'): | ||
108 | + answer = Answer(answer=self.request.POST[key],order=key,poll=poll) | ||
109 | + answer.save() | ||
110 | + | ||
111 | + return super(UpdatePoll, self).form_valid(form) | ||
112 | + | ||
113 | + def get_context_data(self, **kwargs): | ||
114 | + context = super(UpdatePoll, self).get_context_data(**kwargs) | ||
115 | + poll = self.object | ||
116 | + context['course'] = poll.topic.subject.course | ||
117 | + context['subject'] = poll.topic.subject | ||
118 | + context['subjects'] = poll.topic.subject.course.subjects.all() | ||
119 | + | ||
120 | + answers = {} | ||
121 | + for answer in poll.answers.all(): | ||
122 | + # print (key.answer) | ||
123 | + answers[answer.order] = answer.answer | ||
124 | + | ||
125 | + keys = sorted(answers) | ||
126 | + context['answers'] = answers | ||
127 | + context['keys'] = keys | ||
128 | + | ||
129 | + return context |