Exemplo n.º 1
0
def get_student_reputation(req):
    """
    Returns the student information along with the convincing rationales
    criterion.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                id: int
                    Student pk

    Returns
    -------
    Either
        JSONResponse
            Response with json data:
                {
                    email : str
                        Student email
                    last_login : str
                        Date of last login in isoformat
                    popularity : float
                        Value of the convincing rationales criterion

                }
        HttpResponse
            Error response
    """
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (id_,), _ = args

    try:
        student = Student.objects.get(pk=id_)
    except Student.DoesNotExist:
        return response_400(
            req,
            msg=_("The student couldn't be found."),
            logger_msg=(
                "The student with pk {} couldn't be found.".format(id_)
            ),
            log=logger.warning,
        )
    criteria = {
        c.name: student.evaluate_reputation(c.name)
        for c in ReputationType.objects.get(type="student").criteria.all()
    }

    return JsonResponse(
        {
            "email": student.student.email,
            "last_login": student.student.last_login.isoformat()
            if student.student.last_login is not None
            else None,
            "criteria": criteria,
        }
    )
Exemplo n.º 2
0
def remove_gradebook_task(req, teacher):
    """
    Removes the failed gradebook task from the running tasks.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                task_id: str
                    Id of the celery task responsible for the gradebook
                    generation sent with the first request for a gradebook
    teacher : Teacher
        Teacher instance returned by `teacher_required` (not used)

    Returns
    -------
    HttpResponse
        Empty 200 response
    """
    args = get_json_params(req, args=["task_id"])
    if isinstance(args, HttpResponse):
        return args
    (task_id, ), _ = args

    try:
        task = RunningTask.objects.get(id=task_id)
    except RunningTask.DoesNotExist:
        return HttpResponse("")

    task.delete()
    return HttpResponse("")
Exemplo n.º 3
0
def teacher_reputation(req):
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (teacher_id, ), __ = args

    try:
        teacher = Teacher.objects.get(pk=teacher_id)
    except (Teacher.DoesNotExist, AttributeError):
        return response_400(
            req,
            msg=_("This teacher doesn't exist."),
            logger_msg=(
                "Tried to obtain teacher with pk {}".format(teacher_id)),
            log=logger.warning,
        )

    if teacher.reputation is None:
        teacher.reputation = Reputation.create(teacher)
        teacher.save()

    reputation, reputations = teacher.reputation.evaluate()

    data = {"reputation": reputation, "reputations": reputations}

    return JsonResponse(data, status=200)
Exemplo n.º 4
0
def test_get_json_params__missing_arg(rf):
    data = {"arg1": 1}

    req = rf.post("/test", json.dumps(data), content_type="application/json")

    args = get_json_params(req, args=["arg1", "arg2"])
    assert isinstance(args, HttpResponse)
Exemplo n.º 5
0
def test_get_json_params__wrong_data(rf):
    data = {"arg1": 1, "arg2": 2}

    req = rf.post("/test", data)

    args = get_json_params(req, args=["arg1", "arg2"])
    assert isinstance(args, HttpResponse)
Exemplo n.º 6
0
def collection_add_assignment(request, teacher):
    """
    creates a collection with assignments from a student group
    used in group detail view
    """
    args = get_json_params(request, args=["group_pk"])
    if isinstance(args, HttpResponse):
        return args
    (group_pk,), _ = args

    student_group = get_object_or_404(StudentGroup, pk=group_pk)

    title = (student_group.title + "'s curriculum")[:40]
    description = (
        "This collection contains all assignments that have been assigned to "
        + student_group.title
        + "'s students."
    )[:200]

    collection = Collection.objects.create(
        discipline=teacher.disciplines.first(),
        owner=teacher,
        title=title,
        description=description,
    )

    student_group_assignments = student_group.studentgroupassignment_set.all()
    for assignment in student_group_assignments:
        if assignment.assignment not in collection.assignments.all():
            collection.assignments.add(assignment.assignment)
    return JsonResponse({"pk": collection.pk})
Exemplo n.º 7
0
def student_reputation(req):
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (student_id, ), __ = args

    if req.user.student.pk != student_id:
        return response_403(
            req,
            msg=_("You don't have access to this resource."),
            logger_msg=(
                "Access to reputation of student {} from student {}.".format(
                    student_id, req.user.student.pk)),
            log=logger.warning,
        )

    try:
        student = Student.objects.get(pk=student_id)
    except Student.DoesNotExist:
        return response_400(
            req,
            msg=_("This student doesn't exist."),
            logger_msg=(
                "Tried to obtain student with pk {}".format(student_id)),
            log=logger.warning,
        )

    if student.reputation is None:
        student.reputation = Reputation.create(student)
        student.save()

    reputation, reputations = student.reputation.evaluate()

    data = {"reputation": reputation, "reputations": reputations}
    return JsonResponse(data, status=200)
