1
+ import re
2
+
1
3
from django .contrib .auth .mixins import UserPassesTestMixin
4
+ from django .db import transaction
2
5
from django .shortcuts import get_object_or_404
3
6
from django .urls import reverse
4
7
from django .views .generic import FormView , ListView
5
8
6
- from crowdsourcer .forms import OptionFormset , QuestionFormset
7
- from crowdsourcer .models import Option , Question , Section
9
+ import pandas as pd
10
+
11
+ from crowdsourcer .forms import OptionFormset , QuestionBulkUploadForm , QuestionFormset
12
+ from crowdsourcer .models import (
13
+ Option ,
14
+ PublicAuthority ,
15
+ Question ,
16
+ Response ,
17
+ ResponseType ,
18
+ Section ,
19
+ )
8
20
9
21
10
22
class SectionList (ListView ):
@@ -27,7 +39,7 @@ def get_success_url(self):
27
39
"session_urls:edit_options" ,
28
40
kwargs = {
29
41
"marking_session" : self .request .current_session .label ,
30
- "section_name" : "Buildings & Heating" ,
42
+ "section_name" : self . kwargs [ "section_name" ] ,
31
43
},
32
44
)
33
45
@@ -97,3 +109,129 @@ def get_context_data(self, **kwargs):
97
109
def form_valid (self , form ):
98
110
form .save ()
99
111
return super ().form_valid (form )
112
+
113
+
114
+ class QuestionBulkUpdateView (UserPassesTestMixin , FormView ):
115
+ template_name = "crowdsourcer/questions/question_bulk_upload.html"
116
+ form_class = QuestionBulkUploadForm
117
+
118
+ def test_func (self ):
119
+ return self .request .user .has_perm ("crowdsourcer.can_manage_users" )
120
+
121
+ def get_success_url (self ):
122
+ return reverse (
123
+ "session_urls:question_bulk_update" ,
124
+ kwargs = {
125
+ "marking_session" : self .request .current_session .label ,
126
+ "section_name" : self .kwargs ["section_name" ],
127
+ "question" : self .kwargs ["question" ],
128
+ },
129
+ )
130
+
131
+ def get_form (self ):
132
+ self .section = get_object_or_404 (
133
+ Section ,
134
+ title = self .kwargs ["section_name" ],
135
+ marking_session = self .request .current_session ,
136
+ )
137
+
138
+ q_parts = re .match (r"(\d+)([a-z]?)" , self .kwargs ["question" ])
139
+ q_kwargs = {
140
+ "section" : self .section ,
141
+ "number" : q_parts .groups ()[0 ],
142
+ }
143
+
144
+ if len (q_parts .groups ()) == 2 and q_parts .groups ()[1 ] != "" :
145
+ q_kwargs ["number_part" ] = q_parts .groups ()[1 ]
146
+
147
+ self .question = get_object_or_404 (Question , ** q_kwargs )
148
+ return self .form_class (
149
+ self .question .pk ,
150
+ [(rt .type , rt .type ) for rt in ResponseType .objects .all ()],
151
+ self .request .current_session ,
152
+ ** self .get_form_kwargs (),
153
+ )
154
+
155
+ def get_context_data (self , ** kwargs ):
156
+ context = super ().get_context_data (** kwargs )
157
+
158
+ context ["section" ] = self .section
159
+ context ["question" ] = self .question
160
+
161
+ return context
162
+
163
+ def form_valid (self , form ):
164
+ data = form .cleaned_data
165
+
166
+ question = get_object_or_404 (Question , id = data ["question" ])
167
+ stage = get_object_or_404 (ResponseType , type = data ["stage" ])
168
+ is_multi = question .question_type == "multiple_choice"
169
+
170
+ with transaction .atomic ():
171
+ for index , row in form .responses_df .iterrows ():
172
+ answer = row ["answer" ].strip ()
173
+ if answer == "-" :
174
+ continue
175
+
176
+ if is_multi :
177
+ answers = answer .split ("|" )
178
+
179
+ authority = PublicAuthority .objects .get (
180
+ name = row ["authority" ],
181
+ marking_session = self .request .current_session ,
182
+ )
183
+ if not is_multi :
184
+ option = Option .objects .get (question = question , description = answer )
185
+
186
+ try :
187
+ response = Response .objects .get (
188
+ question = question , response_type = stage , authority = authority
189
+ )
190
+ changed = False
191
+ opts = {}
192
+ for col in ["page_number" , "evidence" , "public_notes" ]:
193
+ if pd .isna (row [col ]) is False :
194
+ opts [col ] = row [col ]
195
+ if row [col ] != getattr (response , col ):
196
+ changed = True
197
+ if not is_multi and response .option != option :
198
+ changed = True
199
+ opts ["option" ] = option
200
+
201
+ if changed :
202
+ response .user = self .request .user
203
+ for k , v in opts .items ():
204
+ setattr (response , k , v )
205
+ response .save ()
206
+
207
+ if is_multi :
208
+ response .multi_option .clear ()
209
+ for a in answers :
210
+ option = Option .objects .get (
211
+ question = question , description = a
212
+ )
213
+ response .multi_option .add (option .id )
214
+
215
+ except Response .DoesNotExist :
216
+ opts = {
217
+ "question" : question ,
218
+ "response_type" : stage ,
219
+ "authority" : authority ,
220
+ "user" : self .request .user ,
221
+ }
222
+ for col in ["page_number" , "evidence" , "public_notes" ]:
223
+ if pd .isna (row [col ]) is False :
224
+ opts [col ] = row [col ]
225
+ if not is_multi :
226
+ opts ["option" ] = option
227
+
228
+ response = Response .objects .create (** opts )
229
+
230
+ if is_multi :
231
+ for a in answers :
232
+ option = Option .objects .get (
233
+ question = question , description = a
234
+ )
235
+ response .multi_option .add (option .id )
236
+
237
+ return super ().form_valid (form )
0 commit comments