Skip to content

Commit

Permalink
Merge pull request #2448 from tomchristie/uuid-field
Browse files Browse the repository at this point in the history
Added UUIDField.
  • Loading branch information
tomchristie committed Jan 23, 2015
2 parents 47ddbc0 + 889a07f commit b07d931
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 2 deletions.
8 changes: 7 additions & 1 deletion docs/api-guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ Corresponds to `django.db.models.fields.URLField`. Uses Django's `django.core.v

**Signature:** `URLField(max_length=200, min_length=None, allow_blank=False)`

## UUIDField

A field that ensures the input is a valid UUID string. The `to_internal_value` method will return a `uuid.UUID` instance. On output the field will return a string in the canonical hyphenated format, for example:

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

---

# Numeric fields
Expand Down Expand Up @@ -320,7 +326,7 @@ Both the `allow_blank` and `allow_null` are valid options on `ChoiceField`, alth

## MultipleChoiceField

A field that can accept a set of zero, one or many values, chosen from a limited set of choices. Takes a single mandatory argument. `to_internal_representation` returns a `set` containing the selected values.
A field that can accept a set of zero, one or many values, chosen from a limited set of choices. Takes a single mandatory argument. `to_internal_value` returns a `set` containing the selected values.

**Signature:** `MultipleChoiceField(choices)`

Expand Down
18 changes: 18 additions & 0 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import decimal
import inspect
import re
import uuid


class empty:
Expand Down Expand Up @@ -632,6 +633,23 @@ def __init__(self, **kwargs):
self.validators.append(validator)


class UUIDField(Field):
default_error_messages = {
'invalid': _('"{value}" is not a valid UUID.'),
}

def to_internal_value(self, data):
if not isinstance(data, uuid.UUID):
try:
return uuid.UUID(data)
except (ValueError, TypeError):
self.fail('invalid', value=data)
return data

def to_representation(self, value):
return str(value)


# Number types...

class IntegerField(Field):
Expand Down
8 changes: 7 additions & 1 deletion rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ class ModelSerializer(Serializer):
you need you should either declare the extra/differing fields explicitly on
the serializer class, or simply use a `Serializer` class.
"""

_field_mapping = ClassLookupDict({
models.AutoField: IntegerField,
models.BigIntegerField: IntegerField,
Expand All @@ -724,7 +725,8 @@ class ModelSerializer(Serializer):
models.SmallIntegerField: IntegerField,
models.TextField: CharField,
models.TimeField: TimeField,
models.URLField: URLField,
models.URLField: URLField
# Note: Some version-specific mappings also defined below.
})
_related_class = PrimaryKeyRelatedField

Expand Down Expand Up @@ -1132,6 +1134,10 @@ class Meta:
return NestedSerializer


if hasattr(models, 'UUIDField'):
ModelSerializer._field_mapping[models.UUIDField] = UUIDField


class HyperlinkedModelSerializer(ModelSerializer):
"""
A type of `ModelSerializer` that uses hyperlinked relationships instead
Expand Down
3 changes: 3 additions & 0 deletions rest_framework/utils/field_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def __getitem__(self, key):
return self.mapping[cls]
raise KeyError('Class %s not found in lookup.', cls.__name__)

def __setitem__(self, key, value):
self.mapping[key] = value


def needs_label(model_field, field_name):
"""
Expand Down
18 changes: 18 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import datetime
import django
import pytest
import uuid


# Tests for field keyword arguments and core functionality.
Expand Down Expand Up @@ -467,6 +468,23 @@ class TestURLField(FieldValues):
field = serializers.URLField()


class TestUUIDField(FieldValues):
"""
Valid and invalid values for `UUIDField`.
"""
valid_inputs = {
'825d7aeb-05a9-45b5-a5b7-05df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
'825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda')
}
invalid_inputs = {
'825d7aeb-05a9-45b5-a5b7': ['"825d7aeb-05a9-45b5-a5b7" is not a valid UUID.']
}
outputs = {
uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'): '825d7aeb-05a9-45b5-a5b7-05df87923cda'
}
field = serializers.UUIDField()


# Number types...

class TestIntegerField(FieldValues):
Expand Down

0 comments on commit b07d931

Please sign in to comment.