or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auth-permissions.mdcontent-negotiation.mddecorators.mdfields-validation.mdgeneric-views.mdindex.mdpagination-filtering.mdrequest-response.mdrouters-urls.mdserializers.mdstatus-exceptions.mdtesting.mdviews-viewsets.md

fields-validation.mddocs/

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

```