Exemplo n.º 8
0
def collections(req, teacher):
    """
    View that returns featured collections in the teacher's disciplines.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            optional parameters:
                n: int (default : 5)
                    Number of questions to return
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    JsonResponse
        Response with json data:
            {
                "collections": [
                    {
                        title : str
                            Collection title
                        discipline : str
                            Collection discipline
                        n_assignments : int
                            Number of assignments in collection
                        n_followers : str
                            Number of followers for the collection
                    }
                ]
            }
    """
    args = get_json_params(req, opt_args=["n"])
    if isinstance(args, HttpResponse):
        return args
    _, (n, ) = args

    if n is None:
        n = 5

    data = {
        "collections": [{
            "title": collection.title,
            "description": collection.description,
            "discipline": collection.discipline.title,
            "n_assignments": collection.assignments.count(),
            "n_followers": collection.n_followers,
        } for collection in Collection.objects.filter(
            discipline__in=teacher.disciplines.all()).annotate(
                n_followers=models.Count("followers")).order_by(
                    "-n_followers").all()[:n]]
    }
    return JsonResponse(data)
Exemplo n.º 9
0
def remove_dalite_message(req, teacher):
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (id_, ), _ = args
    try:
        message = UserMessage.objects.get(pk=id_)
        message.showing = False
        message.save()
    except UserMessage.DoesNotExist:
        pass
    return HttpResponse("")
Exemplo n.º 10
0
def get_gradebook_task_result(req, teacher):
    """
    Returns a 200 response if the gradebook is ready. If not, will return a 202
    response.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                task_id: str
                    Id of the celery task responsible for the gradebook
                    generation sent with the first request for a gradebook
    teacher : Teacher
        Teacher instance returned by `teacher_required` (not used)

    Returns
    -------
    HttpResponse
        Either
            Empty 200 response (task done)
            Empty 202 response (accepted, still processing)
            Empty 500 response (error)
    """
    args = get_json_params(req, args=["task_id"])
    if isinstance(args, HttpResponse):
        return args
    (task_id, ), _ = args

    result = AsyncResult(task_id)

    try:
        if result.ready():
            return HttpResponse("", status=200)
        else:
            return HttpResponse("", status=202)
    except AttributeError:
        return response_500(
            req,
            msg="",
            logger_msg="Error computing gradebook for teacher {}".format(
                teacher.user.username) + " and task {}.".format(task_id),
            log=logger.warning,
            use_template=False,
        )
Exemplo n.º 11
0
def test_get_json_params(rf):
    data = {"arg1": 1, "arg2": 2, "opt_arg1": 3, "opt_arg2": 4}

    req = rf.post("/test", json.dumps(data), content_type="application/json")

    args = get_json_params(
        req,
        args=["arg1", "arg2"],
        opt_args=["opt_arg1", "opt_arg2", "opt_arg3"],
    )
    assert not isinstance(args, HttpResponse)
    args, opt_args = args

    assert data["arg1"] == args[0]
    assert data["arg2"] == args[1]
    assert data["opt_arg1"] == opt_args[0]
    assert data["opt_arg2"] == opt_args[1]
    assert opt_args[2] is None
Exemplo n.º 12
0
def reputation(req):
    args = get_json_params(req, args=["reputation_type"])
    if isinstance(args, HttpResponse):
        return args
    (reputation_type, ), __ = args

    if reputation_type == "teacher":
        return teacher_reputation(req)
    if reputation_type == "student":
        return student_reputation(req)
    else:
        return response_400(
            req,
            msg=_("This isn't a supported reputation type."),
            logger_msg=("The sent data used reputation type {} ".format(
                reputation_type) + "which isn't supported."),
            log=logger.warning,
        )
Exemplo n.º 13
0
def unsubscribe_from_thread(req, teacher):
    """
    Unsubscribes the `teacher` from a thread (won't appear in the messages).

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                id: int
                    Thread primary key
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    HttpResponse
        Error response or empty 200 response
    """
    args = get_json_params(req, args=["id"])
    if isinstance(args, HttpResponse):
        return args
    (id_, ), _ = args
    try:
        thread = ForumThread.objects.get(pk=id_)
    except ForumThread.DoesNotExist:
        return response_400(
            req,
            msg=translate("The thread couldn't be found."),
            logger_msg=(
                "The thread with pk {} couldn't be found.".format(id_)),
            log=logger.warning,
        )

    thread.subscriptions.filter(user=teacher.user).delete()

    return HttpResponse("")
