Commit 0a91999d by Tymur Maryokhin

Merge branch 'master' of github.com:tomchristie/django-rest-framework

parents e2ea98e8 d1fe61ce
<a class="github" href="validators.py"></a>
source: validators.py
---
......
......@@ -11,6 +11,8 @@
**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
For more details see the [3.0 release notes][3.0-announcement].
---
<p>
......@@ -201,6 +203,7 @@ General guides to using REST framework.
* [2.2 Announcement][2.2-announcement]
* [2.3 Announcement][2.3-announcement]
* [2.4 Announcement][2.4-announcement]
* [3.0 Announcement][3.0-announcement]
* [Kickstarter Announcement][kickstarter-announcement]
* [Release Notes][release-notes]
* [Credits][credits]
......@@ -319,6 +322,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[2.2-announcement]: topics/2.2-announcement.md
[2.3-announcement]: topics/2.3-announcement.md
[2.4-announcement]: topics/2.4-announcement.md
[3.0-announcement]: topics/3.0-announcement.md
[kickstarter-announcement]: topics/kickstarter-announcement.md
[release-notes]: topics/release-notes.md
[credits]: topics/credits.md
......
......@@ -50,6 +50,7 @@ pages:
- ['topics/2.2-announcement.md', 'Topics', '2.2 Announcement']
- ['topics/2.3-announcement.md', 'Topics', '2.3 Announcement']
- ['topics/2.4-announcement.md', 'Topics', '2.4 Announcement']
- ['topics/3.0-announcement.md', 'Topics', '3.0 Announcement']
- ['topics/kickstarter-announcement.md', 'Topics', 'Kickstarter Announcement']
- ['topics/release-notes.md', 'Topics', 'Release Notes']
- ['topics/credits.md', 'Topics', 'Credits']
......@@ -11,6 +11,7 @@ python primitives.
response content is handled by parsers and renderers.
"""
from django.core.exceptions import ImproperlyConfigured
from django.core.exceptions import ValidationError as DjangoValidationError
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.utils import six
......@@ -330,6 +331,14 @@ class Serializer(BaseSerializer):
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [exc.detail]
})
except DjangoValidationError as exc:
# Normally you should raise `serializers.ValidationError`
# inside your codebase, but we handle Django's validation
# exception class as well for simpler compat.
# Eg. Calling Model.clean() explictily inside Serializer.validate()
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: list(exc.messages)
})
return value
......@@ -353,6 +362,8 @@ class Serializer(BaseSerializer):
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = list(exc.messages)
except SkipField:
pass
else:
......@@ -554,6 +565,14 @@ class ModelSerializer(Serializer):
* A set of default fields are automatically populated.
* A set of default validators are automatically populated.
* Default `.create()` and `.update()` implementations are provided.
The process of automatically determining a set of serializer fields
based on the model fields is reasonably complex, but you almost certainly
don't need to dig into the implemention.
If the `ModelSerializer` class *doesn't* generate the set of fields that
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,
......@@ -582,6 +601,26 @@ class ModelSerializer(Serializer):
_related_class = PrimaryKeyRelatedField
def create(self, validated_attrs):
"""
We have a bit of extra checking around this in order to provide
descriptive messages when something goes wrong, but this method is
essentially just:
return ExampleModel.objects.create(**validated_attrs)
If there are many to many fields present on the instance then they
cannot be set until the model is instantiated, in which case the
implementation is like so:
example_relationship = validated_attrs.pop('example_relationship')
instance = ExampleModel.objects.create(**validated_attrs)
instance.example_relationship = example_relationship
return instance
The default implementation also does not handle nested relationships.
If you want to support writable nested relationships you'll need
to write an explicit `.create()` method.
"""
# Check that the user isn't trying to handle a writable nested field.
# If we don't do this explicitly they'd likely get a confusing
# error at the point of calling `Model.objects.create()`.
......@@ -632,14 +671,19 @@ class ModelSerializer(Serializer):
return instance
def get_validators(self):
# If the validators have been declared explicitly then use that.
validators = getattr(getattr(self, 'Meta', None), 'validators', None)
if validators is not None:
return validators
# Determine the default set of validators.
validators = []
model_class = self.Meta.model
field_names = set([
field.source for field in self.fields.values()
if (field.source != '*') and ('.' not in field.source)
])
validators = getattr(getattr(self, 'Meta', None), 'validators', [])
model_class = self.Meta.model
# Note that we make sure to check `unique_together` both on the
# base model class, but also on any parent classes.
for parent_class in [model_class] + list(model_class._meta.parents.keys()):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment