4
4
from django .conf import settings
5
5
from django .contrib .auth .models import User
6
6
from django .core .management .base import BaseCommand
7
+ from django .db import transaction
7
8
from django .db .models import Q
8
9
9
10
import pandas as pd
@@ -113,6 +114,12 @@ def add_arguments(self, parser):
113
114
"--make_assignments" , action = "store_true" , help = "assign councils to users"
114
115
)
115
116
117
+ parser .add_argument (
118
+ "--dry_run" ,
119
+ action = "store_true" ,
120
+ help = "run everything and then undo changes. Helpful to check if assigment weighting is good" ,
121
+ )
122
+
116
123
def get_df (self , filename ):
117
124
df = pd .read_csv (
118
125
filename ,
@@ -149,32 +156,7 @@ def get_assignment_count(self, user_type):
149
156
num_councils = self .num_council_map .get (user_type )
150
157
return num_councils
151
158
152
- def handle (
153
- self ,
154
- quiet : bool = False ,
155
- file : str = None ,
156
- session : str = None ,
157
- col_names : str = None ,
158
- response_type : str = None ,
159
- assignment_map : str = None ,
160
- authority_map : str = None ,
161
- * args ,
162
- ** options ,
163
- ):
164
- if file is None :
165
- file = self .volunteer_file
166
-
167
- self .set_cols (col_names )
168
- self .set_assignment_map (assignment_map )
169
- self .set_authority_map (authority_map )
170
-
171
- df = self .get_df (file )
172
-
173
- if response_type is None :
174
- response_type = self .response_type
175
-
176
- session = MarkingSession .objects .get (label = session )
177
- rt = ResponseType .objects .get (type = response_type )
159
+ def add_users_and_assignments (self , df , response_type , session , rt , options ):
178
160
179
161
bad_councils = []
180
162
for index , row in df .iterrows ():
@@ -300,28 +282,70 @@ def handle(
300
282
response_type = rt ,
301
283
)
302
284
303
- council_count = PublicAuthority .objects .filter (
304
- marking_session = session , do_not_mark = False
305
- ).count ()
306
- for section in Section .objects .filter (marking_session = session ).all ():
307
- assigned = Assigned .objects .filter (section = section ).count ()
308
- if assigned != council_count :
309
- self .stdout .write (
310
- f"{ RED } Not all councils assigned for { section .title } ({ assigned } /{ council_count } ){ NOBOLD } "
311
- )
312
- else :
313
- self .stdout .write (f"{ GREEN } All councils and sections assigned{ NOBOLD } " )
314
-
315
- volunteer_count = User .objects .filter (
316
- marker__marking_session = session , marker__response_type = rt
317
- ).count ()
318
- assigned_count = (
319
- Assigned .objects .filter (user__is_superuser = False )
320
- .distinct ("user_id" )
321
- .count ()
322
- )
285
+ return bad_councils
286
+
287
+ def handle (
288
+ self ,
289
+ quiet : bool = False ,
290
+ file : str = None ,
291
+ session : str = None ,
292
+ col_names : str = None ,
293
+ response_type : str = None ,
294
+ assignment_map : str = None ,
295
+ authority_map : str = None ,
296
+ * args ,
297
+ ** options ,
298
+ ):
299
+ if file is None :
300
+ file = self .volunteer_file
301
+
302
+ self .set_cols (col_names )
303
+ self .set_assignment_map (assignment_map )
304
+ self .set_authority_map (authority_map )
305
+
306
+ df = self .get_df (file )
307
+
308
+ if response_type is None :
309
+ response_type = self .response_type
310
+
311
+ session = MarkingSession .objects .get (label = session )
312
+ rt = ResponseType .objects .get (type = response_type )
313
+
314
+ with transaction .atomic ():
315
+ bad_councils = self .add_users_and_assignments (
316
+ df , response_type , session , rt , options
317
+ )
318
+
319
+ council_count = PublicAuthority .objects .filter (
320
+ marking_session = session , do_not_mark = False
321
+ ).count ()
322
+ for section in Section .objects .filter (marking_session = session ).all ():
323
+ assigned = Assigned .objects .filter (section = section ).count ()
324
+ if assigned != council_count :
325
+ self .stdout .write (
326
+ f"{ RED } Not all councils assigned for { section .title } ({ assigned } /{ council_count } ){ NOBOLD } "
327
+ )
328
+ else :
329
+ self .stdout .write (
330
+ f"{ GREEN } All councils and sections assigned{ NOBOLD } "
331
+ )
332
+
333
+ volunteer_count = User .objects .filter (
334
+ marker__marking_session = session , marker__response_type = rt
335
+ ).count ()
336
+ assigned_count = (
337
+ Assigned .objects .filter (user__is_superuser = False )
338
+ .distinct ("user_id" )
339
+ .count ()
340
+ )
341
+
342
+ self .stdout .write (
343
+ f"{ assigned_count } /{ volunteer_count } users assigned marking"
344
+ )
345
+
346
+ if options ["dry_run" ]:
347
+ transaction .set_rollback (True )
323
348
324
- self .stdout .write (f"{ assigned_count } /{ volunteer_count } users assigned marking" )
325
349
if not options ["add_users" ]:
326
350
self .stdout .write (
327
351
f"{ YELLOW } Dry run, no users added, call with --add_users to add users{ NOBOLD } "
@@ -331,6 +355,11 @@ def handle(
331
355
f"{ YELLOW } Dry run, no assignments made, call with --make_assignments to make them{ NOBOLD } "
332
356
)
333
357
358
+ if options ["dry_run" ]:
359
+ self .stdout .write (
360
+ f"{ YELLOW } Dry run, no changes made, call without --dry_run to make changes{ NOBOLD } "
361
+ )
362
+
334
363
if len (bad_councils ):
335
364
self .stdout .write ("Bad councils are:" )
336
365
for c in bad_councils :
0 commit comments