Skip to content

Commit 0c66c7c

Browse files
committed
Merge pull request #3000 from linovia/ovangle/uuid_format2
Add 'format' argument to UUIDField
2 parents bb97485 + ea00fc7 commit 0c66c7c

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

docs/api-guide/fields.md

Lines changed: 9 additions & 0 deletions
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: `"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`
190+
- `'hex'` - The compact hex representation of the UUID, not including hyphens: `"5ce0e9a55ffa654bcee01238041fb31a"`
191+
- `'int'` - A 128 bit integer representation of the UUID: `"123456789012312313134124512351145145114"`
192+
- `'urn'` - RFC 4122 URN representation of the UUID: `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`
193+
Changing the `format` parameters only affects representation values. All formats are accepted by `to_internal_value`
194+
186195
---
187196

188197
# Numeric fields

rest_framework/fields.py

Lines changed: 19 additions & 2 deletions
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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,9 @@ class TestUUIDField(FieldValues):
525525
"""
526526
valid_inputs = {
527527
'825d7aeb-05a9-45b5-a5b7-05df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
528-
'825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda')
528+
'825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
529+
'urn:uuid:213b7d9b-244f-410d-828c-dabce7a2615d': uuid.UUID('213b7d9b-244f-410d-828c-dabce7a2615d'),
530+
284758210125106368185219588917561929842: uuid.UUID('d63a6fb6-88d5-40c7-a91c-9edf73283072')
529531
}
530532
invalid_inputs = {
531533
'825d7aeb-05a9-45b5-a5b7': ['"825d7aeb-05a9-45b5-a5b7" is not a valid UUID.']
@@ -535,6 +537,17 @@ class TestUUIDField(FieldValues):
535537
}
536538
field = serializers.UUIDField()
537539

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

539552
# Number types...
540553

0 commit comments

Comments
 (0)