22import time
33import uuid
44
5+ import progressbar
56from django .core .management .base import BaseCommand
6- from django .db import transaction
77from django .db .models import Count
88from django .db .models import F
99
@@ -18,42 +18,47 @@ class Command(BaseCommand):
1818 def handle (self , * args , ** options ):
1919 start = time .time ()
2020 # Go through nodes that have assessment items with the same assessment_id
21+ logging .info ("Looking for nodes with invalid assessments..." )
2122 nodes = ContentNode .objects .filter (kind_id = 'exercise' ) \
2223 .annotate (
2324 num_ids = Count ('assessment_items__pk' ),
2425 num_assessment_ids = Count ('assessment_items__assessment_id' , distinct = True )
2526 ).exclude (num_ids = F ('num_assessment_ids' ))
27+ total = nodes .count ()
2628
27- with transaction .atomic ():
28- items_to_delete = []
29- for node in nodes :
30- # Go through each node's assessment items
31- for item in node .assessment_items .all ():
32- # Handle duplicate assessment ids
33- exclude_ids = [i .pk for i in items_to_delete ] + [item .pk ]
34- other_duplicate_assessment_items = node .assessment_items .filter (assessment_id = item .assessment_id ).exclude (pk__in = exclude_ids )
35-
36- if other_duplicate_assessment_items .exists ():
37- # Remove duplicates
38- if other_duplicate_assessment_items .filter (
39- question = item .question ,
40- answers = item .answers ,
41- hints = item .hints ,
42- raw_data = item .raw_data
43- ).exists ():
44- items_to_delete .append (item )
45-
46- # Get new ids for non-duplicates
47- else :
29+ logging .info ("Fixing {} nodes..." .format (total ))
30+
31+ items_to_delete = []
32+ bar = progressbar .ProgressBar (max_value = total )
33+ for i , node in enumerate (nodes ):
34+ # Go through each node's assessment items
35+ for item in node .assessment_items .all ():
36+ # Handle duplicate assessment ids
37+ exclude_ids = [i .pk for i in items_to_delete ] + [item .pk ]
38+ other_duplicate_assessment_items = node .assessment_items .filter (assessment_id = item .assessment_id ).exclude (pk__in = exclude_ids )
39+
40+ if other_duplicate_assessment_items .exists ():
41+ # Remove duplicates
42+ if other_duplicate_assessment_items .filter (
43+ question = item .question ,
44+ answers = item .answers ,
45+ hints = item .hints ,
46+ raw_data = item .raw_data
47+ ).exists ():
48+ items_to_delete .append (item )
49+
50+ # Get new ids for non-duplicates
51+ else :
52+ new_id = uuid .uuid4 ().hex
53+ while node .assessment_items .filter (assessment_id = new_id ).exists ():
4854 new_id = uuid .uuid4 ().hex
49- while node .assessment_items .filter (assessment_id = new_id ).exists ():
50- new_id = uuid .uuid4 ().hex
51- item .assessment_id = new_id
52- item .save ()
55+ item .assessment_id = new_id
56+ item .save ()
57+ bar .update (i )
5358
54- for item in items_to_delete :
55- if AssessmentItem .objects .filter (assessment_id = item .assessment_id , contentnode_id = item .contentnode_id ).exclude (pk = item .pk ).exists ():
56- item .delete ()
59+ logging .info ("Deduping identical assessments..." )
60+ for item in items_to_delete :
61+ if AssessmentItem .objects .filter (assessment_id = item .assessment_id , contentnode_id = item .contentnode_id ).exclude (pk = item .pk ).exists ():
62+ item .delete ()
5763
58- self .stdout .write ("Finished in {}" .format (time .time () - start ))
5964 logging .info ("Finished in {}" .format (time .time () - start ))
0 commit comments