forms.py 4 KB
Newer Older
1 2 3 4
"""
Discussion API forms
"""
from django.core.exceptions import ValidationError
5 6 7
from django.forms import (
    BooleanField,
    CharField,
8
    ChoiceField,
9 10
    Form,
    IntegerField,
Ned Batchelder committed
11
)
12 13 14

from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseLocator
15
from openedx.core.djangoapps.util.forms import MultiValueField, ExtendedNullBooleanField
16 17


18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
class _PaginationForm(Form):
    """A form that includes pagination fields"""
    page = IntegerField(required=False, min_value=1)
    page_size = IntegerField(required=False, min_value=1)

    def clean_page(self):
        """Return given valid page or default of 1"""
        return self.cleaned_data.get("page") or 1

    def clean_page_size(self):
        """Return given valid page_size (capped at 100) or default of 10"""
        return min(self.cleaned_data.get("page_size") or 10, 100)


class ThreadListGetForm(_PaginationForm):
33 34 35
    """
    A form to validate query parameters in the thread list retrieval endpoint
    """
36
    EXCLUSIVE_PARAMS = ["topic_id", "text_search", "following"]
37

38
    course_id = CharField()
Nimisha Asthagiri committed
39
    topic_id = MultiValueField(required=False)
40
    text_search = CharField(required=False)
41
    following = ExtendedNullBooleanField(required=False)
42 43
    view = ChoiceField(
        choices=[(choice, choice) for choice in ["unread", "unanswered"]],
44 45 46 47 48 49 50
        required=False,
    )
    order_by = ChoiceField(
        choices=[(choice, choice) for choice in ["last_activity_at", "comment_count", "vote_count"]],
        required=False
    )
    order_direction = ChoiceField(
51
        choices=[(choice, choice) for choice in ["desc"]],
52 53
        required=False
    )
54
    requested_fields = MultiValueField(required=False)
55

56 57 58 59 60 61 62 63
    def clean_order_by(self):
        """Return a default choice"""
        return self.cleaned_data.get("order_by") or "last_activity_at"

    def clean_order_direction(self):
        """Return a default choice"""
        return self.cleaned_data.get("order_direction") or "desc"

64 65 66 67 68 69 70 71
    def clean_course_id(self):
        """Validate course_id"""
        value = self.cleaned_data["course_id"]
        try:
            return CourseLocator.from_string(value)
        except InvalidKeyError:
            raise ValidationError("'{}' is not a valid course id".format(value))

72 73 74 75 76 77 78 79
    def clean_following(self):
        """Validate following"""
        value = self.cleaned_data["following"]
        if value is False:
            raise ValidationError("The value of the 'following' parameter must be true.")
        else:
            return value

80 81 82 83 84 85 86 87 88 89 90 91 92
    def clean(self):
        cleaned_data = super(ThreadListGetForm, self).clean()
        exclusive_params_count = sum(
            1 for param in self.EXCLUSIVE_PARAMS if cleaned_data.get(param)
        )
        if exclusive_params_count > 1:
            raise ValidationError(
                "The following query parameters are mutually exclusive: {}".format(
                    ", ".join(self.EXCLUSIVE_PARAMS)
                )
            )
        return cleaned_data

93

94
class ThreadActionsForm(Form):
95
    """
96
    A form to handle fields in thread creation/update that require separate
97 98 99
    interactions with the comments service.
    """
    following = BooleanField(required=False)
100
    voted = BooleanField(required=False)
101
    abuse_flagged = BooleanField(required=False)
102
    read = BooleanField(required=False)
103 104


105 106 107 108 109
class CommentListGetForm(_PaginationForm):
    """
    A form to validate query parameters in the comment list retrieval endpoint
    """
    thread_id = CharField()
110
    endorsed = ExtendedNullBooleanField(required=False)
111
    requested_fields = MultiValueField(required=False)
112 113 114 115 116 117 118 119


class CommentActionsForm(Form):
    """
    A form to handle fields in comment creation/update that require separate
    interactions with the comments service.
    """
    voted = BooleanField(required=False)
120
    abuse_flagged = BooleanField(required=False)
121 122 123 124 125 126 127


class CommentGetForm(_PaginationForm):
    """
    A form to validate query parameters in the comment retrieval endpoint
    """
    requested_fields = MultiValueField(required=False)