Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream #3

Merged
merged 35 commits into from
Dec 5, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
dbb435c
Added missing default style for FileField
kchang Nov 12, 2014
ad060aa
More helpful error message when default `.create` fails. Closes #2013.
gregmuellegger Nov 15, 2014
2f03483
Removed unused models
maryokhin Nov 29, 2014
dd9d40d
Moved non-conflicting models
maryokhin Nov 29, 2014
e2ea98e
Fixed typos
maryokhin Nov 29, 2014
bc0c25d
Consolidate Django and test requirements
jpadilla Dec 1, 2014
0a91999
Merge branch 'master' of github.com:tomchristie/django-rest-framework
maryokhin Dec 2, 2014
d847e33
Merge pull request #2161 from NextHub/master
tomchristie Dec 2, 2014
deec61e
Merge pull request #2173 from jpadilla/master
tomchristie Dec 2, 2014
f4fc467
Promote 'many_init' to public API. Closes #2152.
tomchristie Dec 2, 2014
53f5276
Not allow to pass an empty actions to viewset.as_view(). Refs issue #…
BrickXu Dec 2, 2014
6ac79b8
Document Field.fail(). Closes #2147.
tomchristie Dec 2, 2014
79e18a2
Raise assertion error if calling .save() on a serializer with errors.…
tomchristie Dec 2, 2014
54b7b32
Merge branch 'fixes/2013' of git://github.com/gregmuellegger/django-r…
tomchristie Dec 2, 2014
76ac641
Minor tweaks for helpful message on Model.objects.create() failure.
tomchristie Dec 2, 2014
41045c1
Merge branch 'gregmuellegger-fixes/2013'
tomchristie Dec 2, 2014
e30e3f6
Update README with 3.0 info.
tomchristie Dec 2, 2014
0359e92
FileUploadParser. Raising StopFutureHandlers removes any handlers not…
tomchristie Dec 2, 2014
84cff98
fix typo
daaray Dec 2, 2014
e335ad4
Merge pull request #2181 from daaray/patch-2
tomchristie Dec 2, 2014
33096a1
BindingDict inherits from collections.MutableMapping. Closes #2135.
tomchristie Dec 2, 2014
2123685
Merge branch 'master' of https://github.com/tomchristie/django-rest-f…
tomchristie Dec 2, 2014
5ad22ae
Updated serializers documentation
cript0nauta Dec 2, 2014
95d57e6
Merge pull request #2182 from sh4r3m4n/master
tomchristie Dec 2, 2014
9397a65
Use svg version of travis build status badge
eiriksm Dec 3, 2014
71a8cb2
Merge pull request #2185 from eiriksm/patch-1
tomchristie Dec 3, 2014
c5a2d50
Merge pull request #2175 from BrickXu/fix_2171
tomchristie Dec 3, 2014
74a9ece
Update build status icon on github pages page.
eiriksm Dec 3, 2014
5f2f54b
Merge pull request #2188 from eiriksm/patch-2
tomchristie Dec 3, 2014
f2dd05a
Improved nested update test in update().
tomchristie Dec 3, 2014
e1d98f7
Improve nested update and create testing.
tomchristie Dec 3, 2014
ab25d70
Renamed validated_attrs to validated_data to be more in line with oth…
mtschammer Dec 3, 2014
66bce38
Merge pull request #2196 from tomchristie/tomchristie-improve-update-…
kevin-brown Dec 3, 2014
f221b73
Merge pull request #2197 from mtschammer/mtschammer-validated_attrs-r…
tomchristie Dec 3, 2014
e8cbf41
Merge pull request #2172 from kchange/master
tomchristie Dec 4, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ If you use REST framework, we'd love you to be vocal about your experiences with

Other really great ways you can help move the community forward include helping answer questions on the [discussion group][google-group], or setting up an [email alert on StackOverflow][so-filter] so that you get notified of any new questions with the `django-rest-framework` tag.

When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.
When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.

## Code of conduct

Expand All @@ -38,7 +38,7 @@ Some tips on good issue reporting:

## Triaging issues

Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to
Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to

