From e2ea98e8ab3192fa8d252d33cc03929fcf6ed02f Mon Sep 17 00:00:00 2001 From: Tymur Maryokhin Date: Sat, 29 Nov 2014 20:23:55 +0100 Subject: Fixed typos --- docs/index.md | 4 ++-- docs/topics/2.3-announcement.md | 6 +++--- docs/topics/release-notes.md | 4 ++-- docs/tutorial/6-viewsets-and-routers.md | 4 ++-- docs/tutorial/quickstart.md | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index b5257c73..feada2a9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ Django REST framework is a powerful and flexible toolkit that makes it easy to b Some reasons you might want to use REST framework: -* The [Web browseable API][sandbox] is a huge usability win for your developers. +* The [Web browsable API][sandbox] is a huge usability win for your developers. * [Authentication policies][authentication] including [OAuth1a][oauth1-section] and [OAuth2][oauth2-section] out of the box. * [Serialization][serializers] that supports both [ORM][modelserializer-section] and [non-ORM][serializer-section] data sources. * Customizable all the way down - just use [regular function-based views][functionview-section] if you don't need the [more][generic-views] [powerful][viewsets] [features][routers]. @@ -132,7 +132,7 @@ Here's our project's root `urls.py` module: router.register(r'users', UserViewSet) # Wire up our API using automatic URL routing. - # Additionally, we include login URLs for the browseable API. + # Additionally, we include login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) diff --git a/docs/topics/2.3-announcement.md b/docs/topics/2.3-announcement.md index 9c9f3e9f..66e46865 100644 --- a/docs/topics/2.3-announcement.md +++ b/docs/topics/2.3-announcement.md @@ -35,7 +35,7 @@ As an example of just how simple REST framework APIs can now be, here's an API w # Wire up our API using automatic URL routing. - # Additionally, we include login URLs for the browseable API. + # Additionally, we include login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) @@ -207,9 +207,9 @@ The old-style signature will continue to function but will raise a `PendingDepre ## View names and descriptions -The mechanics of how the names and descriptions used in the browseable API are generated has been modified and cleaned up somewhat. +The mechanics of how the names and descriptions used in the browsable API are generated has been modified and cleaned up somewhat. -If you've been customizing this behavior, for example perhaps to use `rst` markup for the browseable API, then you'll need to take a look at the implementation to see what updates you need to make. +If you've been customizing this behavior, for example perhaps to use `rst` markup for the browsable API, then you'll need to take a look at the implementation to see what updates you need to make. Note that the relevant methods have always been private APIs, and the docstrings called them out as intended to be deprecated. diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 53187589..19dfbb98 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -121,7 +121,7 @@ You can determine your currently installed version using `pip freeze`: * Add `UnicodeYAMLRenderer` that extends `YAMLRenderer` with unicode. * Fix `parse_header` argument convertion. * Fix mediatype detection under Python 3. -* Web browseable API now offers blank option on dropdown when the field is not required. +* Web browsable API now offers blank option on dropdown when the field is not required. * `APIException` representation improved for logging purposes. * Allow source="*" within nested serializers. * Better support for custom oauth2 provider backends. @@ -200,7 +200,7 @@ You can determine your currently installed version using `pip freeze`: * Added `MAX_PAGINATE_BY` setting and `max_paginate_by` generic view attribute. * Added `cache` attribute to throttles to allow overriding of default cache. * 'Raw data' tab in browsable API now contains pre-populated data. -* 'Raw data' and 'HTML form' tab preference in browseable API now saved between page views. +* 'Raw data' and 'HTML form' tab preference in browsable API now saved between page views. * Bugfix: `required=True` argument fixed for boolean serializer fields. * Bugfix: `client.force_authenticate(None)` should also clear session info if it exists. * Bugfix: Client sending empty string instead of file now clears `FileField`. diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index 3fad509a..816e9da6 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -112,7 +112,7 @@ Here's our re-wired `urls.py` file. router.register(r'users', views.UserViewSet) # The API URLs are now determined automatically by the router. - # Additionally, we include the login URLs for the browseable API. + # Additionally, we include the login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) @@ -130,7 +130,7 @@ That doesn't mean it's always the right approach to take. There's a similar set ## Reviewing our work -With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browseable, and comes complete with authentication, per-object permissions, and multiple renderer formats. +With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, and comes complete with authentication, per-object permissions, and multiple renderer formats. We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views. diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 1c398c1f..3e1ce0a9 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -100,7 +100,7 @@ Okay, now let's wire up the API URLs. On to `tutorial/urls.py`... router.register(r'groups', views.GroupViewSet) # Wire up our API using automatic URL routing. - # Additionally, we include login URLs for the browseable API. + # Additionally, we include login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) -- cgit v1.2.3 From bc0c25df3020772124e1767895c7e7cb60d974c1 Mon Sep 17 00:00:00 2001 From: José Padilla Date: Mon, 1 Dec 2014 17:31:11 -0400 Subject: Consolidate Django and test requirements --- docs/topics/contributing.md | 1 - docs/topics/third-party-resources.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 99f4fc3c..c9626ebf 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -62,7 +62,6 @@ To run the tests, clone the repository, and then: virtualenv env source env/bin/activate pip install -r requirements.txt - pip install -r requirements-test.txt # Run the tests ./runtests.py diff --git a/docs/topics/third-party-resources.md b/docs/topics/third-party-resources.md index efa0b91f..0358d614 100644 --- a/docs/topics/third-party-resources.md +++ b/docs/topics/third-party-resources.md @@ -93,7 +93,7 @@ The cookiecutter template includes a `runtests.py` which uses the `pytest` packa Before running, you'll need to install a couple test requirements. - $ pip install -r requirements-test.txt + $ pip install -r requirements.txt Once requirements installed, you can run `runtests.py`. -- cgit v1.2.3 From f4fc4670ca491eabd5bcdfcef382d8373dd5e380 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 2 Dec 2014 08:53:36 +0000 Subject: Promote 'many_init' to public API. Closes #2152. --- docs/api-guide/serializers.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 0ee80d53..4c78473e 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -689,6 +689,21 @@ Here's an example of how you might choose to implement multiple updates: It is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the `allow_add_remove` behavior that was present in REST framework 2. +#### Customizing ListSerializer initialization + +When a serializer with `many=True` is instantiated, we need to determine which arguments and keyword arguments should be passed to the `.__init__()` method for both the child `Serializer` class, and for the parent `ListSerializer` class. + +The default implementation is to pass all arguments to both classes, except for `validators`, and any custom keyword arguments, both of which are assumed to be intended for the child serializer class. + +Occasionally you might need to explicitly specify how the child and parent classes should be instantiated when `many=True` is passed. You can do so by using the `many_init` class method. + + @classmethod + def many_init(cls, *args, **kwargs): + # Instantiate the child serializer. + kwargs['child'] = cls() + # Instantiate the parent list serializer. + return CustomListSerializer(*args, **kwargs) + --- # BaseSerializer -- cgit v1.2.3 From 6ac79b822325784ad145ff0ad064127750c4f7e0 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 2 Dec 2014 09:19:59 +0000 Subject: Document Field.fail(). Closes #2147. --- docs/api-guide/fields.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 391a52e5..aa5cc84e 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -453,7 +453,7 @@ If you want to create a custom field, you'll need to subclass `Field` and then o The `.to_representation()` method is called to convert the initial datatype into a primitive, serializable datatype. -The `to_internal_value()` method is called to restore a primitive datatype into its internal python representation. +The `to_internal_value()` method is called to restore a primitive datatype into its internal python representation. This method should raise a `serializer.ValidationError` if the data is invalid. Note that the `WritableField` class that was present in version 2.x no longer exists. You should subclass `Field` and override `to_internal_value()` if the field supports data input. @@ -498,6 +498,53 @@ As an example, let's create a field that can be used represent the class name of """ return obj.__class__.__name__ +#### Raising validation errors + +Our `ColorField` class above currently does not perform any data validation. +To indicate invalid data, we should raise a `serializers.ValidationError`, like so: + + def to_internal_value(self, data): + if not isinstance(data, six.text_type): + msg = 'Incorrect type. Expected a string, but got %s' + raise ValidationError(msg % type(data).__name__) + + if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data): + raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.') + + data = data.strip('rgb(').rstrip(')') + red, green, blue = [int(col) for col in data.split(',')] + + if any([col > 255 or col < 0 for col in (red, green, blue)]): + raise ValidationError('Value out of range. Must be between 0 and 255.') + + return Color(red, green, blue) + +The `.fail()` method is a shortcut for raising `ValidationError` that takes a message string from the `error_messages` dictionary. For example: + + default_error_messages = { + 'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}', + 'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.', + 'out_of_range': 'Value out of range. Must be between 0 and 255.' + } + + def to_internal_value(self, data): + if not isinstance(data, six.text_type): + msg = 'Incorrect type. Expected a string, but got %s' + self.fail('incorrect_type', input_type=type(data).__name__) + + if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data): + self.fail('incorrect_format') + + data = data.strip('rgb(').rstrip(')') + red, green, blue = [int(col) for col in data.split(',')] + + if any([col > 255 or col < 0 for col in (red, green, blue)]): + self.fail('out_of_range') + + return Color(red, green, blue) + +This style keeps you error messages more cleanly separated from your code, and should be preferred. + # Third party packages The following third party packages are also available. -- cgit v1.2.3 From 84cff98fbf72355cb5e8359aa1c9b5568c289cbf Mon Sep 17 00:00:00 2001 From: David Ray Date: Tue, 2 Dec 2014 09:46:43 -0500 Subject: fix typo --- docs/api-guide/serializers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 4c78473e..a011bb52 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -96,7 +96,7 @@ If we want to be able to return complete object instances based on the validated If your object instances correspond to Django models you'll also want to ensure that these methods save the object to the database. For example, if `Comment` was a Django model, the methods might look like this: def create(self, validated_data): - return Comment.objcts.create(**validated_data) + return Comment.objects.create(**validated_data) def update(self, instance, validated_data): instance.email = validated_data.get('email', instance.email) -- cgit v1.2.3 From 5ad22aea605f888e06186d907674669c46a611ef Mon Sep 17 00:00:00 2001 From: Matías Lang Date: Tue, 2 Dec 2014 12:23:25 -0300 Subject: Updated serializers documentation There was an error in the docs: the field extra_field_kwargs of the serializer's Meta doesn't work. The field must be extra_kwargs instead.--- docs/api-guide/serializers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index a011bb52..1779c863 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -567,13 +567,13 @@ There needs to be a way of determining which views should be used for hyperlinki By default hyperlinks are expected to correspond to a view name that matches the style `'{model_name}-detail'`, and looks up the instance by a `pk` keyword argument. -You can override a URL field view name and lookup field by using either, or both of, the `view_name` and `lookup_field` options in the `extra_field_kwargs` setting, like so: +You can override a URL field view name and lookup field by using either, or both of, the `view_name` and `lookup_field` options in the `extra_kwargs` setting, like so: class AccountSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Account fields = ('account_url', 'account_name', 'users', 'created') - extra_field_kwargs = { + extra_kwargs = { 'url': {'view_name': 'accounts', 'lookup_field': 'account_name'} 'users': {'lookup_field': 'username'} } -- cgit v1.2.3 From 74a9ece3dcf76372c26aaf3bdd6c48bbfbf45f99 Mon Sep 17 00:00:00 2001 From: eiriksm Date: Wed, 3 Dec 2014 13:37:56 +0100 Subject: Update build status icon on github pages page. --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index e0ba2332..52e42fc9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ - +

