Commit 7ecd4f78 by Tom Christie

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

parents 38bde343 2230784f
...@@ -363,7 +363,7 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a ...@@ -363,7 +363,7 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a
[oauth]: http://oauth.net/2/ [oauth]: http://oauth.net/2/
[permission]: permissions.md [permission]: permissions.md
[throttling]: throttling.md [throttling]: throttling.md
[csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/csrf/#ajax [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax
[mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization
[django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html [django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html
[django-rest-framework-oauth]: http://jpadilla.github.io/django-rest-framework-oauth/ [django-rest-framework-oauth]: http://jpadilla.github.io/django-rest-framework-oauth/
......
...@@ -261,7 +261,7 @@ Corresponds to `django.db.models.fields.DecimalField`. ...@@ -261,7 +261,7 @@ Corresponds to `django.db.models.fields.DecimalField`.
**Signature**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)` **Signature**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)`
- `max_digits` The maximum number of digits allowed in the number. Note that this number must be greater than or equal to decimal_places. - `max_digits` The maximum number of digits allowed in the number. It must be either `None` or an integer greater than or equal to `decimal_places`.
- `decimal_places` The number of decimal places to store with the number. - `decimal_places` The number of decimal places to store with the number.
- `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `Decimal` objects should be returned. Defaults to the same value as the `COERCE_DECIMAL_TO_STRING` settings key, which will be `True` unless overridden. If `Decimal` objects are returned by the serializer, then the final output format will be determined by the renderer. Note that setting `localize` will force the value to `True`. - `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `Decimal` objects should be returned. Defaults to the same value as the `COERCE_DECIMAL_TO_STRING` settings key, which will be `True` unless overridden. If `Decimal` objects are returned by the serializer, then the final output format will be determined by the renderer. Note that setting `localize` will force the value to `True`.
- `max_value` Validate that the number provided is no greater than this value. - `max_value` Validate that the number provided is no greater than this value.
...@@ -665,12 +665,12 @@ The [django-rest-framework-gis][django-rest-framework-gis] package provides geog ...@@ -665,12 +665,12 @@ The [django-rest-framework-gis][django-rest-framework-gis] package provides geog
The [django-rest-framework-hstore][django-rest-framework-hstore] package provides an `HStoreField` to support [django-hstore][django-hstore] `DictionaryField` model field. The [django-rest-framework-hstore][django-rest-framework-hstore] package provides an `HStoreField` to support [django-hstore][django-hstore] `DictionaryField` model field.
[cite]: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data [cite]: https://docs.djangoproject.com/en/stable/ref/forms/api/#django.forms.Form.cleaned_data
[html-and-forms]: ../topics/html-and-forms.md [html-and-forms]: ../topics/html-and-forms.md
[FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS [FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS
[ecma262]: http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15 [ecma262]: http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
[strftime]: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior [strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior
[django-widgets]: https://docs.djangoproject.com/en/dev/ref/forms/widgets/ [django-widgets]: https://docs.djangoproject.com/en/stable/ref/forms/widgets/
[iso8601]: http://www.w3.org/TR/NOTE-datetime [iso8601]: http://www.w3.org/TR/NOTE-datetime
[drf-compound-fields]: https://drf-compound-fields.readthedocs.io [drf-compound-fields]: https://drf-compound-fields.readthedocs.io
[drf-extra-fields]: https://github.com/Hipo/drf-extra-fields [drf-extra-fields]: https://github.com/Hipo/drf-extra-fields
......
...@@ -455,14 +455,14 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter] ...@@ -455,14 +455,14 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter]
[drf-url-filter][drf-url-filter] is a simple Django app to apply filters on drf `ModelViewSet`'s `Queryset` in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package `Voluptuous` is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements. [drf-url-filter][drf-url-filter] is a simple Django app to apply filters on drf `ModelViewSet`'s `Queryset` in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package `Voluptuous` is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements.
[cite]: https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-specific-objects-with-filters [cite]: https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-specific-objects-with-filters
[django-filter]: https://github.com/alex/django-filter [django-filter]: https://github.com/alex/django-filter
[django-filter-docs]: https://django-filter.readthedocs.io/en/latest/index.html [django-filter-docs]: https://django-filter.readthedocs.io/en/latest/index.html
[guardian]: https://django-guardian.readthedocs.io/ [guardian]: https://django-guardian.readthedocs.io/
[view-permissions]: https://django-guardian.readthedocs.io/en/latest/userguide/assign.html [view-permissions]: https://django-guardian.readthedocs.io/en/latest/userguide/assign.html
[view-permissions-blogpost]: http://blog.nyaruka.com/adding-a-view-permission-to-django-models [view-permissions-blogpost]: http://blog.nyaruka.com/adding-a-view-permission-to-django-models
[nullbooleanselect]: https://github.com/django/django/blob/master/django/forms/widgets.py [nullbooleanselect]: https://github.com/django/django/blob/master/django/forms/widgets.py
[search-django-admin]: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields [search-django-admin]: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields
[django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters [django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters
[django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter [django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter
[django-url-filter]: https://github.com/miki725/django-url-filter [django-url-filter]: https://github.com/miki725/django-url-filter
......
...@@ -382,7 +382,7 @@ The [django-rest-framework-bulk package][django-rest-framework-bulk] implements ...@@ -382,7 +382,7 @@ The [django-rest-framework-bulk package][django-rest-framework-bulk] implements
[Django Rest Multiple Models][django-rest-multiple-models] provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request. [Django Rest Multiple Models][django-rest-multiple-models] provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.
[cite]: https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views [cite]: https://docs.djangoproject.com/en/stable/ref/class-based-views/#base-vs-generic-views
[GenericAPIView]: #genericapiview [GenericAPIView]: #genericapiview
[ListModelMixin]: #listmodelmixin [ListModelMixin]: #listmodelmixin
[CreateModelMixin]: #createmodelmixin [CreateModelMixin]: #createmodelmixin
......
...@@ -325,7 +325,7 @@ The [`DRF-extensions` package][drf-extensions] includes a [`PaginateByMaxMixin` ...@@ -325,7 +325,7 @@ The [`DRF-extensions` package][drf-extensions] includes a [`PaginateByMaxMixin`
The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagination` class which allows to choose pagination class with a query parameter. The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagination` class which allows to choose pagination class with a query parameter.
[cite]: https://docs.djangoproject.com/en/dev/topics/pagination/ [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/
[github-link-pagination]: https://developer.github.com/guides/traversing-with-pagination/ [github-link-pagination]: https://developer.github.com/guides/traversing-with-pagination/
[link-header]: ../img/link-header-pagination.png [link-header]: ../img/link-header-pagination.png
[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ [drf-extensions]: http://chibisov.github.io/drf-extensions/docs/
......
...@@ -224,7 +224,7 @@ Modify your REST framework settings. ...@@ -224,7 +224,7 @@ Modify your REST framework settings.
[jquery-ajax]: http://api.jquery.com/jQuery.ajax/ [jquery-ajax]: http://api.jquery.com/jQuery.ajax/
[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
[upload-handlers]: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#upload-handlers [upload-handlers]: https://docs.djangoproject.com/en/stable/topics/http/file-uploads/#upload-handlers
[rest-framework-yaml]: http://jpadilla.github.io/django-rest-framework-yaml/ [rest-framework-yaml]: http://jpadilla.github.io/django-rest-framework-yaml/
[rest-framework-xml]: http://jpadilla.github.io/django-rest-framework-xml/ [rest-framework-xml]: http://jpadilla.github.io/django-rest-framework-xml/
[yaml]: http://www.yaml.org/ [yaml]: http://www.yaml.org/
......
...@@ -164,7 +164,7 @@ As with `DjangoModelPermissions`, this permission must only be applied to views ...@@ -164,7 +164,7 @@ As with `DjangoModelPermissions`, this permission must only be applied to views
Note that `DjangoObjectPermissions` **does not** require the `django-guardian` package, and should support other object-level backends equally well. Note that `DjangoObjectPermissions` **does not** require the `django-guardian` package, and should support other object-level backends equally well.
As with `DjangoModelPermissions` you can use custom model permissions by overriding `DjangoModelPermissions` and setting the `.perms_map` property. Refer to the source code for details. As with `DjangoModelPermissions` you can use custom model permissions by overriding `DjangoObjectPermissions` and setting the `.perms_map` property. Refer to the source code for details.
--- ---
...@@ -269,8 +269,8 @@ The [Django Rest Framework Roles][django-rest-framework-roles] package makes it ...@@ -269,8 +269,8 @@ The [Django Rest Framework Roles][django-rest-framework-roles] package makes it
[authentication]: authentication.md [authentication]: authentication.md
[throttling]: throttling.md [throttling]: throttling.md
[filtering]: filtering.md [filtering]: filtering.md
[contribauth]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-permissions [contribauth]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions
[objectpermissions]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#handling-object-permissions [objectpermissions]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#handling-object-permissions
[guardian]: https://github.com/lukaszb/django-guardian [guardian]: https://github.com/lukaszb/django-guardian
[get_objects_for_user]: http://pythonhosted.org/django-guardian/api/guardian.shortcuts.html#get-objects-for-user [get_objects_for_user]: http://pythonhosted.org/django-guardian/api/guardian.shortcuts.html#get-objects-for-user
[2.2-announcement]: ../topics/2.2-announcement.md [2.2-announcement]: ../topics/2.2-announcement.md
......
...@@ -505,7 +505,7 @@ For example, given the following model for a tag, which has a generic relationsh ...@@ -505,7 +505,7 @@ For example, given the following model for a tag, which has a generic relationsh
""" """
Tags arbitrary model instances using a generic relation. Tags arbitrary model instances using a generic relation.
See: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ See: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/
""" """
tag_name = models.SlugField() tag_name = models.SlugField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
...@@ -593,9 +593,9 @@ The [drf-nested-routers package][drf-nested-routers] provides routers and relati ...@@ -593,9 +593,9 @@ The [drf-nested-routers package][drf-nested-routers] provides routers and relati
The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys. The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys.
[cite]: http://lwn.net/Articles/193245/ [cite]: http://lwn.net/Articles/193245/
[reverse-relationships]: https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward [reverse-relationships]: https://docs.djangoproject.com/en/stable/topics/db/queries/#following-relationships-backward
[routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter [routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter
[generic-relations]: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1 [generic-relations]: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#id1
[2.2-announcement]: ../topics/2.2-announcement.md [2.2-announcement]: ../topics/2.2-announcement.md
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
[drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations [drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations
...@@ -123,6 +123,8 @@ You can use `TemplateHTMLRenderer` either to return regular HTML pages using RES ...@@ -123,6 +123,8 @@ You can use `TemplateHTMLRenderer` either to return regular HTML pages using RES
If you're building websites that use `TemplateHTMLRenderer` along with other renderer classes, you should consider listing `TemplateHTMLRenderer` as the first class in the `renderer_classes` list, so that it will be prioritised first even for browsers that send poorly formed `ACCEPT:` headers. If you're building websites that use `TemplateHTMLRenderer` along with other renderer classes, you should consider listing `TemplateHTMLRenderer` as the first class in the `renderer_classes` list, so that it will be prioritised first even for browsers that send poorly formed `ACCEPT:` headers.
See the [_HTML & Forms_ Topic Page][html-and-forms] for further examples of `TemplateHTMLRenderer` usage.
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.html'` **.format**: `'.html'`
...@@ -476,7 +478,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily ...@@ -476,7 +478,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily
[Rest Framework Latex] provides a renderer that outputs PDFs using Laulatex. It is maintained by [Pebble (S/F Software)][mypebble]. [Rest Framework Latex] provides a renderer that outputs PDFs using Laulatex. It is maintained by [Pebble (S/F Software)][mypebble].
[cite]: https://docs.djangoproject.com/en/dev/ref/template-response/#the-rendering-process [cite]: https://docs.djangoproject.com/en/stable/stable/template-response/#the-rendering-process
[conneg]: content-negotiation.md [conneg]: content-negotiation.md
[html-and-forms]: ../topics/html-and-forms.md [html-and-forms]: ../topics/html-and-forms.md
[browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers [browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers
...@@ -485,7 +487,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily ...@@ -485,7 +487,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily
[quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven [quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
[application/vnd.github+json]: http://developer.github.com/v3/media/ [application/vnd.github+json]: http://developer.github.com/v3/media/
[application/vnd.collection+json]: http://www.amundsen.com/media-types/collection/ [application/vnd.collection+json]: http://www.amundsen.com/media-types/collection/
[django-error-views]: https://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views [django-error-views]: https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views
[rest-framework-jsonp]: http://jpadilla.github.io/django-rest-framework-jsonp/ [rest-framework-jsonp]: http://jpadilla.github.io/django-rest-framework-jsonp/
[cors]: http://www.w3.org/TR/cors/ [cors]: http://www.w3.org/TR/cors/
[cors-docs]: http://www.django-rest-framework.org/topics/ajax-csrf-cors/ [cors-docs]: http://www.django-rest-framework.org/topics/ajax-csrf-cors/
......
...@@ -91,5 +91,5 @@ As with any other `TemplateResponse`, this method is called to render the serial ...@@ -91,5 +91,5 @@ As with any other `TemplateResponse`, this method is called to render the serial
You won't typically need to call `.render()` yourself, as it's handled by Django's standard response cycle. You won't typically need to call `.render()` yourself, as it's handled by Django's standard response cycle.
[cite]: https://docs.djangoproject.com/en/dev/ref/template-response/ [cite]: https://docs.djangoproject.com/en/stable/stable/template-response/
[statuscodes]: status-codes.md [statuscodes]: status-codes.md
...@@ -51,5 +51,5 @@ As with the `reverse` function, you should **include the request as a keyword ar ...@@ -51,5 +51,5 @@ As with the `reverse` function, you should **include the request as a keyword ar
api_root = reverse_lazy('api-root', request=request) api_root = reverse_lazy('api-root', request=request)
[cite]: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5 [cite]: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5
[reverse]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse [reverse]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse
[reverse-lazy]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy [reverse-lazy]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy
...@@ -541,5 +541,5 @@ A short description of the meaning and intended usage of the input field. ...@@ -541,5 +541,5 @@ A short description of the meaning and intended usage of the input field.
[open-api]: https://openapis.org/ [open-api]: https://openapis.org/
[json-hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html [json-hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html
[api-blueprint]: https://apiblueprint.org/ [api-blueprint]: https://apiblueprint.org/
[static-files]: https://docs.djangoproject.com/en/dev/howto/static-files/ [static-files]: https://docs.djangoproject.com/en/stable/howto/static-files/
[named-arguments]: https://docs.djangoproject.com/en/dev/topics/http/urls/#named-groups [named-arguments]: https://docs.djangoproject.com/en/stable/topics/http/urls/#named-groups
...@@ -1118,7 +1118,7 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali ...@@ -1118,7 +1118,7 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali
[cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion
[relations]: relations.md [relations]: relations.md
[model-managers]: https://docs.djangoproject.com/en/dev/topics/db/managers/ [model-managers]: https://docs.djangoproject.com/en/stable/topics/db/managers/
[encapsulation-blogpost]: http://www.dabapps.com/blog/django-models-and-encapsulation/ [encapsulation-blogpost]: http://www.dabapps.com/blog/django-models-and-encapsulation/
[django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/ [django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/
[marshmallow]: https://marshmallow.readthedocs.io/en/latest/ [marshmallow]: https://marshmallow.readthedocs.io/en/latest/
......
...@@ -456,7 +456,7 @@ An integer of 0 or more, that may be used to specify the number of application p ...@@ -456,7 +456,7 @@ An integer of 0 or more, that may be used to specify the number of application p
Default: `None` Default: `None`
[cite]: http://www.python.org/dev/peps/pep-0020/ [cite]: https://www.python.org/dev/peps/pep-0020/
[rfc4627]: http://www.ietf.org/rfc/rfc4627.txt [rfc4627]: http://www.ietf.org/rfc/rfc4627.txt
[heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses [heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses
[strftime]: http://docs.python.org/2/library/time.html#time.strftime [strftime]: https://docs.python.org/3/library/time.html#time.strftime
...@@ -373,6 +373,6 @@ For example, to add support for using `format='html'` in test requests, you migh ...@@ -373,6 +373,6 @@ For example, to add support for using `format='html'` in test requests, you migh
} }
[cite]: http://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper [cite]: http://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper
[client]: https://docs.djangoproject.com/en/dev/topics/testing/tools/#the-test-client [client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client
[requestfactory]: https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.client.RequestFactory [requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory
[configuration]: #configuration [configuration]: #configuration
...@@ -193,5 +193,5 @@ The following is an example of a rate throttle, that will randomly throttle 1 in ...@@ -193,5 +193,5 @@ The following is an example of a rate throttle, that will randomly throttle 1 in
[cite]: https://dev.twitter.com/docs/error-codes-responses [cite]: https://dev.twitter.com/docs/error-codes-responses
[permissions]: permissions.md [permissions]: permissions.md
[identifing-clients]: http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster [identifing-clients]: http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster
[cache-setting]: https://docs.djangoproject.com/en/dev/ref/settings/#caches [cache-setting]: https://docs.djangoproject.com/en/stable/ref/settings/#caches
[cache-docs]: https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache [cache-docs]: https://docs.djangoproject.com/en/stable/topics/cache/#setting-up-the-cache
...@@ -300,4 +300,4 @@ In some advanced cases you might want a validator to be passed the serializer fi ...@@ -300,4 +300,4 @@ In some advanced cases you might want a validator to be passed the serializer fi
# In `__call__` we can then use that information to modify the validation behavior. # In `__call__` we can then use that information to modify the validation behavior.
self.is_update = serializer_field.parent.instance is not None self.is_update = serializer_field.parent.instance is not None
[cite]: https://docs.djangoproject.com/en/dev/ref/validators/ [cite]: https://docs.djangoproject.com/en/stable/ref/validators/
...@@ -147,10 +147,10 @@ When using a serializer with a `HyperlinkedRelatedField` or `HyperlinkedIdentity ...@@ -147,10 +147,10 @@ When using a serializer with a `HyperlinkedRelatedField` or `HyperlinkedIdentity
From version 2.2 onwards, serializers with hyperlinked relationships *always* require a `'request'` key to be supplied in the context dictionary. The implicit behavior will continue to function, but its use will raise a `PendingDeprecationWarning`. From version 2.2 onwards, serializers with hyperlinked relationships *always* require a `'request'` key to be supplied in the context dictionary. The implicit behavior will continue to function, but its use will raise a `PendingDeprecationWarning`.
[xordoquy]: https://github.com/xordoquy [xordoquy]: https://github.com/xordoquy
[django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 [django-python-3]: https://docs.djangoproject.com/en/stable/faq/install/#can-i-use-django-with-python-3
[porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ [porting-python-3]: https://docs.djangoproject.com/en/stable/topics/python3/
[python-compat]: https://docs.djangoproject.com/en/dev/releases/1.5/#python-compatibility [python-compat]: https://docs.djangoproject.com/en/stable/releases/1.5/#python-compatibility
[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy [django-deprecation-policy]: https://docs.djangoproject.com/en/stable/internals/release-process/#internal-release-deprecation-policy
[credits]: http://www.django-rest-framework.org/topics/credits [credits]: http://www.django-rest-framework.org/topics/credits
[mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
[django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs [django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs
......
...@@ -162,7 +162,7 @@ The next planned release will be 3.0, featuring an improved and simplified seria ...@@ -162,7 +162,7 @@ The next planned release will be 3.0, featuring an improved and simplified seria
Once again, many thanks to all the generous [backers and sponsors][kickstarter-sponsors] who've helped make this possible! Once again, many thanks to all the generous [backers and sponsors][kickstarter-sponsors] who've helped make this possible!
[lts-releases]: https://docs.djangoproject.com/en/dev/internals/release-process/#long-term-support-lts-releases [lts-releases]: https://docs.djangoproject.com/en/stable/internals/release-process/#long-term-support-lts-releases
[2-4-release-notes]: release-notes#240 [2-4-release-notes]: release-notes#240
[view-name-and-description-settings]: ../api-guide/settings#view-names-and-descriptions [view-name-and-description-settings]: ../api-guide/settings#view-names-and-descriptions
[client-ip-identification]: ../api-guide/throttling#how-clients-are-identified [client-ip-identification]: ../api-guide/throttling#how-clients-are-identified
......
...@@ -870,7 +870,7 @@ The `COMPACT_JSON` setting has been added, and can be used to revert this behavi ...@@ -870,7 +870,7 @@ The `COMPACT_JSON` setting has been added, and can be used to revert this behavi
#### File fields as URLs #### File fields as URLs
The `FileField` and `ImageField` classes are now represented as URLs by default. You should ensure you set Django's [standard `MEDIA_URL` setting](https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-MEDIA_URL) appropriately, and ensure your application [serves the uploaded files](https://docs.djangoproject.com/en/dev/howto/static-files/#serving-uploaded-files-in-development). The `FileField` and `ImageField` classes are now represented as URLs by default. You should ensure you set Django's [standard `MEDIA_URL` setting](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-MEDIA_URL) appropriately, and ensure your application [serves the uploaded files](https://docs.djangoproject.com/en/stable/howto/static-files/#serving-uploaded-files-in-development).
You can revert this behavior, and display filenames in the representation by using the `UPLOADED_FILES_USE_URL` settings key: You can revert this behavior, and display filenames in the representation by using the `UPLOADED_FILES_USE_URL` settings key:
...@@ -962,4 +962,4 @@ You can follow development on the GitHub site, where we use [milestones to indic ...@@ -962,4 +962,4 @@ You can follow development on the GitHub site, where we use [milestones to indic
[kickstarter]: http://kickstarter.com/projects/tomchristie/django-rest-framework-3 [kickstarter]: http://kickstarter.com/projects/tomchristie/django-rest-framework-3
[sponsors]: http://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors [sponsors]: http://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors
[mixins.py]: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py [mixins.py]: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py
[django-localization]: https://docs.djangoproject.com/en/dev/topics/i18n/translation/#localization-how-to-create-language-files [django-localization]: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#localization-how-to-create-language-files
...@@ -35,7 +35,7 @@ The best way to deal with CORS in REST framework is to add the required response ...@@ -35,7 +35,7 @@ The best way to deal with CORS in REST framework is to add the required response
[cite]: http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html [cite]: http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html
[csrf]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) [csrf]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
[csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/csrf/#ajax [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax
[cors]: http://www.w3.org/TR/cors/ [cors]: http://www.w3.org/TR/cors/
[ottoyiu]: https://github.com/ottoyiu/ [ottoyiu]: https://github.com/ottoyiu/
[django-cors-headers]: https://github.com/ottoyiu/django-cors-headers/ [django-cors-headers]: https://github.com/ottoyiu/django-cors-headers/
...@@ -598,7 +598,7 @@ For older release notes, [please see the version 2.x documentation][old-release- ...@@ -598,7 +598,7 @@ For older release notes, [please see the version 2.x documentation][old-release-
[cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html
[deprecation-policy]: #deprecation-policy [deprecation-policy]: #deprecation-policy
[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy [django-deprecation-policy]: https://docs.djangoproject.com/en/stable/internals/release-process/#internal-release-deprecation-policy
[defusedxml-announce]: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html [defusedxml-announce]: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html
[743]: https://github.com/tomchristie/django-rest-framework/pull/743 [743]: https://github.com/tomchristie/django-rest-framework/pull/743
[staticfiles14]: https://docs.djangoproject.com/en/1.4/howto/static-files/#with-a-template-tag [staticfiles14]: https://docs.djangoproject.com/en/1.4/howto/static-files/#with-a-template-tag
......
...@@ -118,7 +118,9 @@ We'd also like to set a few global settings. We'd like to turn on pagination, a ...@@ -118,7 +118,9 @@ We'd also like to set a few global settings. We'd like to turn on pagination, a
) )
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',), 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser',
],
'PAGE_SIZE': 10 'PAGE_SIZE': 10
} }
......
...@@ -26,16 +26,19 @@ class DropdownWithAuthTests(TestCase): ...@@ -26,16 +26,19 @@ class DropdownWithAuthTests(TestCase):
def test_name_shown_when_logged_in(self): def test_name_shown_when_logged_in(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
response = self.client.get('/') response = self.client.get('/')
self.assertContains(response, 'john') content = response.content.decode('utf8')
assert 'john' in content
def test_logout_shown_when_logged_in(self): def test_logout_shown_when_logged_in(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
response = self.client.get('/') response = self.client.get('/')
self.assertContains(response, '>Log out<') content = response.content.decode('utf8')
assert '>Log out<' in content
def test_login_shown_when_logged_out(self): def test_login_shown_when_logged_out(self):
response = self.client.get('/') response = self.client.get('/')
self.assertContains(response, '>Log in<') content = response.content.decode('utf8')
assert '>Log in<' in content
@override_settings(ROOT_URLCONF='tests.browsable_api.no_auth_urls') @override_settings(ROOT_URLCONF='tests.browsable_api.no_auth_urls')
...@@ -58,13 +61,16 @@ class NoDropdownWithoutAuthTests(TestCase): ...@@ -58,13 +61,16 @@ class NoDropdownWithoutAuthTests(TestCase):
def test_name_shown_when_logged_in(self): def test_name_shown_when_logged_in(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
response = self.client.get('/') response = self.client.get('/')
self.assertContains(response, 'john') content = response.content.decode('utf8')
assert 'john' in content
def test_dropdown_not_shown_when_logged_in(self): def test_dropdown_not_shown_when_logged_in(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
response = self.client.get('/') response = self.client.get('/')
self.assertNotContains(response, '<li class="dropdown">') content = response.content.decode('utf8')
assert '<li class="dropdown">' not in content
def test_dropdown_not_shown_when_logged_out(self): def test_dropdown_not_shown_when_logged_out(self):
response = self.client.get('/') response = self.client.get('/')
self.assertNotContains(response, '<li class="dropdown">') content = response.content.decode('utf8')
assert '<li class="dropdown">' not in content
...@@ -35,8 +35,8 @@ class DropdownWithAuthTests(TestCase): ...@@ -35,8 +35,8 @@ class DropdownWithAuthTests(TestCase):
@override_settings(ROOT_URLCONF='tests.browsable_api.test_browsable_nested_api') @override_settings(ROOT_URLCONF='tests.browsable_api.test_browsable_nested_api')
def test_login(self): def test_login(self):
response = self.client.get('/api/') response = self.client.get('/api/')
self.assertEqual(200, response.status_code) assert 200 == response.status_code
content = response.content.decode('utf-8') content = response.content.decode('utf-8')
self.assertIn('form action="/api/"', content) assert 'form action="/api/"' in content
self.assertIn('input name="nested.one"', content) assert 'input name="nested.one"' in content
self.assertIn('input name="nested.two"', content) assert 'input name="nested.two"' in content
...@@ -50,5 +50,5 @@ class TestManyPostView(TestCase): ...@@ -50,5 +50,5 @@ class TestManyPostView(TestCase):
request = factory.post('/', data, format='json') request = factory.post('/', data, format='json')
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(len(response.data), 3) assert len(response.data) == 3
...@@ -67,8 +67,8 @@ class DBTransactionTests(TestCase): ...@@ -67,8 +67,8 @@ class DBTransactionTests(TestCase):
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request) response = self.view(request)
self.assertFalse(transaction.get_rollback()) assert not transaction.get_rollback()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
assert BasicModel.objects.count() == 1 assert BasicModel.objects.count() == 1
...@@ -98,7 +98,7 @@ class DBTransactionErrorTests(TestCase): ...@@ -98,7 +98,7 @@ class DBTransactionErrorTests(TestCase):
# 3 - release savepoint # 3 - release savepoint
with transaction.atomic(): with transaction.atomic():
self.assertRaises(Exception, self.view, request) self.assertRaises(Exception, self.view, request)
self.assertFalse(transaction.get_rollback()) assert not transaction.get_rollback()
assert BasicModel.objects.count() == 1 assert BasicModel.objects.count() == 1
...@@ -128,9 +128,8 @@ class DBTransactionAPIExceptionTests(TestCase): ...@@ -128,9 +128,8 @@ class DBTransactionAPIExceptionTests(TestCase):
# 4 - release savepoint (django>=1.8 only) # 4 - release savepoint (django>=1.8 only)
with transaction.atomic(): with transaction.atomic():
response = self.view(request) response = self.view(request)
self.assertTrue(transaction.get_rollback()) assert transaction.get_rollback()
self.assertEqual(response.status_code, assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
status.HTTP_500_INTERNAL_SERVER_ERROR)
assert BasicModel.objects.count() == 0 assert BasicModel.objects.count() == 0
...@@ -151,5 +150,4 @@ class NonAtomicDBTransactionAPIExceptionTests(TransactionTestCase): ...@@ -151,5 +150,4 @@ class NonAtomicDBTransactionAPIExceptionTests(TransactionTestCase):
# without checking connection.in_atomic_block view raises 500 # without checking connection.in_atomic_block view raises 500
# due attempt to rollback without transaction # due attempt to rollback without transaction
self.assertEqual(response.status_code, assert response.status_code == status.HTTP_404_NOT_FOUND
status.HTTP_404_NOT_FOUND)
...@@ -56,11 +56,11 @@ class DecoratorTestCase(TestCase): ...@@ -56,11 +56,11 @@ class DecoratorTestCase(TestCase):
request = self.factory.get('/') request = self.factory.get('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
request = self.factory.post('/') request = self.factory.post('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
def test_calling_put_method(self): def test_calling_put_method(self):
...@@ -70,11 +70,11 @@ class DecoratorTestCase(TestCase): ...@@ -70,11 +70,11 @@ class DecoratorTestCase(TestCase):
request = self.factory.put('/') request = self.factory.put('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
request = self.factory.post('/') request = self.factory.post('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
def test_calling_patch_method(self): def test_calling_patch_method(self):
...@@ -84,11 +84,11 @@ class DecoratorTestCase(TestCase): ...@@ -84,11 +84,11 @@ class DecoratorTestCase(TestCase):
request = self.factory.patch('/') request = self.factory.patch('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
request = self.factory.post('/') request = self.factory.post('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
def test_renderer_classes(self): def test_renderer_classes(self):
...@@ -99,16 +99,15 @@ class DecoratorTestCase(TestCase): ...@@ -99,16 +99,15 @@ class DecoratorTestCase(TestCase):
request = self.factory.get('/') request = self.factory.get('/')
response = view(request) response = view(request)
self.assertTrue(isinstance(response.accepted_renderer, JSONRenderer)) assert isinstance(response.accepted_renderer, JSONRenderer)
def test_parser_classes(self): def test_parser_classes(self):
@api_view(['GET']) @api_view(['GET'])
@parser_classes([JSONParser]) @parser_classes([JSONParser])
def view(request): def view(request):
self.assertEqual(len(request.parsers), 1) assert len(request.parsers) == 1
self.assertTrue(isinstance(request.parsers[0], assert isinstance(request.parsers[0], JSONParser)
JSONParser))
return Response({}) return Response({})
request = self.factory.get('/') request = self.factory.get('/')
...@@ -119,9 +118,8 @@ class DecoratorTestCase(TestCase): ...@@ -119,9 +118,8 @@ class DecoratorTestCase(TestCase):
@api_view(['GET']) @api_view(['GET'])
@authentication_classes([BasicAuthentication]) @authentication_classes([BasicAuthentication])
def view(request): def view(request):
self.assertEqual(len(request.authenticators), 1) assert len(request.authenticators) == 1
self.assertTrue(isinstance(request.authenticators[0], assert isinstance(request.authenticators[0], BasicAuthentication)
BasicAuthentication))
return Response({}) return Response({})
request = self.factory.get('/') request = self.factory.get('/')
...@@ -136,7 +134,7 @@ class DecoratorTestCase(TestCase): ...@@ -136,7 +134,7 @@ class DecoratorTestCase(TestCase):
request = self.factory.get('/') request = self.factory.get('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_throttle_classes(self): def test_throttle_classes(self):
class OncePerDayUserThrottle(UserRateThrottle): class OncePerDayUserThrottle(UserRateThrottle):
...@@ -149,7 +147,7 @@ class DecoratorTestCase(TestCase): ...@@ -149,7 +147,7 @@ class DecoratorTestCase(TestCase):
request = self.factory.get('/') request = self.factory.get('/')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_429_TOO_MANY_REQUESTS) assert response.status_code == status.HTTP_429_TOO_MANY_REQUESTS
...@@ -60,7 +60,7 @@ class TestViewNamesAndDescriptions(TestCase): ...@@ -60,7 +60,7 @@ class TestViewNamesAndDescriptions(TestCase):
""" """
class MockView(APIView): class MockView(APIView):
pass pass
self.assertEqual(MockView().get_view_name(), 'Mock') assert MockView().get_view_name() == 'Mock'
def test_view_description_uses_docstring(self): def test_view_description_uses_docstring(self):
"""Ensure view descriptions are based on the docstring.""" """Ensure view descriptions are based on the docstring."""
...@@ -80,7 +80,7 @@ class TestViewNamesAndDescriptions(TestCase): ...@@ -80,7 +80,7 @@ class TestViewNamesAndDescriptions(TestCase):
# hash style header #""" # hash style header #"""
self.assertEqual(MockView().get_view_description(), DESCRIPTION) assert MockView().get_view_description() == DESCRIPTION
def test_view_description_can_be_empty(self): def test_view_description_can_be_empty(self):
""" """
...@@ -89,7 +89,7 @@ class TestViewNamesAndDescriptions(TestCase): ...@@ -89,7 +89,7 @@ class TestViewNamesAndDescriptions(TestCase):
""" """
class MockView(APIView): class MockView(APIView):
pass pass
self.assertEqual(MockView().get_view_description(), '') assert MockView().get_view_description() == ''
def test_view_description_can_be_promise(self): def test_view_description_can_be_promise(self):
""" """
...@@ -111,7 +111,7 @@ class TestViewNamesAndDescriptions(TestCase): ...@@ -111,7 +111,7 @@ class TestViewNamesAndDescriptions(TestCase):
class MockView(APIView): class MockView(APIView):
__doc__ = MockLazyStr("a gettext string") __doc__ = MockLazyStr("a gettext string")
self.assertEqual(MockView().get_view_description(), 'a gettext string') assert MockView().get_view_description() == 'a gettext string'
def test_markdown(self): def test_markdown(self):
""" """
...@@ -120,7 +120,7 @@ class TestViewNamesAndDescriptions(TestCase): ...@@ -120,7 +120,7 @@ class TestViewNamesAndDescriptions(TestCase):
if apply_markdown: if apply_markdown:
gte_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_gte_21 gte_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_gte_21
lt_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_lt_21 lt_21_match = apply_markdown(DESCRIPTION) == MARKED_DOWN_lt_21
self.assertTrue(gte_21_match or lt_21_match) assert gte_21_match or lt_21_match
def test_dedent_tabs(): def test_dedent_tabs():
......
...@@ -20,21 +20,21 @@ class JSONEncoderTests(TestCase): ...@@ -20,21 +20,21 @@ class JSONEncoderTests(TestCase):
Tests encoding a decimal Tests encoding a decimal
""" """
d = Decimal(3.14) d = Decimal(3.14)
self.assertEqual(d, float(d)) assert d == float(d)
def test_encode_datetime(self): def test_encode_datetime(self):
""" """
Tests encoding a datetime object Tests encoding a datetime object
""" """
current_time = datetime.now() current_time = datetime.now()
self.assertEqual(self.encoder.default(current_time), current_time.isoformat()) assert self.encoder.default(current_time) == current_time.isoformat()
def test_encode_time(self): def test_encode_time(self):
""" """
Tests encoding a timezone Tests encoding a timezone
""" """
current_time = datetime.now().time() current_time = datetime.now().time()
self.assertEqual(self.encoder.default(current_time), current_time.isoformat()[:12]) assert self.encoder.default(current_time) == current_time.isoformat()[:12]
def test_encode_time_tz(self): def test_encode_time_tz(self):
""" """
...@@ -64,18 +64,18 @@ class JSONEncoderTests(TestCase): ...@@ -64,18 +64,18 @@ class JSONEncoderTests(TestCase):
Tests encoding a date object Tests encoding a date object
""" """
current_date = date.today() current_date = date.today()
self.assertEqual(self.encoder.default(current_date), current_date.isoformat()) assert self.encoder.default(current_date) == current_date.isoformat()
def test_encode_timedelta(self): def test_encode_timedelta(self):
""" """
Tests encoding a timedelta object Tests encoding a timedelta object
""" """
delta = timedelta(hours=1) delta = timedelta(hours=1)
self.assertEqual(self.encoder.default(delta), str(delta.total_seconds())) assert self.encoder.default(delta) == str(delta.total_seconds())
def test_encode_uuid(self): def test_encode_uuid(self):
""" """
Tests encoding a UUID object Tests encoding a UUID object
""" """
unique_id = uuid4() unique_id = uuid4()
self.assertEqual(self.encoder.default(unique_id), str(unique_id)) assert self.encoder.default(unique_id) == str(unique_id)
...@@ -16,28 +16,22 @@ class ExceptionTestCase(TestCase): ...@@ -16,28 +16,22 @@ class ExceptionTestCase(TestCase):
example = "string" example = "string"
lazy_example = _(example) lazy_example = _(example)
self.assertEqual( assert _get_error_details(lazy_example) == example
_get_error_details(lazy_example),
example
)
assert isinstance( assert isinstance(
_get_error_details(lazy_example), _get_error_details(lazy_example),
ErrorDetail ErrorDetail
) )
self.assertEqual( assert _get_error_details({'nested': lazy_example})['nested'] == example
_get_error_details({'nested': lazy_example})['nested'],
example
)
assert isinstance( assert isinstance(
_get_error_details({'nested': lazy_example})['nested'], _get_error_details({'nested': lazy_example})['nested'],
ErrorDetail ErrorDetail
) )
self.assertEqual( assert _get_error_details([[lazy_example]])[0][0] == example
_get_error_details([[lazy_example]])[0][0],
example
)
assert isinstance( assert isinstance(
_get_error_details([[lazy_example]])[0][0], _get_error_details([[lazy_example]])[0][0],
ErrorDetail ErrorDetail
......
...@@ -1014,16 +1014,16 @@ class TestLocalizedDecimalField(TestCase): ...@@ -1014,16 +1014,16 @@ class TestLocalizedDecimalField(TestCase):
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl') @override_settings(USE_L10N=True, LANGUAGE_CODE='pl')
def test_to_internal_value(self): def test_to_internal_value(self):
field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True) field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_internal_value('1,1'), Decimal('1.1')) assert field.to_internal_value('1,1') == Decimal('1.1')
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl') @override_settings(USE_L10N=True, LANGUAGE_CODE='pl')
def test_to_representation(self): def test_to_representation(self):
field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True) field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_representation(Decimal('1.1')), '1,1') assert field.to_representation(Decimal('1.1')) == '1,1'
def test_localize_forces_coerce_to_string(self): def test_localize_forces_coerce_to_string(self):
field = serializers.DecimalField(max_digits=2, decimal_places=1, coerce_to_string=False, localize=True) field = serializers.DecimalField(max_digits=2, decimal_places=1, coerce_to_string=False, localize=True)
self.assertTrue(isinstance(field.to_representation(Decimal('1.1')), six.string_types)) assert isinstance(field.to_representation(Decimal('1.1')), six.string_types)
class TestQuantizedValueForDecimal(TestCase): class TestQuantizedValueForDecimal(TestCase):
...@@ -1031,19 +1031,19 @@ class TestQuantizedValueForDecimal(TestCase): ...@@ -1031,19 +1031,19 @@ class TestQuantizedValueForDecimal(TestCase):
field = serializers.DecimalField(max_digits=4, decimal_places=2) field = serializers.DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value(12).as_tuple() value = field.to_internal_value(12).as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2) expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple) assert value == expected_digit_tuple
def test_string_quantized_value_for_decimal(self): def test_string_quantized_value_for_decimal(self):
field = serializers.DecimalField(max_digits=4, decimal_places=2) field = serializers.DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value('12').as_tuple() value = field.to_internal_value('12').as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2) expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple) assert value == expected_digit_tuple
def test_part_precision_string_quantized_value_for_decimal(self): def test_part_precision_string_quantized_value_for_decimal(self):
field = serializers.DecimalField(max_digits=4, decimal_places=2) field = serializers.DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value('12.0').as_tuple() value = field.to_internal_value('12.0').as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2) expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple) assert value == expected_digit_tuple
class TestNoDecimalPlaces(FieldValues): class TestNoDecimalPlaces(FieldValues):
......
...@@ -94,7 +94,7 @@ class Issue3674ParentModel(models.Model): ...@@ -94,7 +94,7 @@ class Issue3674ParentModel(models.Model):
class Issue3674ChildModel(models.Model): class Issue3674ChildModel(models.Model):
parent = models.ForeignKey(Issue3674ParentModel, related_name='children') parent = models.ForeignKey(Issue3674ParentModel, related_name='children', on_delete=models.CASCADE)
value = models.CharField(primary_key=True, max_length=64) value = models.CharField(primary_key=True, max_length=64)
...@@ -1013,7 +1013,7 @@ class Issue3674Test(TestCase): ...@@ -1013,7 +1013,7 @@ class Issue3674Test(TestCase):
title = models.CharField(max_length=64) title = models.CharField(max_length=64)
class TestChildModel(models.Model): class TestChildModel(models.Model):
parent = models.ForeignKey(TestParentModel, related_name='children') parent = models.ForeignKey(TestParentModel, related_name='children', on_delete=models.CASCADE)
value = models.CharField(primary_key=True, max_length=64) value = models.CharField(primary_key=True, max_length=64)
class TestChildModelSerializer(serializers.ModelSerializer): class TestChildModelSerializer(serializers.ModelSerializer):
......
...@@ -2,6 +2,7 @@ from django.contrib.auth.models import Group, User ...@@ -2,6 +2,7 @@ from django.contrib.auth.models import Group, User
from django.test import TestCase from django.test import TestCase
from rest_framework import generics, serializers from rest_framework import generics, serializers
from rest_framework.compat import set_many
from rest_framework.test import APIRequestFactory from rest_framework.test import APIRequestFactory
factory = APIRequestFactory() factory = APIRequestFactory()
...@@ -22,7 +23,7 @@ class TestPrefetchRelatedUpdates(TestCase): ...@@ -22,7 +23,7 @@ class TestPrefetchRelatedUpdates(TestCase):
def setUp(self): def setUp(self):
self.user = User.objects.create(username='tom', email='tom@example.com') self.user = User.objects.create(username='tom', email='tom@example.com')
self.groups = [Group.objects.create(name='a'), Group.objects.create(name='b')] self.groups = [Group.objects.create(name='a'), Group.objects.create(name='b')]
self.user.groups = self.groups set_many(self.user, 'groups', self.groups)
self.user.save() self.user.save()
def test_prefetch_related_updates(self): def test_prefetch_related_updates(self):
......
...@@ -75,7 +75,7 @@ class TestGenericRelations(TestCase): ...@@ -75,7 +75,7 @@ class TestGenericRelations(TestCase):
'tags': ['django', 'python'], 'tags': ['django', 'python'],
'url': 'https://www.djangoproject.com/' 'url': 'https://www.djangoproject.com/'
} }
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_generic_fk(self): def test_generic_fk(self):
""" """
...@@ -105,4 +105,4 @@ class TestGenericRelations(TestCase): ...@@ -105,4 +105,4 @@ class TestGenericRelations(TestCase):
'tagged_item': 'Note: Remember the milk' 'tagged_item': 'Note: Remember the milk'
} }
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
...@@ -60,11 +60,11 @@ class TestNestedValidationError(TestCase): ...@@ -60,11 +60,11 @@ class TestNestedValidationError(TestCase):
} }
}) })
self.assertEqual(serializers.as_serializer_error(e), { assert serializers.as_serializer_error(e) == {
'nested': { 'nested': {
'field': ['error'], 'field': ['error'],
} }
}) }
class TestPreSaveValidationExclusionsSerializer(TestCase): class TestPreSaveValidationExclusionsSerializer(TestCase):
...@@ -75,20 +75,20 @@ class TestPreSaveValidationExclusionsSerializer(TestCase): ...@@ -75,20 +75,20 @@ class TestPreSaveValidationExclusionsSerializer(TestCase):
# We've set `required=False` on the serializer, but the model # We've set `required=False` on the serializer, but the model
# does not have `blank=True`, so this serializer should not validate. # does not have `blank=True`, so this serializer should not validate.
serializer = ShouldValidateModelSerializer(data={'renamed': ''}) serializer = ShouldValidateModelSerializer(data={'renamed': ''})
self.assertEqual(serializer.is_valid(), False) assert serializer.is_valid() is False
self.assertIn('renamed', serializer.errors) assert 'renamed' in serializer.errors
self.assertNotIn('should_validate_field', serializer.errors) assert 'should_validate_field' not in serializer.errors
class TestCustomValidationMethods(TestCase): class TestCustomValidationMethods(TestCase):
def test_custom_validation_method_is_executed(self): def test_custom_validation_method_is_executed(self):
serializer = ShouldValidateModelSerializer(data={'renamed': 'fo'}) serializer = ShouldValidateModelSerializer(data={'renamed': 'fo'})
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertIn('renamed', serializer.errors) assert 'renamed' in serializer.errors
def test_custom_validation_method_passing(self): def test_custom_validation_method_passing(self):
serializer = ShouldValidateModelSerializer(data={'renamed': 'foo'}) serializer = ShouldValidateModelSerializer(data={'renamed': 'foo'})
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
class ValidationSerializer(serializers.Serializer): class ValidationSerializer(serializers.Serializer):
...@@ -108,12 +108,12 @@ class TestAvoidValidation(TestCase): ...@@ -108,12 +108,12 @@ class TestAvoidValidation(TestCase):
""" """
def test_serializer_errors_has_only_invalid_data_error(self): def test_serializer_errors_has_only_invalid_data_error(self):
serializer = ValidationSerializer(data='invalid data') serializer = ValidationSerializer(data='invalid data')
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertDictEqual(serializer.errors, { assert serializer.errors == {
'non_field_errors': [ 'non_field_errors': [
'Invalid data. Expected a dictionary, but got %s.' % type('').__name__ 'Invalid data. Expected a dictionary, but got %s.' % type('').__name__
] ]
}) }
# regression tests for issue: 1493 # regression tests for issue: 1493
...@@ -137,27 +137,31 @@ class TestMaxValueValidatorValidation(TestCase): ...@@ -137,27 +137,31 @@ class TestMaxValueValidatorValidation(TestCase):
def test_max_value_validation_serializer_success(self): def test_max_value_validation_serializer_success(self):
serializer = ValidationMaxValueValidatorModelSerializer(data={'number_value': 99}) serializer = ValidationMaxValueValidatorModelSerializer(data={'number_value': 99})
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
def test_max_value_validation_serializer_fails(self): def test_max_value_validation_serializer_fails(self):
serializer = ValidationMaxValueValidatorModelSerializer(data={'number_value': 101}) serializer = ValidationMaxValueValidatorModelSerializer(data={'number_value': 101})
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertDictEqual({'number_value': ['Ensure this value is less than or equal to 100.']}, serializer.errors) assert serializer.errors == {
'number_value': [
'Ensure this value is less than or equal to 100.'
]
}
def test_max_value_validation_success(self): def test_max_value_validation_success(self):
obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) obj = ValidationMaxValueValidatorModel.objects.create(number_value=100)
request = factory.patch('/{0}'.format(obj.pk), {'number_value': 98}, format='json') request = factory.patch('/{0}'.format(obj.pk), {'number_value': 98}, format='json')
view = UpdateMaxValueValidationModel().as_view() view = UpdateMaxValueValidationModel().as_view()
response = view(request, pk=obj.pk).render() response = view(request, pk=obj.pk).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_max_value_validation_fail(self): def test_max_value_validation_fail(self):
obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) obj = ValidationMaxValueValidatorModel.objects.create(number_value=100)
request = factory.patch('/{0}'.format(obj.pk), {'number_value': 101}, format='json') request = factory.patch('/{0}'.format(obj.pk), {'number_value': 101}, format='json')
view = UpdateMaxValueValidationModel().as_view() view = UpdateMaxValueValidationModel().as_view()
response = view(request, pk=obj.pk).render() response = view(request, pk=obj.pk).render()
self.assertEqual(response.content, b'{"number_value":["Ensure this value is less than or equal to 100."]}') assert response.content == b'{"number_value":["Ensure this value is less than or equal to 100."]}'
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) assert response.status_code == status.HTTP_400_BAD_REQUEST
# regression tests for issue: 1533 # regression tests for issue: 1533
......
...@@ -54,16 +54,16 @@ class TestValidationErrorWithFullDetails(TestCase): ...@@ -54,16 +54,16 @@ class TestValidationErrorWithFullDetails(TestCase):
request = factory.get('/', content_type='application/json') request = factory.get('/', content_type='application/json')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) assert response.status_code == status.HTTP_400_BAD_REQUEST
self.assertEqual(response.data, self.expected_response_data) assert response.data == self.expected_response_data
def test_function_based_view_exception_handler(self): def test_function_based_view_exception_handler(self):
view = error_view view = error_view
request = factory.get('/', content_type='application/json') request = factory.get('/', content_type='application/json')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) assert response.status_code == status.HTTP_400_BAD_REQUEST
self.assertEqual(response.data, self.expected_response_data) assert response.data == self.expected_response_data
class TestValidationErrorWithCodes(TestCase): class TestValidationErrorWithCodes(TestCase):
...@@ -89,13 +89,13 @@ class TestValidationErrorWithCodes(TestCase): ...@@ -89,13 +89,13 @@ class TestValidationErrorWithCodes(TestCase):
request = factory.get('/', content_type='application/json') request = factory.get('/', content_type='application/json')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) assert response.status_code == status.HTTP_400_BAD_REQUEST
self.assertEqual(response.data, self.expected_response_data) assert response.data == self.expected_response_data
def test_function_based_view_exception_handler(self): def test_function_based_view_exception_handler(self):
view = error_view view = error_view
request = factory.get('/', content_type='application/json') request = factory.get('/', content_type='application/json')
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) assert response.status_code == status.HTTP_400_BAD_REQUEST
self.assertEqual(response.data, self.expected_response_data) assert response.data == self.expected_response_data
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