forms.py

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from django import forms
from mywebsite.todos.models import Todo, List, todo_id_gen
from django.core.exceptions import ValidationError


# todo move these constants to their own file
EMPTY_ITEM_ERROR = "You can't have an empty list item"
DUPLICATE_ITEM_ERROR = "This item has already been entered"
TODO_TITLE_DUPE = "Can't save a todo that has the same text as title"


class GenericForm(forms.models.ModelForm):
    placeholder_text = None

    class Meta:
        model = None
        widgets = None

        fields = ("text",)
        labels = {
            "text": "",
        }
        error_messages = {
            "text": {"required": EMPTY_ITEM_ERROR},
        }

    def validate_unique(self) -> None:
        try:
            self.instance.validate_unique()
        except ValidationError as e:
            e.error_dict = {"text": [DUPLICATE_ITEM_ERROR]}
            self._update_errors(e)


def create_widget(placeholder_text, extra_attr: dict = None):
    attrs = {
        "placeholder": f"{placeholder_text}",
        "class": "form-control input-lg",
    }
    if extra_attr:
        attrs = attrs | extra_attr
    return {"text": forms.TextInput(attrs=attrs)}


class TodoForm(GenericForm):

    def __init__(self, for_list=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.instance.list = for_list
        # self.fields["text"].validators.append(validate_unique)

    class Meta(GenericForm.Meta):
        model = Todo
        placeholder_text = "Enter a todo"
        widgets = create_widget(placeholder_text)

    def save(self, owner, pk):
        if owner and pk:
            return Todo.objects.create(
                text=self.cleaned_data["text"],
                list=owner.list_set.get(id=pk),
                todo_id=todo_id_gen(),
            )

    def validate_unique(self) -> None:
        try:
            val = self.data.get("text")
            todos_for_list = list(self.instance.list.todo_set.all())
            if val == todos_for_list[0].text:
                raise ValidationError(TODO_TITLE_DUPE)
            for todo in todos_for_list[1:]:
                if todo.text == val:
                    raise ValidationError(DUPLICATE_ITEM_ERROR)
        except ValidationError as e:
            self._update_errors(e)


class ListForm(GenericForm):
    def __init__(self, queryset=None, *args, **kwargs):
        self.queryset = queryset
        super().__init__(*args, **kwargs)

    class Meta(GenericForm.Meta):
        model = Todo
        widgets = create_widget("Enter a title for list. Press enter to submit.")

    def save(self, owner):
        if owner:
            return List.create_new(text=self.cleaned_data["text"], owner=owner)

    def validate_unique(self) -> None:
        try:
            val = self.data.get("text")
            tmp_list = list(self.queryset)
            all_lists_name = []
            for list_obj in tmp_list:
                try:
                    if list_obj.name:
                        all_lists_name.append(list_obj.name)
                except AttributeError as e:
                    """list_obj does not yet exist and thus does not have name"""
                    continue

            if val in all_lists_name:
                raise ValidationError(DUPLICATE_ITEM_ERROR)
        except ValidationError as e:
            self._update_errors(e)


class EditForm(GenericForm):
    class Meta(GenericForm.Meta):
        model = Todo
        widgets = create_widget("Enter a new title", extra_attr={"id": "edit-form"})


class EditTodoForm(GenericForm):
    class Meta(GenericForm.Meta):
        model = Todo
        widgets = create_widget("Edit Todo entry", extra_attr={"id": "edit-todo-form"})