Skip to content

Commit cdd3aca

Browse files
committed
Add 'format' argument to UUIDField
To allow serializations to control the representation format of a UUID value
1 parent 5cf8230 commit cdd3aca

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

docs/api-guide/fields.md

+9
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ A field that ensures the input is a valid UUID string. The `to_internal_value` m
183183

184184
"de305d54-75b4-431b-adb2-eb6b9e546013"
185185

186+
**Signature:** `UUIDField(format='hex_verbose')`
187+
188+
- `format`: Determines the representation format of the uuid value
189+
- `'hex_verbose'` - The cannoncical hex representation, including hyphens
190+
- `'hex'` - The compact hex representation of the UUID, not including hyphens
191+
- `'int'` - A 128 bit integer representation of the UUID.
192+
- `'urn'` - RFC 4122 URN representation of the UUID
193+
The `to_internal_value` will accept any of the string formats of a UUID unless the `format` is `'int'`, when it will accept a
194+
186195
---
187196

188197
# Numeric fields

rest_framework/fields.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -639,20 +639,37 @@ def __init__(self, **kwargs):
639639

640640

641641
class UUIDField(Field):
642+
valid_formats = ('hex_verbose', 'hex', 'int', 'urn')
643+
642644
default_error_messages = {
643645
'invalid': _('"{value}" is not a valid UUID.'),
644646
}
645647

648+
def __init__(self, **kwargs):
649+
self.uuid_format = kwargs.pop('format', 'hex_verbose')
650+
if self.uuid_format not in self.valid_formats:
651+
raise ValueError(
652+
'Invalid format for uuid representation. '
653+
'Must be one of "{0}"'.format('", "'.join(self.valid_formats))
654+
)
655+
super(UUIDField, self).__init__(**kwargs)
656+
646657
def to_internal_value(self, data):
647658
if not isinstance(data, uuid.UUID):
648659
try:
649-
return uuid.UUID(data)
660+
if isinstance(data, six.integer_types):
661+
return uuid.UUID(int=data)
662+
else:
663+
return uuid.UUID(hex=data)
650664
except (ValueError, TypeError):
651665
self.fail('invalid', value=data)
652666
return data
653667

654668
def to_representation(self, value):
655-
return str(value)
669+
if self.uuid_format == 'hex_verbose':
670+
return str(value)
671+
else:
672+
return getattr(value, self.uuid_format)
656673

657674

658675
# Number types...

tests/test_fields.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,9 @@ class TestUUIDField(FieldValues):
526526
"""
527527
valid_inputs = {
528528
'825d7aeb-05a9-45b5-a5b7-05df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
529-
'825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda')
529+
'825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
530+
'urn:uuid:213b7d9b-244f-410d-828c-dabce7a2615d': uuid.UUID('213b7d9b-244f-410d-828c-dabce7a2615d'),
531+
284758210125106368185219588917561929842: uuid.UUID('d63a6fb6-88d5-40c7-a91c-9edf73283072')
530532
}
531533
invalid_inputs = {
532534
'825d7aeb-05a9-45b5-a5b7': ['"825d7aeb-05a9-45b5-a5b7" is not a valid UUID.']
@@ -536,6 +538,17 @@ class TestUUIDField(FieldValues):
536538
}
537539
field = serializers.UUIDField()
538540

541+
def _test_format(self, uuid_format, formatted_uuid_0):
542+
field = serializers.UUIDField(format=uuid_format)
543+
assert field.to_representation(uuid.UUID(int=0)) == formatted_uuid_0
544+
assert field.to_internal_value(formatted_uuid_0) == uuid.UUID(int=0)
545+
546+
def test_formats(self):
547+
self._test_format('int', 0)
548+
self._test_format('hex_verbose', '00000000-0000-0000-0000-000000000000')
549+
self._test_format('urn', 'urn:uuid:00000000-0000-0000-0000-000000000000')
550+
self._test_format('hex', '0' * 32)
551+
539552

540553
# Number types...
541554

0 commit comments

Comments
 (0)