* Read through the ticket - does it make sense, is it missing any context that would help explain it better?
* Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?
Expand All @@ -62,7 +62,6 @@ To run the tests, clone the repository, and then:
virtualenv env
env/bin/activate
pip install -r requirements.txt
pip install -r requirements-test.txt

# Run the tests
./runtests.py
Expand Down Expand Up @@ -130,8 +129,8 @@ There are a couple of conventions you should follow when working on the document
Headers should use the hash style. For example:

### Some important topic
The underline style should not be used. **Don't do this:**

The underline style should not be used. **Don't do this:**

Some important topic
====================
Expand All @@ -141,9 +140,9 @@ The underline style should not be used. **Don't do this:**
Links should always use the reference style, with the referenced hyperlinks kept at the end of the document.

Here is a link to [some other thing][other-thing].

More text...

[other-thing]: http://example.com/other/thing

This style helps keep the documentation source consistent and readable.
Expand All @@ -159,9 +158,9 @@ Linking in this style means you'll be able to click the hyperlink in your markdo
If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:

---

**Note:** A useful documentation note.

---

# Third party packages
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
[![build-status-image]][travis]
[![pypi-version]][pypi]

**Awesome web-browseable Web APIs.**
**Awesome web-browsable Web APIs.**

Full documentation for the project is available at [http://www.django-rest-framework.org][docs].

---

**Note**: The incoming 3.0 version has now been merged to the `master` branch on GitHub. For the source of the currently available PyPI version, please see the `2.4.4` tag.
**Note**: We have now released Django REST framework 3.0. For older codebases you may want to refer to the version 2.4.4 [source code](https://github.com/tomchristie/django-rest-framework/tree/version-2.4.x), and [documentation](http://tomchristie.github.io/rest-framework-2-docs/).

---

Expand All @@ -19,15 +19,15 @@ Django REST framework is a powerful and flexible toolkit for building Web APIs.

Some reasons you might want to use REST framework:

* The [Web browseable API][sandbox] is a huge useability 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].
* [Extensive documentation][index], and [great community support][group].

There is a live example API for testing purposes, [available here][sandbox].

**Below**: *Screenshot from the browseable API*
**Below**: *Screenshot from the browsable API*

![Screenshot][image]

Expand Down Expand Up @@ -86,7 +86,7 @@ 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'))
Expand Down Expand Up @@ -180,7 +180,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


[build-status-image]: https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=master
[build-status-image]: https://secure.travis-ci.org/tomchristie/django-rest-framework.svg?branch=master
[travis]: http://travis-ci.org/tomchristie/django-rest-framework?branch=master
[pypi-version]: https://pypip.in/version/djangorestframework/badge.svg
[pypi]: https://pypi.python.org/pypi/djangorestframework
Expand Down
49 changes: 48 additions & 1 deletion docs/api-guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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.
Expand Down
21 changes: 18 additions & 3 deletions docs/api-guide/serializers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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'}
}
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<a href="https://twitter.com/share" class="twitter-share-button" data-url="django-rest-framework.org" data-text="Checking out the totally awesome Django REST framework! http://www.django-rest-framework.org" data-count="none"></a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="http://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

<img src="https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=master" class="travis-build-image">
<img src="https://secure.travis-ci.org/tomchristie/django-rest-framework.svg?branch=master" class="travis-build-image">
</p>

---
Expand Down Expand Up @@ -33,7 +33,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].
Expand Down Expand Up @@ -134,7 +134,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'))
Expand Down
6 changes: 3 additions & 3 deletions docs/topics/2.3-announcement.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
Expand Down Expand Up @@ -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.

Expand Down
1 change: 0 additions & 1 deletion docs/topics/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions docs/topics/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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`.
Expand Down
2 changes: 1 addition & 1 deletion docs/topics/third-party-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down
16 changes: 8 additions & 8 deletions docs/tutorial/1-serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions docs/tutorial/6-viewsets-and-routers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
Expand All @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion docs/tutorial/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
Expand Down
15 changes: 0 additions & 15 deletions requirements-test.txt

This file was deleted.

Loading