Exemplo n.º 14
0
def flag_question(req, teacher):
    args = get_json_params(req, args=["id", "reason"])
    if isinstance(args, HttpResponse):
        return args
    (question_id, reason), _ = args

    try:
        question = Question.objects.get(id=question_id)
    except Question.DoesNotExist:
        return response_400(
            req,
            msg=translate("The question couldn't be found."),
            logger_msg=("The question with pk {} couldn't be found.".format(
                question_id)),
            log=logger.warning,
        )

    try:
        flag_reason = QuestionFlagReason.objects.get(title=reason)
    except Question.DoesNotExist:
        return response_400(
            req,
            msg=translate("The flag reason couldn't be found."),
            logger_msg=(
                "The question flag reason with title {} ".format(reason) +
                "couldn't be found."),
            log=logger.warning,
        )

    flag = QuestionFlag.objects.create(question=question,
                                       user=teacher.user,
                                       flag=True)
    flag.flag_reason.add(flag_reason)
    logger.info("Question flagged!")

    return HttpResponse("")
Exemplo n.º 15
0
def mark_message_read(req, teacher):
    """
    Unsubscribes the `teacher` from a thread (won't appear in the messages).

    Parameters
    ----------
    req : HttpRequest
        Request with:
            optional parameters:
                id: int
                    Thread primary key
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    HttpResponse
        Error response or empty 200 response
    """
    args = get_json_params(req, opt_args=["id"])
    if isinstance(args, HttpResponse):
        return args
    _, (id_, ) = args

    notification_type = ContentType.objects.get(app_label="pinax_forums",
                                                model="ThreadSubscription")

    if id_ is None:
        TeacherNotification.objects.filter(
            teacher=teacher, notification_type=notification_type).delete()
    else:
        TeacherNotification.objects.filter(teacher=teacher,
                                           notification_type=notification_type,
                                           object_id=id_).delete()

    return HttpResponse("")
Exemplo n.º 16
0
def evaluate_rationale(req, teacher):
    """
    Add the `teacher`'s evaluation for a rationale.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                id: int
                    Primary key of the rationale
                score: int
                    Given score
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    HttpResponse
        Error response or empty 200 response
    """

    if req.META["CONTENT_TYPE"] == "application/json":
        args = get_json_params(req,
                               args=["id", "score"],
                               opt_args=["redirect"])
        if isinstance(args, HttpResponse):
            return args
        (id_, score), (redirect_, ) = args
        if redirect_ is None:
            redirect_ = True
    else:
        id_ = req.POST.get("id", None)
        score = req.POST.get("score", None)
        redirect_ = True

    if id_ is None or score is None:
        return response_400(
            req,
            msg=translate("Missing parameters."),
            logger_msg=("Score and/or ID are missing from request."),
            log=logger.warning,
        )

    score = int(score)

    if score not in range(0, 4):
        return response_400(
            req,
            msg=translate("The score wasn't in a valid range."),
            logger_msg=("The score wasn't valid; was {}.".format(score)),
            log=logger.warning,
        )

    try:
        answer = Answer.objects.get(id=id_)
    except Answer.DoesNotExist:
        return response_400(
            req,
            msg=translate("Unkown answer id sent."),
            logger_msg=("No answer could be found for pk {}.".format(id_)),
            log=logger.warning,
        )

    if AnswerAnnotation.objects.filter(answer=answer,
                                       annotator=teacher.user).exists():
        annotation = AnswerAnnotation.objects.get(answer=answer,
                                                  annotator=teacher.user)
        annotation.score = score
        annotation.save()
    else:
        AnswerAnnotation.objects.create(answer=answer,
                                        annotator=teacher.user,
                                        score=score)

    if redirect_:
        return redirect(reverse("teacher-dashboard--rationales"))
    else:
        return HttpResponse("")
Exemplo n.º 17
0
def download_gradebook(req, teacher, results=None):
    """
    Download the wanted gradebook.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters:
                task_id: str
                    Id of the celery task responsible for the gradebook
                    generation sent with the first request for a gradebook
    teacher : Teacher
        Teacher instance returned by `teacher_required` (not used)
    results : Optional[Dict[str, Any]]
        Either
            If group gradebook
                {
                    group: str
                        Title of the group
                    assignments: List[str]
                        Assignment identifier
                    school_id_needed: bool
                        If a school id is needed
                    results: [{
                        school_id: Optional[str]
                            School id if needed
                        email: str
                            Student email
                        assignments: [{
                            n_completed: Optional[int]
                                Number of completed questions
                            n_correct: Optional[int]
                                Number of correct questions
                        }]
                    }]
                }
            If assignment gradebook
                {
                    group: str
                        Title of the group
                    assignment: str
                        Title of the assignment
                    questions: List[str]
                        Question title
                    school_id_needed: bool
                        If a school id is needed
                    results: [{
                        school_id: Optional[str]
                            School id if needed
                        email: str
                            Student email
                        questions: List[Optional[float]]
                            Grade for each question
                    }]
                }

    Returns
    -------
    StreamingHttpResponse
        csv file with the gradebook results
    """
    if results is None:
        args = get_json_params(req, args=["task_id"])
        if isinstance(args, HttpResponse):
            return args
        (task_id, ), _ = args

        result = AsyncResult(task_id)

        try:
            if not result.ready():
                return response_400(
                    req,
                    msg="The gradebook isn't ready.",
                    logger_msg="Not completed gradebook {}".format(task_id) +
                    " accessed by teacher {}".format(teacher.user.username),
                )
        except AttributeError:
            return response_500(
                req,
                msg="There is no gradebook corresponding to this url. "
                "Please ask for a new one.",
                logger_msg="Celery error getting gradebook"
                " for teacher {}".format(teacher.user.username) +
                " and task {}.".format(task_id),
                log=logger.warning,
                use_template=False,
            )

        results = result.result

        if RunningTask.objects.filter(id=task_id):
            RunningTask.objects.get(id=task_id).delete()

    if "assignment" in results:
        filename = "myDALITE_gradebook_{}_{}.csv".format(
            results["group"], results["assignment"])
    else:
        filename = "myDALITE_gradebook_{}.csv".format(results["group"])
    gradebook_gen = convert_gradebook_to_csv(results)
    data = chain(iter((filename + "\n", )), gradebook_gen)
    resp = StreamingHttpResponse(data, content_type="text/csv")
    return resp