--- -- cgit v1.2.3 From ab25d706c78627dfd582fe9d142ada510c4d6d90 Mon Sep 17 00:00:00 2001 From: Martin Tschammer Date: Wed, 3 Dec 2014 23:52:35 +0100 Subject: Renamed validated_attrs to validated_data to be more in line with other similar code. --- docs/tutorial/1-serialization.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index a3c19858..52c75d2c 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -110,21 +110,21 @@ The first thing we need to get started on our Web API is to provide a way of ser style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly') - def create(self, validated_attrs): + def create(self, validated_data): """ Create and return a new `Snippet` instance, given the validated data. """ - return Snippet.objects.create(**validated_attrs) + return Snippet.objects.create(**validated_data) - def update(self, instance, validated_attrs): + def update(self, instance, validated_data): """ Update and return an existing `Snippet` instance, given the validated data. """ - instance.title = validated_attrs.get('title', instance.title) - instance.code = validated_attrs.get('code', instance.code) - instance.linenos = validated_attrs.get('linenos', instance.linenos) - instance.language = validated_attrs.get('language', instance.language) - instance.style = validated_attrs.get('style', instance.style) + instance.title = validated_data.get('title', instance.title) + instance.code = validated_data.get('code', instance.code) + instance.linenos = validated_data.get('linenos', instance.linenos) + instance.language = validated_data.get('language', instance.language) + instance.style = validated_data.get('style', instance.style) instance.save() return instance -- cgit v1.2.3