def make_single_query(course_id, query, associate_group=None, origin=QueryOrigin.WIDGET): """ Make a single query for student information """ temp_query = TemporaryQuery( inclusion=INCLUSION_MAP.get(query.inclusion), course_id=course_id, module_state_key=query.entity_id, filter_on=query.filter, entity_name=query.entity_name, query_type=query.query_type, origin=QUERYORIGIN_MAP[origin], done=False, ) temp_query.save() try: if query.query_type == QueryType.SECTION: students = get_section_users(course_id, query) else: students = get_problem_users(course_id, query) bulk_queries = [] for student_id, dummy0 in students: row = StudentsForQuery( query=temp_query, inclusion=INCLUSION_MAP[query.inclusion], student=User.objects.filter(id=student_id)[0], ) bulk_queries.append(row) StudentsForQuery.objects.bulk_create(bulk_queries) TemporaryQuery.objects.filter(id=temp_query.id).update(done=True) # pylint: disable=no-member if associate_group is not None: grouped_temp = GroupedTempQueryForSubquery( grouped_id=associate_group, query_id=temp_query.id # pylint: disable=no-member ) grouped_temp.save() except Exception as error: TemporaryQuery.objects.filter(id=temp_query.id).update(done=None) # pylint: disable=no-member raise (error) # on roughly every 5th query, purge the temporary queries of anything older than rand = random.random() if rand > 0.8: purge_temporary_queries()
def make_existing_query(course_id, existing_queries): """ Aggregates single queries in a group into one unified set of students """ if existing_queries is None or len(existing_queries) == 0: return None ids_in_course = CourseEnrollment.objects.filter(course_id=course_id, is_active=1, ).values_list(DatabaseFields.USER_ID) query = User.objects.filter(id__in=ids_in_course) query_dct = defaultdict(list) for existing_query in existing_queries: if existing_query == "" or existing_query == QueryStatus.WORKING: continue inclusion_type = TemporaryQuery.objects.filter(id=existing_query) filtered_query = StudentsForQuery.objects.filter(query_id=existing_query).values_list( DatabaseFields.STUDENT_ID, flat=True, ) if inclusion_type.exists(): query_dct[inclusion_type[0].inclusion].append(filtered_query) for not_query in query_dct[INCLUSION_MAP.get(Inclusion.NOT)]: query = query.exclude(id__in=not_query) for and_query in query_dct[INCLUSION_MAP.get(Inclusion.AND)]: query = query.filter(id__in=and_query) or_query = User.objects.filter(id__in=ids_in_course) qobjs = Q() for orq in query_dct[INCLUSION_MAP.get(Inclusion.OR)]: qobjs = qobjs | (Q(id__in=orq)) # if there are only or queries, return the or_query if len(query_dct[INCLUSION_MAP.get(Inclusion.NOT)]) == 0 and len(query_dct[INCLUSION_MAP.get(Inclusion.AND)]) == 0: return or_query.filter(qobjs) # if there is no or_query, do not include it as it contains all the students in the course elif len(query_dct[INCLUSION_MAP.get(Inclusion.OR)]) == 0: return query else: return query | or_query.filter(qobjs)