Exemplo n.º 18
0
def request_gradebook(req, teacher):
    """
    Request the generation of a gradebook. An response containing the task id
    is returned so the client can poll the server for the result until it's
    ready.

    Parameters
    ----------
    req : HttpRequest
        Request with:
            parameters
                group_id: int
                    Primary key of the group for which the gradebook is wanted
            optional parameters:
                assignment_id: int (default : None)
                    Primary key of the assignment for which the gradebook is
                    wanted
    teacher : Teacher
        Teacher instance returned by `teacher_required`

    Returns
    -------
    Either
        JsonResponse with json data
            Response 201 (created) with json data if computation run
            asynchronously
                {
                    task_id: str
                        Id corresponding to the celery task for use in polling
                }
            Response 200 with json data if computation run synchronously
                Either
                    If group gradebook wanted
                        {
                            assignments: List[str]
                                Assignment identifier
                            school_id_needed: bool
                                If a school id is needed
                            results: [{
                                school_id: Optional[str]
                                    School id if needed
                                email: str
                                    Student email
                                assignments: [{
                                    n_completed: int
                                        Number of completed questions
                                    n_correct: int
                                        Number of correct questions
                                }]
                            }]
                        }
                    If assignment gradebook wanted
                        {
                            questions: List[str]
                                Question title
                            school_id_needed: bool
                                If a school id is needed
                            results: [{
                                school_id: Optional[str]
                                    School id if needed
                                email: str
                                    Student email
                                questions: List[float]
                                    Grade for each question
                            }]
                        }
        HttpResponse
            Error response
    """
    args = get_json_params(req, args=["group_id"], opt_args=["assignment_id"])
    if isinstance(args, HttpResponse):
        return args
    (group_pk, ), (assignment_pk, ) = args

    try:
        group = StudentGroup.objects.get(pk=group_pk)
    except StudentGroup.DoesNotExist:
        return response_400(
            req,
            msg=translate("The group doesn't exist."),
            logger_msg=("Access to {} with an invalid group {}.".format(
                req.path, group_pk)),
            log=logger.warning,
        )

    if teacher not in group.teacher.all():
        return response_403(
            req,
            msg=translate(
                "You don't have access to this resource. You must be "
                "registered as a teacher for the group."),
            logger_msg=(
                "Unauthorized access to group {} from teacher {}.".format(
                    group.pk, teacher.pk)),
            log=logger.warning,
        )

    if assignment_pk is not None:
        try:
            assignment = StudentGroupAssignment.objects.get(pk=assignment_pk)
        except StudentGroupAssignment.DoesNotExist:
            return response_400(
                req,
                msg=translate("The group or assignment don't exist."),
                logger_msg=(
                    "Access to {} with an invalid assignment {}.".format(
                        req.path, assignment_pk)),
                log=logger.warning,
            )

    result = compute_gradebook_async(group_pk, assignment_pk)

    if assignment_pk is None:
        description = format_html("gradebook for group <strong>{}</strong>",
                                  group.name)
    else:
        description = "gradebook for assignment {} and group {}".format(
            assignment.assignment.identifier, group.name)

    if isinstance(result, AsyncResult):
        task = RunningTask.objects.create(id=result.id,
                                          description=description,
                                          teacher=teacher)
        data = {
            "id": task.id,
            "description": task.description,
            "completed": False,
            "datetime": task.datetime.strftime("%Y-%m-%d %H:%M:%S.%f"),
        }
        return JsonResponse(data, status=201)
    else:
        return download_gradebook(req, results=result)