def get_queryset(self): """ Overrides queryset. Shows feedback for studies you can edit, or feedback left on your created responses. A researcher can only add feedback to responses to studies they have permission to edit feedback for. """ qs = super().get_queryset() studies_for_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA ).values_list("id", flat=True) studies_for_preview = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA ).values_list("id", flat=True) consented_responses = get_consented_responses_qs().filter( (Q(study__id__in=studies_for_data) & Q(is_preview=False)) | (Q(study__id__in=studies_for_preview) & Q(is_preview=True)) ) response_ids = consented_responses.values_list("id", flat=True) return qs.filter( Q(response__id__in=response_ids) | Q(response__child__user=self.request.user) ).distinct()
def get_queryset(self): """ Overrides queryset. Shows 1) users that have responded to studies you can view and 2) your own user object """ all_users = super().get_queryset() # Users with can_read_all_user_data permissions can view all active users via the API if self.request.user.has_perm("accounts.can_read_all_user_data"): return all_users.filter(is_active=True) qs_ids = all_users.values_list("id", flat=True) studies_for_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA ).values_list("id", flat=True) studies_for_preview = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA ).values_list("id", flat=True) consented_responses = get_consented_responses_qs().filter( (Q(study__id__in=studies_for_data) & Q(is_preview=False)) | (Q(study__id__in=studies_for_preview) & Q(is_preview=True)) ) child_ids = consented_responses.values_list("child", flat=True) return User.objects.filter( (Q(children__id__in=child_ids) | Q(id=self.request.user.id)), Q(id__in=qs_ids), ).distinct()
def get_queryset(self): """ Overrides queryset. Show children that have 1) responded to studies you can view and 2) are your own children """ children_for_active_users = super().get_queryset() # Users with can_read_all_user_data permissions can view all children/demographics of active users via the API if self.request.user.has_perm("accounts.can_read_all_user_data"): return children_for_active_users # TODO: make helper for this, maybe on user studies_for_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA ).values_list("id", flat=True) studies_for_preview = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA ).values_list("id", flat=True) consented_responses = get_consented_responses_qs().filter( (Q(study__id__in=studies_for_data) & Q(is_preview=False)) | (Q(study__id__in=studies_for_preview) & Q(is_preview=True)) ) child_ids = consented_responses.values_list("child", flat=True) return children_for_active_users.filter( (Q(id__in=child_ids) | Q(user__id=self.request.user.id)) )
def get_queryset(self): """Queryset getter override. Largely duplicated from ChildViewSet but not completely, so we should duplicate before introducing the wrong abstraction. :return: The properly configured queryset. """ demographics_for_active_users = super().get_queryset() if self.request.user.has_perm("accounts.can_read_all_user_data"): return demographics_for_active_users studies_for_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA ).values_list("id", flat=True) studies_for_preview = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA ).values_list("id", flat=True) consented_responses = get_consented_responses_qs().filter( (Q(study__id__in=studies_for_data) & Q(is_preview=False)) | (Q(study__id__in=studies_for_preview) & Q(is_preview=True)) ) demographics_ids = consented_responses.values_list( "demographic_snapshot", flat=True ) return demographics_for_active_users.filter( (Q(id__in=demographics_ids) | Q(user__id=self.request.user.id)) )
def valid_responses(self): study_ids_real_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA).values_list("id", flat=True) study_ids_preview_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA).values_list("id", flat=True) return get_consented_responses_qs().filter( Q(study__id__in=study_ids_real_data, is_preview=False) | Q(study__id__in=study_ids_preview_data, is_preview=True))
def get_queryset(self): """ Restricts queryset to participants that a researcher has permission to view. """ studies = get_objects_for_user(self.request.user, "studies.can_view_study") valid_study_ids = studies.values_list("id", flat=True) valid_child_ids = (get_consented_responses_qs().filter( study__id__in=valid_study_ids).values_list("child", flat=True)) return (User.objects.filter( children__in=valid_child_ids).prefetch_related( Prefetch("children", queryset=Child.objects.filter( id__in=valid_child_ids))).distinct())
def get_queryset(self): """ Overrides queryset. Show children that have 1) responded to studies you can view and 2) are your own children """ children_for_active_users = super().get_queryset() # Users with can_read_all_user_data permissions can view all children/demographics of active users via the API if self.request.user.has_perm("accounts.can_read_all_user_data"): return children_for_active_users studies = get_objects_for_user(self.request.user, "studies.can_view_study_responses") consented_responses = get_consented_responses_qs().filter( study__in=studies) child_ids = consented_responses.values_list("child", flat=True) return children_for_active_users.filter( (Q(id__in=child_ids) | Q(user__id=self.request.user.id)))
def get_study_info(self): """ Returns paginated responses from a user with the study title, response id, completion status, and date modified. """ resps = ( get_consented_responses_qs() .filter(child__user=self.get_object()) .select_related("child__user") ) orderby = self.request.GET.get("sort", "-date_created") if orderby: if "date_created" in orderby: resps = resps.order_by(orderby) elif "completed" in orderby: resps = resps.order_by( orderby.replace("-", "") if "-" in orderby else "-" + orderby ) studies = [ { "modified": resp.date_modified, "created": resp.date_created, "study": resp.study, "name": resp.study.name, "completed": resp.completed, "response": resp, } for resp in resps ] if orderby and "name" in orderby: studies = sorted( studies, key=operator.itemgetter("name"), reverse=True if "-" in orderby else False, ) return self.paginated_queryset(studies, self.request.GET.get("page"), 10)
def get_queryset(self): """Queryset getter override. Largely duplicated from ChildViewSet but not completely, so we should duplicate before introducing the wrong abstraction. :return: The properly configured queryset. """ demographics_for_active_users = super().get_queryset() if self.request.user.has_perm("accounts.can_read_all_user_data"): return demographics_for_active_users studies = get_objects_for_user(self.request.user, "studies.can_view_study_responses") consented_responses = get_consented_responses_qs().filter( study__in=studies) demographics_ids = consented_responses.values_list( "demographic_snapshot", flat=True) return demographics_for_active_users.filter( (Q(id__in=demographics_ids) | Q(user__id=self.request.user.id)))
def get_queryset(self): """Overrides queryset. The overall idea is that we want to limit the responses one can retrieve through the API to two cases: 1) A user is in a session in the frameplayer, and they're hitting the response API to update their session. 2) A researcher is programmatically accessing the API to get responses for a given study XXX: HERE BE DRAGONS: this method is invoked with PATCH as well as GET requests! TODO: Break this out into multiple handlers. The logic-gymnastics is getting annoying. """ children_belonging_to_user = Child.objects.filter(user__id=self.request.user.id) # NESTED ROUTE: # GET /api/v1/studies/{STUDY_ID}/responses/?{Query string with pagination and child id} # This route gets accessed by: # 1) Participant sessions GETting history of responses for a study and a given child. # 2) Experimenters/parents programmatically GETting the responses facet of the *Study* # API to retrieve responses for a given study. if "study_uuid" in self.kwargs: study_uuid = self.kwargs["study_uuid"] study = get_object_or_404(Study, uuid=study_uuid) nested_responses = study.responses # CASE 1: Participant session, using query string with child ID. # Want same functionality regardless of whether user is a researcher. child_id = self.request.query_params.get("child", None) if child_id == "TEST_CHILD_DISREGARD": return Response.objects.none() # Preview route elif child_id is not None: nested_responses = nested_responses.filter( child__uuid=child_id, child__in=children_belonging_to_user ) # CASE 2: Experimenters/parents getting responses for study. else: if self.request.user.has_study_perms( StudyPermission.READ_STUDY_RESPONSE_DATA, study ) or self.request.user.has_study_perms( StudyPermission.READ_STUDY_PREVIEW_DATA, study ): consented_responses = study.responses_for_researcher( self.request.user ) # consented preview/real responses as appropriate nested_responses = nested_responses.filter( Q(pk__in=consented_responses) | Q(child__in=children_belonging_to_user) ).select_related( "child", "child__user", "study", "study__study_type", "demographic_snapshot", ) else: nested_responses = nested_responses.filter( child__in=children_belonging_to_user ) # Order by date created even though in some edge cases the current session will # not be the most recently created (e.g., same user made an additional attempt to # participate after starting this session) - updating # consent status will change date_modified return nested_responses.order_by("-date_modified") else: # NON-NESTED ROUTE # GET '/api/v1/responses/' or PATCH '/api/v1/responses/{RESPONSE_UUID}'. # This route gets accessed by: # 1) Participant sessions PATCHing (partial updating) ongoing response-sessions. # 2) Experimenters/parents programmatically GETting the Responses API studies_for_data = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_RESPONSE_DATA ).values_list("id", flat=True) studies_for_preview = studies_for_which_user_has_perm( self.request.user, StudyPermission.READ_STUDY_PREVIEW_DATA ).values_list("id", flat=True) consented_responses = get_consented_responses_qs().filter( (Q(study__id__in=studies_for_data) & Q(is_preview=False)) | (Q(study__id__in=studies_for_preview) & Q(is_preview=True)) ) response_queryset = Response.objects.filter( Q(child__in=children_belonging_to_user) # Case #1 | Q(pk__in=consented_responses) # Case #2 ).select_related( "child", "child__user", "study", "study__study_type", "demographic_snapshot", ) return response_queryset.order_by("-date_modified")