0
# Contrib Modules
1
2
Additional field types and utilities provided as contrib modules in Schematics. These modules extend core functionality with specialized field types for specific use cases and external dependencies.
3
4
## Capabilities
5
6
### MongoDB Integration
7
8
MongoDB-specific field types for working with BSON data types.
9
10
```python { .api }
11
from schematics.contrib.mongo import ObjectIdType
12
13
class ObjectIdType(BaseType):
14
"""
15
MongoDB ObjectId field with BSON integration.
16
17
Handles MongoDB ObjectId objects with automatic conversion between
18
string representations and BSON ObjectId instances. Requires pymongo/bson.
19
"""
20
21
def __init__(self, auto_fill=False, **kwargs):
22
"""
23
Initialize ObjectId field.
24
25
Args:
26
auto_fill (bool): Whether to auto-generate ObjectIds (default: False)
27
**kwargs: Base field options
28
"""
29
30
def to_native(self, value, context=None):
31
"""
32
Convert string or ObjectId to BSON ObjectId.
33
34
Args:
35
value: String representation or ObjectId instance
36
context: Conversion context
37
38
Returns:
39
bson.ObjectId: BSON ObjectId instance
40
41
Raises:
42
ConversionError: If value cannot be converted to ObjectId
43
"""
44
45
def to_primitive(self, value, context=None):
46
"""
47
Convert ObjectId to string representation.
48
49
Args:
50
value: BSON ObjectId instance
51
context: Conversion context
52
53
Returns:
54
str: String representation of ObjectId
55
"""
56
```
57
58
### Enum Field Types
59
60
Native Python enum support for field values.
61
62
```python { .api }
63
from schematics.contrib.enum_type import EnumType
64
65
class EnumType(BaseType):
66
"""
67
Field type for Python enum values.
68
69
Restricts field values to members of a specified enum class with
70
optional support for accepting enum values in addition to enum members.
71
"""
72
73
def __init__(self, enum, use_values=False, **kwargs):
74
"""
75
Initialize enum field.
76
77
Args:
78
enum: Enum class to restrict values to
79
use_values (bool): Whether to accept enum values in addition to members
80
**kwargs: Base field options
81
"""
82
83
def to_native(self, value, context=None):
84
"""
85
Convert input to enum member.
86
87
Args:
88
value: Enum member, enum name string, or enum value
89
context: Conversion context
90
91
Returns:
92
Enum member corresponding to input
93
94
Raises:
95
ConversionError: If value is not a valid enum member/value
96
"""
97
98
def to_primitive(self, value, context=None):
99
"""
100
Convert enum member to primitive representation.
101
102
Args:
103
value: Enum member
104
context: Conversion context
105
106
Returns:
107
str or primitive: Enum name (default) or value (if use_values=True)
108
"""
109
```
110
111
### State Machine
112
113
Simple state machine for data processing workflows.
114
115
```python { .api }
116
from schematics.contrib.machine import Machine
117
118
class Machine:
119
"""
120
Simple state machine for data transformation workflows.
121
122
Manages data through predefined states (raw, converted, validated, serialized)
123
with automatic callbacks for state transitions.
124
"""
125
126
states = ('raw', 'converted', 'validated', 'serialized')
127
128
def __init__(self, data, *args):
129
"""
130
Initialize machine with data and schema.
131
132
Args:
133
data: Initial data
134
*args: Schema and additional arguments for transformations
135
"""
136
137
def convert(self):
138
"""
139
Transition from raw to converted state.
140
141
Applies conversion transformation to data.
142
"""
143
144
def validate(self):
145
"""
146
Transition from converted to validated state.
147
148
Applies validation to converted data.
149
"""
150
151
def serialize(self):
152
"""
153
Transition from validated to serialized state.
154
155
Converts validated data to primitive representation.
156
"""
157
158
def can(self, state):
159
"""
160
Check if transition to state is possible.
161
162
Args:
163
state (str): Target state name
164
165
Returns:
166
bool: True if transition is valid
167
"""
168
169
def cannot(self, state):
170
"""
171
Check if transition to state is not possible.
172
173
Args:
174
state (str): Target state name
175
176
Returns:
177
bool: True if transition is invalid
178
"""
179
```
180
181
## Usage Examples
182
183
### MongoDB ObjectId Fields
184
185
```python
186
from schematics.models import Model
187
from schematics.types import StringType
188
from schematics.contrib.mongo import ObjectIdType
189
import bson
190
191
class Document(Model):
192
_id = ObjectIdType(auto_fill=True)
193
title = StringType(required=True)
194
content = StringType()
195
196
# Create with string ObjectId
197
doc = Document({
198
'_id': '507f1f77bcf86cd799439011',
199
'title': 'My Document',
200
'content': 'Document content here'
201
})
202
203
doc.validate() # Converts string to ObjectId
204
205
# Access as BSON ObjectId
206
object_id = doc._id # bson.ObjectId('507f1f77bcf86cd799439011')
207
id_string = doc.to_primitive()['_id'] # '507f1f77bcf86cd799439011'
208
209
# Auto-fill generates new ObjectId
210
new_doc = Document({'title': 'Auto ID Document'})
211
new_doc.validate() # _id is automatically generated
212
```
213
214
### Enum Field Usage
215
216
```python
217
import enum
218
from schematics.models import Model
219
from schematics.types import StringType
220
from schematics.contrib.enum_type import EnumType
221
222
class Status(enum.Enum):
223
DRAFT = 'draft'
224
PUBLISHED = 'published'
225
ARCHIVED = 'archived'
226
227
class Priority(enum.Enum):
228
LOW = 1
229
MEDIUM = 2
230
HIGH = 3
231
232
class Article(Model):
233
title = StringType(required=True)
234
status = EnumType(Status, required=True)
235
priority = EnumType(Priority, use_values=True) # Accept numeric values
236
237
# Using enum members
238
article = Article({
239
'title': 'My Article',
240
'status': Status.DRAFT, # Direct enum member
241
'priority': Priority.HIGH # Direct enum member
242
})
243
244
# Using enum names/values
245
article2 = Article({
246
'title': 'Another Article',
247
'status': 'published', # String name -> Status.PUBLISHED
248
'priority': 2 # Numeric value -> Priority.MEDIUM (use_values=True)
249
})
250
251
article.validate() # Success
252
article2.validate() # Success
253
254
# Export behavior
255
primitive_data = article.to_primitive()
256
# {'title': 'My Article', 'status': 'DRAFT', 'priority': 3}
257
258
primitive_data2 = article2.to_primitive()
259
# {'title': 'Another Article', 'status': 'PUBLISHED', 'priority': 2}
260
```
261
262
### State Machine Workflow
263
264
```python
265
from schematics.models import Model
266
from schematics.types import StringType, IntType
267
from schematics.contrib.machine import Machine
268
269
class User(Model):
270
name = StringType(required=True)
271
age = IntType(min_value=0, required=True)
272
273
# Raw data processing workflow
274
raw_data = {'name': 'John Doe', 'age': '30'} # Age as string
275
user_schema = User
276
277
# Initialize state machine
278
machine = Machine(raw_data, user_schema)
279
print(machine.state) # 'raw'
280
281
# Convert data types
282
machine.convert()
283
print(machine.state) # 'converted'
284
print(machine.data) # {'name': 'John Doe', 'age': 30} - age now integer
285
286
# Validate converted data
287
machine.validate()
288
print(machine.state) # 'validated'
289
290
# Serialize to primitives
291
machine.serialize()
292
print(machine.state) # 'serialized'
293
print(machine.data) # Final primitive representation
294
295
# Check valid transitions
296
print(machine.can('raw')) # False - can't go back to raw
297
print(machine.cannot('raw')) # True - cannot transition to raw
298
```
299
300
### Combined Usage Example
301
302
```python
303
import enum
304
from schematics.models import Model
305
from schematics.types import StringType, DateTimeType
306
from schematics.contrib.mongo import ObjectIdType
307
from schematics.contrib.enum_type import EnumType
308
from datetime import datetime
309
310
class DocumentStatus(enum.Enum):
311
DRAFT = 'draft'
312
REVIEW = 'review'
313
PUBLISHED = 'published'
314
315
class BlogPost(Model):
316
_id = ObjectIdType()
317
title = StringType(required=True, max_length=200)
318
content = StringType(required=True)
319
status = EnumType(DocumentStatus, default=DocumentStatus.DRAFT)
320
created_at = DateTimeType(default=datetime.utcnow)
321
updated_at = DateTimeType()
322
323
# Create blog post with mixed field types
324
post_data = {
325
'title': 'Understanding Schematics',
326
'content': 'Schematics is a powerful data validation library...',
327
'status': 'review', # String converted to enum
328
'created_at': '2024-01-15T10:30:00Z'
329
}
330
331
post = BlogPost(post_data)
332
post.validate()
333
334
# Export for API
335
api_response = post.to_primitive()
336
# {
337
# '_id': None, # Not set
338
# 'title': 'Understanding Schematics',
339
# 'content': 'Schematics is a powerful data validation library...',
340
# 'status': 'REVIEW',
341
# 'created_at': '2024-01-15T10:30:00+00:00',
342
# 'updated_at': None
343
# }
344
345
# Save to MongoDB (conceptual)
346
post._id = ObjectIdType().to_native('507f1f77bcf86cd799439011')
347
post.status = DocumentStatus.PUBLISHED
348
post.updated_at = datetime.utcnow()
349
350
final_data = post.to_primitive()
351
# Now includes ObjectId string and updated status/timestamp
352
```