• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

akvo / iwsims-demo / #128

11 May 2025 07:48PM UTC coverage: 86.762% (+0.5%) from 86.288%
#128

push

coveralls-python

web-flow
Merge pull request #35 from akvo/feature/33-eng-1327-new-question-type-signature

Feature/33 eng 1327 new question type signature

2618 of 3116 branches covered (84.02%)

Branch coverage included in aggregate %.

5961 of 6772 relevant lines covered (88.02%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.61
backend/utils/custom_serializer_fields.py
1
from django.core.validators import EmailValidator
1✔
2
from django.utils.translation import gettext_lazy as _
1✔
3
from rest_framework.fields import (
1✔
4
    IntegerField,
5
    ChoiceField,
6
    CharField,
7
    ImageField,
8
    ListField,
9
    BooleanField,
10
    FloatField,
11
    DecimalField,
12
    URLField,
13
    DateField,
14
    MultipleChoiceField,
15
    FileField,
16
    DateTimeField,
17
    JSONField,
18
    Field,
19
)
20
from rest_framework.relations import PrimaryKeyRelatedField
1✔
21

22
key_map = {}
1✔
23

24

25
class CustomIntegerField(IntegerField):
1✔
26
    default_error_messages = {
1✔
27
        "invalid": _("A valid field_title is required."),
28
        "max_value": _(
29
            "Ensure field_title is less than or equal to {max_value}."
30
        ),
31
        "min_value": _(
32
            "Ensure field_title is greater than or equal to {min_value}."
33
        ),
34
        "max_string_length": _("field_title value too large."),
35
        "required": _("field_title is required."),
36
        "null": _("field_title may not be null."),
37
    }
38

39

40
class CustomCharField(CharField):
1✔
41
    default_error_messages = {
1✔
42
        "invalid": _("A valid field_title is required."),
43
        "blank": _("field_title may not be blank."),
44
        "max_length": _(
45
            "Ensure field_title has no more than {max_length} characters."
46
        ),
47
        "min_length": _(
48
            "Ensure field_title has at least {min_length} characters."
49
        ),
50
        "required": _("field_title is required."),
51
        "null": _("field_title may not be null."),
52
    }
53

54

55
class CustomChoiceField(ChoiceField):
1✔
56
    default_error_messages = {
1✔
57
        "invalid_choice": _('"{input}" is not a valid choice in field_title.'),
58
        "required": _("field_title is required."),
59
        "null": _("field_title may not be null."),
60
    }
61

62

63
class CustomMultipleChoiceField(MultipleChoiceField):
1✔
64
    default_error_messages = {
1✔
65
        "invalid_choice": _('"{input}" is not a valid choice in field_title.'),
66
        "not_a_list": _(
67
            'Expected a list of items but got type "{input_type}"'
68
            " in field_title."
69
        ),
70
        "empty": _("This selection may not be empty in field_title."),
71
    }
72

73

74
class CustomImageField(ImageField):
1✔
75
    default_error_messages = {
1✔
76
        "invalid_image": _(
77
            "Upload a valid image. field_title you uploaded was either not "
78
            "an image or a corrupted image."
79
        ),
80
        "required": _("field_title is required."),
81
        "null": _("field_title may not be null."),
82
    }
83

84

85
class CustomEmailField(CustomCharField):
1✔
86
    default_error_messages = {"invalid": _("Enter a valid email address.")}
1✔
87

88
    def __init__(self, **kwargs):
1✔
89
        super().__init__(**kwargs)
1✔
90
        validator = EmailValidator(message=self.error_messages["invalid"])
1✔
91
        self.validators.append(validator)
1✔
92

93

94
class CustomListField(ListField):
1✔
95
    default_error_messages = {
1✔
96
        "not_a_list": _(
97
            "Expected a list of items in field_title but got type"
98
            ' "{input_type}".'
99
        ),
100
        "empty": _("field_title may not be empty."),
101
        "min_length": _(
102
            "Ensure field_title has at least {min_length} elements."
103
        ),
104
        "max_length": _(
105
            "Ensure field_title has no more than {max_length} elements."
106
        ),
107
        "required": _("field_title is required."),
108
        "null": _("field_title may not be null."),
109
    }
110

111

112
class CustomBooleanField(BooleanField):
1✔
113
    default_error_messages = {
1✔
114
        "invalid": _("Must be a valid field_title."),
115
        "required": _("field_title is required."),
116
        "null": _("field_title may not be null."),
117
    }
118

119

120
class CustomFloatField(FloatField):
1✔
121
    default_error_messages = {
1✔
122
        "invalid": _("A valid field_title is required."),
123
        "max_value": _(
124
            "Ensure field_title is less than or equal to {max_value}."
125
        ),
126
        "min_value": _(
127
            "Ensure field_title is greater than or equal to {min_value}."
128
        ),
129
        "max_string_length": _("field_title too large."),
130
        "required": _("field_title is required."),
131
        "null": _("field_title may not be null."),
132
    }
133

134

135
class CustomDecimalField(DecimalField):
1✔
136
    default_error_messages = {
1✔
137
        "invalid": _("A field_title number is required."),
138
        "max_value": _(
139
            "Ensure field_title is less than or equal to {max_value}."
140
        ),
141
        "min_value": _(
142
            "Ensure field_title is greater than or equal to {min_value}."
143
        ),
144
        "max_digits": _(
145
            "Ensure that in field_title are no more than {max_digits} "
146
            "digits in total."
147
        ),
148
        "max_decimal_places": _(
149
            "Ensure that in field_title are no more than {max_decimal_places} "
150
            "decimal places."
151
        ),
152
        "max_whole_digits": _(
153
            "Ensure that in field_title are no more than {max_whole_digits} "
154
            "digits before the "
155
            "decimal point."
156
        ),
157
        "max_string_length": _("String value too large in field_title."),
158
        "required": _("field_title is required."),
159
        "null": _("field_title may not be null."),
160
    }
161

162

163
class CustomURLField(URLField):
1✔
164
    default_error_messages = {
1✔
165
        "invalid": _("Enter a valid URL in field_title."),
166
        "required": _("field_title is required."),
167
        "null": _("field_title may not be null."),
168
    }
169

170

171
class CustomPrimaryKeyRelatedField(PrimaryKeyRelatedField):
1✔
172
    default_error_messages = {
1✔
173
        "required": _("field_title is required."),
174
        "does_not_exist": _(
175
            'Invalid pk "{pk_value}" - object does not exist.'
176
        ),
177
        "incorrect_type": _(
178
            "Incorrect type. Expected pk value, received {data_type}."
179
        ),
180
        "null": _("field_title may not be null."),
181
    }
182

183

184
class CustomDateField(DateField):
1✔
185
    default_error_messages = {
1✔
186
        "required": _("field_title is required."),
187
        "invalid": _(
188
            "Date has wrong format. Use one of these formats instead:"
189
            " {format}."
190
        ),
191
        "datetime": _("Expected a date but got a datetime."),
192
        "null": _("field_title may not be null."),
193
    }
194

195

196
class CustomFileField(FileField):
1✔
197
    default_error_messages = {
1✔
198
        "required": _("No file was submitted in field_title."),
199
        "invalid": _(
200
            "The submitted data was not a file. Check the encoding type on the"
201
            " form in field_title."
202
        ),
203
        "no_name": _("No filename could be determined in field_title."),
204
        "empty": _("The submitted file is empty in field_title."),
205
        "max_length": _(
206
            "Ensure this filename has at most {max_length} characters"
207
            " (it has {length}) in field_title."
208
        ),
209
    }
210

211

212
class CustomDateTimeField(DateTimeField):
1✔
213
    default_error_messages = {
1✔
214
        "invalid": _(
215
            "Datetime has wrong format. Use one of these formats instead: "
216
            "{format} in field_title."
217
        ),
218
        "date": _("field_title Expected a datetime but got a date."),
219
        "make_aware": _(
220
            'Invalid datetime for the timezone "{timezone} in field_title".'
221
        ),
222
        "overflow": _("Datetime value out of range in field_title."),
223
    }
224

225

226
class CustomUrlField(URLField):
1✔
227
    default_error_messages = {"invalid": _("Enter a valid URL.")}
1✔
228

229

230
class CustomJSONField(JSONField):
1✔
231
    default_error_messages = {
1✔
232
        "invalid": _("Value must be valid JSON in field_title."),
233
        "required": _("field_title field is required"),
234
    }
235

236

237
class UnvalidatedField(Field):
1✔
238
    default_error_messages = {
1✔
239
        "null": _("field_title may not be null."),
240
    }
241

242
    def __init__(self, **kwargs):
1✔
243
        super().__init__(**kwargs)
1✔
244
        self.allow_blank = True
1✔
245
        self.allow_null = False
1✔
246

247
    def to_internal_value(self, data):
1✔
248
        return data
1✔
249

250
    def to_representation(self, value):
1✔
251
        return value
×
252

253

254
def validate_serializers_message(errors):
1✔
255
    def extract_messages(error_obj, key=None):
1✔
256
        msgs = []
1✔
257
        if isinstance(error_obj, dict):
1✔
258
            for k, v in error_obj.items():
1✔
259
                msgs.extend(extract_messages(v, k))
1✔
260
        elif isinstance(error_obj, list):
1✔
261
            for item in error_obj:
1✔
262
                msgs.extend(extract_messages(item, key))
1✔
263
        elif isinstance(error_obj, str):
1!
264
            replacement = key_map.get(key, key) if key else key
1✔
265
            if replacement:
1!
266
                msgs.append(error_obj.replace("field_title", replacement))
1✔
267
            else:
268
                msgs.append(error_obj)
×
269
        return msgs
1✔
270

271
    msg = extract_messages(errors)
1✔
272
    return "|".join(msg)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc