0
# Fields and Validation
1
2
Comprehensive field types for data validation and serialization in Django REST Framework. Includes basic types, specialized fields, relationship fields, and custom validation support.
3
4
## Capabilities
5
6
### Base Field Class
7
8
Foundation class for all serializer fields providing core validation and transformation functionality.
9
10
```python { .api }
11
class Field:
12
"""
13
Base class for all serializer fields.
14
"""
15
def __init__(self, read_only=False, write_only=False, required=None, default=empty,
16
initial=empty, source=None, label=None, help_text=None,
17
style=None, error_messages=None, validators=None, allow_null=False):
18
"""
19
Initialize field with configuration options.
20
21
Args:
22
read_only (bool): Field is read-only
23
write_only (bool): Field is write-only
24
required (bool): Field is required for input
25
default: Default value if not provided
26
initial: Initial value for forms
27
source (str): Source attribute name
28
label (str): Human readable label
29
help_text (str): Help text for field
30
style (dict): Style hints for rendering
31
error_messages (dict): Custom error messages
32
validators (list): List of validator functions
33
allow_null (bool): Allow None values
34
"""
35
36
def bind(self, field_name, parent):
37
"""
38
Bind field to its parent serializer.
39
40
Args:
41
field_name (str): Field name in serializer
42
parent: Parent serializer instance
43
"""
44
45
def get_value(self, dictionary):
46
"""
47
Extract field value from input dictionary.
48
49
Args:
50
dictionary (dict): Input data dictionary
51
52
Returns:
53
Field value or empty sentinel
54
"""
55
56
def get_attribute(self, instance):
57
"""
58
Extract field value from object instance.
59
60
Args:
61
instance: Object instance to serialize
62
63
Returns:
64
Attribute value
65
"""
66
67
def to_representation(self, value):
68
"""
69
Transform internal value to serialized representation.
70
71
Args:
72
value: Internal Python value
73
74
Returns:
75
Serialized representation
76
"""
77
78
def to_internal_value(self, data):
79
"""
80
Transform input data to internal Python value.
81
82
Args:
83
data: Input data to validate
84
85
Returns:
86
Validated internal value
87
88
Raises:
89
ValidationError: If validation fails
90
"""
91
92
def validate(self, value):
93
"""
94
Validate internal value against field validators.
95
96
Args:
97
value: Value to validate
98
99
Returns:
100
Validated value
101
102
Raises:
103
ValidationError: If validation fails
104
"""
105
```
106
107
### Basic Field Types
108
109
Core field types for common data validation needs.
110
111
```python { .api }
112
class BooleanField(Field):
113
"""Boolean field accepting True/False values."""
114
def __init__(self, **kwargs): ...
115
116
class CharField(Field):
117
"""
118
String field with length validation.
119
120
Args:
121
max_length (int): Maximum string length
122
min_length (int): Minimum string length
123
allow_blank (bool): Allow empty strings
124
trim_whitespace (bool): Strip leading/trailing whitespace
125
"""
126
def __init__(self, max_length=None, min_length=None, allow_blank=False,
127
trim_whitespace=True, **kwargs): ...
128
129
class EmailField(CharField):
130
"""Email address validation field."""
131
def __init__(self, **kwargs): ...
132
133
class RegexField(CharField):
134
"""
135
String field validated against regex pattern.
136
137
Args:
138
regex (str or Pattern): Regular expression pattern
139
"""
140
def __init__(self, regex, **kwargs): ...
141
142
class SlugField(CharField):
143
"""Slug validation field (letters, numbers, underscores, hyphens)."""
144
def __init__(self, **kwargs): ...
145
146
class URLField(CharField):
147
"""URL validation field."""
148
def __init__(self, **kwargs): ...
149
150
class UUIDField(Field):
151
"""
152
UUID field supporting string and UUID object formats.
153
154
Args:
155
format (str): Output format ('hex_verbose', 'hex', 'int', 'urn')
156
"""
157
def __init__(self, format='hex_verbose', **kwargs): ...
158
159
class IPAddressField(CharField):
160
"""
161
IP address validation field supporting IPv4 and IPv6.
162
163
Args:
164
protocol (str): 'both', 'ipv4', or 'ipv6'
165
unpack_ipv4 (bool): Unpack IPv4-mapped IPv6 addresses
166
"""
167
def __init__(self, protocol='both', unpack_ipv4=False, **kwargs): ...
168
```
169
170
### Numeric Fields
171
172
Fields for numeric data with range validation.
173
174
```python { .api }
175
class IntegerField(Field):
176
"""
177
Integer field with range validation.
178
179
Args:
180
max_value (int): Maximum allowed value
181
min_value (int): Minimum allowed value
182
"""
183
def __init__(self, max_value=None, min_value=None, **kwargs): ...
184
185
class FloatField(Field):
186
"""
187
Float field with range validation.
188
189
Args:
190
max_value (float): Maximum allowed value
191
min_value (float): Minimum allowed value
192
"""
193
def __init__(self, max_value=None, min_value=None, **kwargs): ...
194
195
class DecimalField(Field):
196
"""
197
Precise decimal field for financial calculations.
198
199
Args:
200
max_digits (int): Maximum number of digits
201
decimal_places (int): Number of decimal places
202
coerce_to_string (bool): Return as string instead of Decimal
203
max_value (Decimal): Maximum allowed value
204
min_value (Decimal): Minimum allowed value
205
"""
206
def __init__(self, max_digits, decimal_places, coerce_to_string=None,
207
max_value=None, min_value=None, **kwargs): ...
208
```
209
210
### Date and Time Fields
211
212
Fields for temporal data with format support.
213
214
```python { .api }
215
class DateTimeField(Field):
216
"""
217
DateTime field with format parsing and output.
218
219
Args:
220
format (str): Output format string or 'iso-8601'
221
input_formats (list): List of acceptable input formats
222
default_timezone (timezone): Default timezone for naive datetimes
223
"""
224
def __init__(self, format=empty, input_formats=None, default_timezone=None, **kwargs): ...
225
226
class DateField(Field):
227
"""
228
Date field with format parsing and output.
229
230
Args:
231
format (str): Output format string or 'iso-8601'
232
input_formats (list): List of acceptable input formats
233
"""
234
def __init__(self, format=empty, input_formats=None, **kwargs): ...
235
236
class TimeField(Field):
237
"""
238
Time field with format parsing and output.
239
240
Args:
241
format (str): Output format string or 'iso-8601'
242
input_formats (list): List of acceptable input formats
243
"""
244
def __init__(self, format=empty, input_formats=None, **kwargs): ...
245
246
class DurationField(Field):
247
"""
248
Duration field supporting various input formats.
249
250
Args:
251
max_value (timedelta): Maximum duration
252
min_value (timedelta): Minimum duration
253
"""
254
def __init__(self, max_value=None, min_value=None, **kwargs): ...
255
```
256
257
### Choice and File Fields
258
259
Fields for constrained choices and file handling.
260
261
```python { .api }
262
class ChoiceField(Field):
263
"""
264
Field that validates against a set of choices.
265
266
Args:
267
choices (list): List of valid choices as (value, label) tuples
268
allow_blank (bool): Allow empty string choice
269
"""
270
def __init__(self, choices, allow_blank=False, **kwargs): ...
271
272
class MultipleChoiceField(ChoiceField):
273
"""
274
Field that validates multiple selections from choices.
275
276
Args:
277
choices (list): List of valid choices
278
allow_empty (bool): Allow empty list
279
"""
280
def __init__(self, allow_empty=True, **kwargs): ...
281
282
class FileField(Field):
283
"""
284
File upload field.
285
286
Args:
287
max_length (int): Maximum filename length
288
allow_empty_file (bool): Allow empty files
289
use_url (bool): Use URL instead of filename in representation
290
"""
291
def __init__(self, max_length=None, allow_empty_file=False, use_url=True, **kwargs): ...
292
293
class ImageField(FileField):
294
"""
295
Image file field with validation.
296
"""
297
def __init__(self, **kwargs): ...
298
```
299
300
### Container Fields
301
302
Fields for complex data structures.
303
304
```python { .api }
305
class ListField(Field):
306
"""
307
Field for lists of items with child validation.
308
309
Args:
310
child (Field): Field for validating list items
311
allow_empty (bool): Allow empty lists
312
max_length (int): Maximum list length
313
min_length (int): Minimum list length
314
"""
315
def __init__(self, child=None, allow_empty=True, max_length=None, min_length=None, **kwargs): ...
316
317
class DictField(Field):
318
"""
319
Field for dictionaries with optional child validation.
320
321
Args:
322
child (Field): Field for validating dictionary values
323
allow_empty (bool): Allow empty dictionaries
324
"""
325
def __init__(self, child=None, allow_empty=True, **kwargs): ...
326
327
class HStoreField(DictField):
328
"""PostgreSQL HStore field (string keys and values only)."""
329
def __init__(self, **kwargs): ...
330
331
class JSONField(Field):
332
"""
333
Field for JSON data with optional binary encoding.
334
335
Args:
336
binary (bool): Store as binary JSON (PostgreSQL)
337
encoder (JSONEncoder): Custom JSON encoder class
338
"""
339
def __init__(self, binary=False, encoder=None, **kwargs): ...
340
```
341
342
### Special Fields
343
344
Specialized fields for specific use cases.
345
346
```python { .api }
347
class ReadOnlyField(Field):
348
"""
349
Read-only field that returns attribute value without validation.
350
"""
351
def __init__(self, **kwargs):
352
kwargs['read_only'] = True
353
super().__init__(**kwargs)
354
355
class HiddenField(Field):
356
"""
357
Hidden field with default value, not included in input validation.
358
"""
359
def __init__(self, **kwargs):
360
kwargs['write_only'] = True
361
super().__init__(**kwargs)
362
363
class SerializerMethodField(Field):
364
"""
365
Field that gets its value by calling a method on the serializer.
366
367
Args:
368
method_name (str): Name of serializer method to call
369
"""
370
def __init__(self, method_name=None, **kwargs):
371
kwargs['read_only'] = True
372
self.method_name = method_name
373
super().__init__(**kwargs)
374
375
class ModelField(Field):
376
"""
377
Field that wraps a Django model field for validation.
378
379
Args:
380
model_field: Django model field instance
381
"""
382
def __init__(self, model_field, **kwargs): ...
383
```
384
385
### Validation Utilities
386
387
Support for custom validation logic.
388
389
```python { .api }
390
# Special values and exceptions
391
empty = object() # Sentinel for no data provided
392
393
class SkipField(Exception):
394
"""Exception to skip field during serialization."""
395
396
# Default value classes
397
class CreateOnlyDefault:
398
"""Default value only used during object creation."""
399
def __init__(self, default): ...
400
def __call__(self): ...
401
402
class CurrentUserDefault:
403
"""Default to current user from request context."""
404
def __call__(self): ...
405
406
# Utility functions
407
def is_simple_callable(obj):
408
"""
409
Check if object is a simple callable (no required arguments).
410
411
Args:
412
obj: Object to check
413
414
Returns:
415
bool: True if simple callable
416
"""
417
418
def get_attribute(instance, attrs):
419
"""
420
Get nested attribute value using dot notation.
421
422
Args:
423
instance: Object instance
424
attrs (list): List of attribute names
425
426
Returns:
427
Attribute value
428
"""
429
430
def to_choices_dict(choices):
431
"""
432
Convert choices list to dictionary format.
433
434
Args:
435
choices: Choices in various formats
436
437
Returns:
438
dict: Normalized choices dictionary
439
"""
440
```
441
442
## Validator Classes
443
444
Built-in validator classes for complex validation scenarios, particularly useful for model-level constraints and uniqueness checks.
445
446
```python { .api }
447
class UniqueValidator:
448
"""
449
Validator that ensures field value is unique within a queryset.
450
Corresponds to unique=True on model fields.
451
"""
452
message = 'This field must be unique.'
453
requires_context = True
454
455
def __init__(self, queryset, message=None, lookup='exact'):
456
"""
457
Args:
458
queryset: QuerySet to check uniqueness against
459
message (str): Custom error message
460
lookup (str): Field lookup type for filtering
461
"""
462
463
def __call__(self, value, serializer_field):
464
"""Validate value uniqueness."""
465
466
class UniqueTogetherValidator:
467
"""
468
Validator that ensures field combinations are unique.
469
Corresponds to unique_together model Meta option.
470
"""
471
message = 'The fields {field_names} must make a unique set.'
472
missing_message = 'This field is required.'
473
requires_context = True
474
475
def __init__(self, queryset, fields, message=None):
476
"""
477
Args:
478
queryset: QuerySet to check uniqueness against
479
fields (list): List of field names that must be unique together
480
message (str): Custom error message
481
"""
482
483
class UniqueForDateValidator:
484
"""
485
Validator that ensures field is unique for a given date.
486
Corresponds to unique_for_date model field option.
487
"""
488
message = 'This field must be unique for the "{date_field}" date.'
489
requires_context = True
490
491
def __init__(self, queryset, field, date_field, message=None):
492
"""
493
Args:
494
queryset: QuerySet to check uniqueness against
495
field (str): Field name to validate
496
date_field (str): Date field to check uniqueness within
497
message (str): Custom error message
498
"""
499
500
class UniqueForMonthValidator:
501
"""
502
Validator that ensures field is unique for a given month.
503
Corresponds to unique_for_month model field option.
504
"""
505
message = 'This field must be unique for the "{date_field}" month.'
506
507
class UniqueForYearValidator:
508
"""
509
Validator that ensures field is unique for a given year.
510
Corresponds to unique_for_year model field option.
511
"""
512
message = 'This field must be unique for the "{date_field}" year.'
513
514
class ProhibitSurrogateCharactersValidator:
515
"""
516
Validator that prohibits surrogate characters in text fields.
517
"""
518
message = 'Surrogate characters are not allowed.'
519
code = 'surrogate_characters_not_allowed'
520
521
def __call__(self, value):
522
"""Validate value does not contain surrogate characters."""
523
```
524
525
### Validator Usage Examples
526
527
```python
528
from rest_framework import serializers
529
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator
530
531
class BookSerializer(serializers.ModelSerializer):
532
# Unique field validator
533
isbn = serializers.CharField(
534
validators=[UniqueValidator(queryset=Book.objects.all())]
535
)
536
537
class Meta:
538
model = Book
539
fields = ['title', 'isbn', 'author', 'publication_year']
540
541
# Unique together validator
542
validators = [
543
UniqueTogetherValidator(
544
queryset=Book.objects.all(),
545
fields=['title', 'author'],
546
message="Book with this title and author already exists."
547
)
548
]
549
550
# Unique for date validator
551
class EventSerializer(serializers.ModelSerializer):
552
class Meta:
553
model = Event
554
fields = ['name', 'venue', 'date']
555
validators = [
556
UniqueForDateValidator(
557
queryset=Event.objects.all(),
558
field='name',
559
date_field='date',
560
message="Event name must be unique per date."
561
)
562
]
563
564
# Custom validator function
565
def validate_isbn_format(value):
566
"""Validate ISBN format (basic example)."""
567
if not value.replace('-', '').isdigit():
568
raise serializers.ValidationError("ISBN must contain only digits and hyphens")
569
return value
570
571
class BookSerializer(serializers.Serializer):
572
isbn = serializers.CharField(validators=[validate_isbn_format])
573
```
574
575
## Usage Examples
576
577
### Basic Field Usage
578
579
```python
580
from rest_framework import serializers
581
582
class BookSerializer(serializers.Serializer):
583
title = serializers.CharField(max_length=200)
584
isbn = serializers.CharField(max_length=13, min_length=13)
585
publication_date = serializers.DateField()
586
pages = serializers.IntegerField(min_value=1, max_value=10000)
587
price = serializers.DecimalField(max_digits=6, decimal_places=2)
588
is_available = serializers.BooleanField(default=True)
589
590
# Custom validation
591
def validate_isbn(self, value):
592
if not value.isdigit():
593
raise serializers.ValidationError("ISBN must contain only digits")
594
return value
595
596
def validate(self, data):
597
if data['publication_date'] > timezone.now().date():
598
raise serializers.ValidationError("Publication date cannot be in future")
599
return data
600
```
601
602
### Complex Field Types
603
604
```python
605
class AuthorSerializer(serializers.Serializer):
606
name = serializers.CharField(max_length=100)
607
email = serializers.EmailField()
608
website = serializers.URLField(required=False)
609
bio = serializers.CharField(allow_blank=True)
610
611
class BookSerializer(serializers.Serializer):
612
# Nested object
613
author = AuthorSerializer()
614
615
# List of strings
616
tags = serializers.ListField(
617
child=serializers.CharField(max_length=50),
618
allow_empty=False,
619
max_length=5
620
)
621
622
# Dictionary with string values
623
metadata = serializers.DictField(
624
child=serializers.CharField(),
625
allow_empty=True
626
)
627
628
# JSON field
629
settings = serializers.JSONField(default=dict)
630
631
# Choice field
632
genre = serializers.ChoiceField(choices=[
633
('fiction', 'Fiction'),
634
('non-fiction', 'Non-Fiction'),
635
('mystery', 'Mystery'),
636
])
637
638
# File upload
639
cover_image = serializers.ImageField(required=False)
640
```
641
642
### Method Fields and Custom Logic
643
644
```python
645
class BookSerializer(serializers.ModelSerializer):
646
# Computed field using method
647
full_title = serializers.SerializerMethodField()
648
649
# Read-only field
650
created_by = serializers.ReadOnlyField(source='owner.username')
651
652
# Hidden field with default
653
created_at = serializers.HiddenField(default=timezone.now)
654
655
# Current user default
656
owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
657
658
class Meta:
659
model = Book
660
fields = ['id', 'title', 'author', 'full_title', 'created_by', 'owner']
661
662
def get_full_title(self, obj):
663
return f"{obj.title} by {obj.author.name}"
664
```
665
666
### Custom Validation
667
668
```python
669
from rest_framework import serializers
670
671
def validate_even_number(value):
672
if value % 2 != 0:
673
raise serializers.ValidationError("Must be an even number")
674
return value
675
676
class CustomFieldSerializer(serializers.Serializer):
677
# Field-level validator
678
even_number = serializers.IntegerField(validators=[validate_even_number])
679
680
# Custom field validation method
681
def validate_title(self, value):
682
if 'forbidden' in value.lower():
683
raise serializers.ValidationError("Title contains forbidden word")
684
return value
685
686
# Object-level validation
687
def validate(self, data):
688
if data.get('start_date') and data.get('end_date'):
689
if data['start_date'] >= data['end_date']:
690
raise serializers.ValidationError("End date must be after start date")
691
return data
692
```