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)
...@@ -106,7 +106,7 @@ class BasicAuthTests(TestCase): ...@@ -106,7 +106,7 @@ class BasicAuthTests(TestCase):
{'example': 'example'}, {'example': 'example'},
HTTP_AUTHORIZATION=auth HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_post_json_passing_basic_auth(self): def test_post_json_passing_basic_auth(self):
"""Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF""" """Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF"""
...@@ -121,7 +121,7 @@ class BasicAuthTests(TestCase): ...@@ -121,7 +121,7 @@ class BasicAuthTests(TestCase):
format='json', format='json',
HTTP_AUTHORIZATION=auth HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_regression_handle_bad_base64_basic_auth_header(self): def test_regression_handle_bad_base64_basic_auth_header(self):
"""Ensure POSTing JSON over basic auth with incorrectly padded Base64 string is handled correctly""" """Ensure POSTing JSON over basic auth with incorrectly padded Base64 string is handled correctly"""
...@@ -134,12 +134,12 @@ class BasicAuthTests(TestCase): ...@@ -134,12 +134,12 @@ class BasicAuthTests(TestCase):
format='json', format='json',
HTTP_AUTHORIZATION=auth HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_post_form_failing_basic_auth(self): def test_post_form_failing_basic_auth(self):
"""Ensure POSTing form over basic auth without correct credentials fails""" """Ensure POSTing form over basic auth without correct credentials fails"""
response = self.csrf_client.post('/basic/', {'example': 'example'}) response = self.csrf_client.post('/basic/', {'example': 'example'})
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_post_json_failing_basic_auth(self): def test_post_json_failing_basic_auth(self):
"""Ensure POSTing json over basic auth without correct credentials fails""" """Ensure POSTing json over basic auth without correct credentials fails"""
...@@ -148,8 +148,8 @@ class BasicAuthTests(TestCase): ...@@ -148,8 +148,8 @@ class BasicAuthTests(TestCase):
{'example': 'example'}, {'example': 'example'},
format='json' format='json'
) )
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
self.assertEqual(response['WWW-Authenticate'], 'Basic realm="api"') assert response['WWW-Authenticate'] == 'Basic realm="api"'
@override_settings(ROOT_URLCONF='tests.test_authentication') @override_settings(ROOT_URLCONF='tests.test_authentication')
...@@ -175,9 +175,8 @@ class SessionAuthTests(TestCase): ...@@ -175,9 +175,8 @@ class SessionAuthTests(TestCase):
cf. [#1810](https://github.com/tomchristie/django-rest-framework/pull/1810) cf. [#1810](https://github.com/tomchristie/django-rest-framework/pull/1810)
""" """
response = self.csrf_client.get('/auth/login/') response = self.csrf_client.get('/auth/login/')
self.assertContains( content = response.content.decode('utf8')
response, '<label for="id_username">Username:</label>' assert '<label for="id_username">Username:</label>' in content
)
def test_post_form_session_auth_failing_csrf(self): def test_post_form_session_auth_failing_csrf(self):
""" """
...@@ -185,7 +184,7 @@ class SessionAuthTests(TestCase): ...@@ -185,7 +184,7 @@ class SessionAuthTests(TestCase):
""" """
self.csrf_client.login(username=self.username, password=self.password) self.csrf_client.login(username=self.username, password=self.password)
response = self.csrf_client.post('/session/', {'example': 'example'}) response = self.csrf_client.post('/session/', {'example': 'example'})
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_post_form_session_auth_passing(self): def test_post_form_session_auth_passing(self):
""" """
...@@ -198,7 +197,7 @@ class SessionAuthTests(TestCase): ...@@ -198,7 +197,7 @@ class SessionAuthTests(TestCase):
response = self.non_csrf_client.post( response = self.non_csrf_client.post(
'/session/', {'example': 'example'} '/session/', {'example': 'example'}
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_put_form_session_auth_passing(self): def test_put_form_session_auth_passing(self):
""" """
...@@ -211,14 +210,14 @@ class SessionAuthTests(TestCase): ...@@ -211,14 +210,14 @@ class SessionAuthTests(TestCase):
response = self.non_csrf_client.put( response = self.non_csrf_client.put(
'/session/', {'example': 'example'} '/session/', {'example': 'example'}
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_post_form_session_auth_failing(self): def test_post_form_session_auth_failing(self):
""" """
Ensure POSTing form over session authentication without logged in user fails. Ensure POSTing form over session authentication without logged in user fails.
""" """
response = self.csrf_client.post('/session/', {'example': 'example'}) response = self.csrf_client.post('/session/', {'example': 'example'})
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) assert response.status_code == status.HTTP_403_FORBIDDEN
class BaseTokenAuthTests(object): class BaseTokenAuthTests(object):
...@@ -248,7 +247,7 @@ class BaseTokenAuthTests(object): ...@@ -248,7 +247,7 @@ class BaseTokenAuthTests(object):
response = self.csrf_client.post( response = self.csrf_client.post(
self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_fail_post_form_passing_nonexistent_token_auth(self): def test_fail_post_form_passing_nonexistent_token_auth(self):
# use a nonexistent token key # use a nonexistent token key
...@@ -256,7 +255,7 @@ class BaseTokenAuthTests(object): ...@@ -256,7 +255,7 @@ class BaseTokenAuthTests(object):
response = self.csrf_client.post( response = self.csrf_client.post(
self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_fail_post_form_passing_invalid_token_auth(self): def test_fail_post_form_passing_invalid_token_auth(self):
# add an 'invalid' unicode character # add an 'invalid' unicode character
...@@ -264,7 +263,7 @@ class BaseTokenAuthTests(object): ...@@ -264,7 +263,7 @@ class BaseTokenAuthTests(object):
response = self.csrf_client.post( response = self.csrf_client.post(
self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_post_json_passing_token_auth(self): def test_post_json_passing_token_auth(self):
""" """
...@@ -276,7 +275,7 @@ class BaseTokenAuthTests(object): ...@@ -276,7 +275,7 @@ class BaseTokenAuthTests(object):
self.path, {'example': 'example'}, self.path, {'example': 'example'},
format='json', HTTP_AUTHORIZATION=auth format='json', HTTP_AUTHORIZATION=auth
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
def test_post_json_makes_one_db_query(self): def test_post_json_makes_one_db_query(self):
""" """
...@@ -298,7 +297,7 @@ class BaseTokenAuthTests(object): ...@@ -298,7 +297,7 @@ class BaseTokenAuthTests(object):
Ensure POSTing form over token auth without correct credentials fails Ensure POSTing form over token auth without correct credentials fails
""" """
response = self.csrf_client.post(self.path, {'example': 'example'}) response = self.csrf_client.post(self.path, {'example': 'example'})
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_post_json_failing_token_auth(self): def test_post_json_failing_token_auth(self):
""" """
...@@ -307,7 +306,7 @@ class BaseTokenAuthTests(object): ...@@ -307,7 +306,7 @@ class BaseTokenAuthTests(object):
response = self.csrf_client.post( response = self.csrf_client.post(
self.path, {'example': 'example'}, format='json' self.path, {'example': 'example'}, format='json'
) )
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) assert response.status_code == status.HTTP_401_UNAUTHORIZED
@override_settings(ROOT_URLCONF='tests.test_authentication') @override_settings(ROOT_URLCONF='tests.test_authentication')
...@@ -319,13 +318,13 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase): ...@@ -319,13 +318,13 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase):
"""Ensure creating a token with no key will auto-assign a key""" """Ensure creating a token with no key will auto-assign a key"""
self.token.delete() self.token.delete()
token = self.model.objects.create(user=self.user) token = self.model.objects.create(user=self.user)
self.assertTrue(bool(token.key)) assert bool(token.key)
def test_generate_key_returns_string(self): def test_generate_key_returns_string(self):
"""Ensure generate_key returns a string""" """Ensure generate_key returns a string"""
token = self.model() token = self.model()
key = token.generate_key() key = token.generate_key()
self.assertTrue(isinstance(key, six.string_types)) assert isinstance(key, six.string_types)
def test_token_login_json(self): def test_token_login_json(self):
"""Ensure token login view using JSON POST works.""" """Ensure token login view using JSON POST works."""
...@@ -335,8 +334,8 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase): ...@@ -335,8 +334,8 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase):
{'username': self.username, 'password': self.password}, {'username': self.username, 'password': self.password},
format='json' format='json'
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data['token'], self.key) assert response.data['token'] == self.key
def test_token_login_json_bad_creds(self): def test_token_login_json_bad_creds(self):
""" """
...@@ -349,22 +348,24 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase): ...@@ -349,22 +348,24 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase):
{'username': self.username, 'password': "badpass"}, {'username': self.username, 'password': "badpass"},
format='json' format='json'
) )
self.assertEqual(response.status_code, 400) assert response.status_code == 400
def test_token_login_json_missing_fields(self): def test_token_login_json_missing_fields(self):
"""Ensure token login view using JSON POST fails if missing fields.""" """Ensure token login view using JSON POST fails if missing fields."""
client = APIClient(enforce_csrf_checks=True) client = APIClient(enforce_csrf_checks=True)
response = client.post('/auth-token/', response = client.post('/auth-token/',
{'username': self.username}, format='json') {'username': self.username}, format='json')
self.assertEqual(response.status_code, 400) assert response.status_code == 400
def test_token_login_form(self): def test_token_login_form(self):
"""Ensure token login view using form POST works.""" """Ensure token login view using form POST works."""
client = APIClient(enforce_csrf_checks=True) client = APIClient(enforce_csrf_checks=True)
response = client.post('/auth-token/', response = client.post(
{'username': self.username, 'password': self.password}) '/auth-token/',
self.assertEqual(response.status_code, status.HTTP_200_OK) {'username': self.username, 'password': self.password}
self.assertEqual(response.data['token'], self.key) )
assert response.status_code == status.HTTP_200_OK
assert response.data['token'] == self.key
@override_settings(ROOT_URLCONF='tests.test_authentication') @override_settings(ROOT_URLCONF='tests.test_authentication')
...@@ -397,8 +398,8 @@ class IncorrectCredentialsTests(TestCase): ...@@ -397,8 +398,8 @@ class IncorrectCredentialsTests(TestCase):
permission_classes=() permission_classes=()
) )
response = view(request) response = view(request)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) assert response.status_code == status.HTTP_403_FORBIDDEN
self.assertEqual(response.data, {'detail': 'Bad credentials'}) assert response.data == {'detail': 'Bad credentials'}
class FailingAuthAccessedInRenderer(TestCase): class FailingAuthAccessedInRenderer(TestCase):
...@@ -435,7 +436,7 @@ class FailingAuthAccessedInRenderer(TestCase): ...@@ -435,7 +436,7 @@ class FailingAuthAccessedInRenderer(TestCase):
request = factory.get('/') request = factory.get('/')
response = self.view(request) response = self.view(request)
content = response.render().content content = response.render().content
self.assertEqual(content, b'not authenticated') assert content == b'not authenticated'
class NoAuthenticationClassesTests(TestCase): class NoAuthenticationClassesTests(TestCase):
...@@ -458,6 +459,5 @@ class NoAuthenticationClassesTests(TestCase): ...@@ -458,6 +459,5 @@ class NoAuthenticationClassesTests(TestCase):
permission_classes=(DummyPermission,), permission_classes=(DummyPermission,),
) )
response = view(request) response = view(request)
self.assertEqual(response.status_code, assert response.status_code == status.HTTP_403_FORBIDDEN
status.HTTP_403_FORBIDDEN) assert response.data == {'detail': 'Dummy permission message'}
self.assertEqual(response.data, {'detail': 'Dummy permission message'})
...@@ -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):
......
...@@ -155,8 +155,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -155,8 +155,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
request = factory.get('/') request = factory.get('/')
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data) assert response.data == self.data
self.assertTrue(issubclass(w[-1].category, PendingDeprecationWarning)) self.assertTrue(issubclass(w[-1].category, PendingDeprecationWarning))
self.assertIn("'rest_framework.filters.DjangoFilterBackend' is pending deprecation.", str(w[-1].message)) self.assertIn("'rest_framework.filters.DjangoFilterBackend' is pending deprecation.", str(w[-1].message))
...@@ -175,9 +175,9 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -175,9 +175,9 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
request = factory.get('/') request = factory.get('/')
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data) assert response.data == self.data
self.assertEqual(len(w), 0) assert len(w) == 0
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_get_filtered_fields_root_view(self): def test_get_filtered_fields_root_view(self):
...@@ -189,24 +189,24 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -189,24 +189,24 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
# Basic test with no filter. # Basic test with no filter.
request = factory.get('/') request = factory.get('/')
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data) assert response.data == self.data
# Tests that the decimal filter works. # Tests that the decimal filter works.
search_decimal = Decimal('2.25') search_decimal = Decimal('2.25')
request = factory.get('/', {'decimal': '%s' % search_decimal}) request = factory.get('/', {'decimal': '%s' % search_decimal})
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal] expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
# Tests that the date filter works. # Tests that the date filter works.
search_date = datetime.date(2012, 9, 22) search_date = datetime.date(2012, 9, 22)
request = factory.get('/', {'date': '%s' % search_date}) # search_date str: '2012-09-22' request = factory.get('/', {'date': '%s' % search_date}) # search_date str: '2012-09-22'
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if parse_date(f['date']) == search_date] expected_data = [f for f in self.data if parse_date(f['date']) == search_date]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_filter_with_queryset(self): def test_filter_with_queryset(self):
...@@ -219,9 +219,9 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -219,9 +219,9 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
search_decimal = Decimal('2.25') search_decimal = Decimal('2.25')
request = factory.get('/', {'decimal': '%s' % search_decimal}) request = factory.get('/', {'decimal': '%s' % search_decimal})
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal] expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_filter_with_get_queryset_only(self): def test_filter_with_get_queryset_only(self):
...@@ -245,32 +245,32 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -245,32 +245,32 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
# Basic test with no filter. # Basic test with no filter.
request = factory.get('/') request = factory.get('/')
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data) assert response.data == self.data
# Tests that the decimal filter set with 'lt' in the filter class works. # Tests that the decimal filter set with 'lt' in the filter class works.
search_decimal = Decimal('4.25') search_decimal = Decimal('4.25')
request = factory.get('/', {'decimal': '%s' % search_decimal}) request = factory.get('/', {'decimal': '%s' % search_decimal})
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if Decimal(f['decimal']) < search_decimal] expected_data = [f for f in self.data if Decimal(f['decimal']) < search_decimal]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
# Tests that the date filter set with 'gt' in the filter class works. # Tests that the date filter set with 'gt' in the filter class works.
search_date = datetime.date(2012, 10, 2) search_date = datetime.date(2012, 10, 2)
request = factory.get('/', {'date': '%s' % search_date}) # search_date str: '2012-10-02' request = factory.get('/', {'date': '%s' % search_date}) # search_date str: '2012-10-02'
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if parse_date(f['date']) > search_date] expected_data = [f for f in self.data if parse_date(f['date']) > search_date]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
# Tests that the text filter set with 'icontains' in the filter class works. # Tests that the text filter set with 'icontains' in the filter class works.
search_text = 'ff' search_text = 'ff'
request = factory.get('/', {'text': '%s' % search_text}) request = factory.get('/', {'text': '%s' % search_text})
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if search_text in f['text'].lower()] expected_data = [f for f in self.data if search_text in f['text'].lower()]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
# Tests that multiple filters works. # Tests that multiple filters works.
search_decimal = Decimal('5.25') search_decimal = Decimal('5.25')
...@@ -280,10 +280,10 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -280,10 +280,10 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
'date': '%s' % (search_date,) 'date': '%s' % (search_date,)
}) })
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
expected_data = [f for f in self.data if parse_date(f['date']) > search_date and expected_data = [f for f in self.data if parse_date(f['date']) > search_date and
Decimal(f['decimal']) < search_decimal] Decimal(f['decimal']) < search_decimal]
self.assertEqual(response.data, expected_data) assert response.data == expected_data
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_incorrectly_configured_filter(self): def test_incorrectly_configured_filter(self):
...@@ -304,8 +304,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -304,8 +304,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
request = factory.get('/?text=aaa') request = factory.get('/?text=aaa')
response = view(request).render() response = 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), 1) assert len(response.data) == 1
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_base_model_filter_with_proxy(self): def test_base_model_filter_with_proxy(self):
...@@ -316,8 +316,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -316,8 +316,8 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
request = factory.get('/?text=aaa') request = factory.get('/?text=aaa')
response = view(request).render() response = 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), 1) assert len(response.data) == 1
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
def test_unknown_filter(self): def test_unknown_filter(self):
...@@ -329,7 +329,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): ...@@ -329,7 +329,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
search_integer = 10 search_integer = 10
request = factory.get('/', {'integer': '%s' % search_integer}) request = factory.get('/', {'integer': '%s' % search_integer})
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
@override_settings(ROOT_URLCONF='tests.test_filters') @override_settings(ROOT_URLCONF='tests.test_filters')
...@@ -351,8 +351,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase): ...@@ -351,8 +351,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
# Basic test with no filter. # Basic test with no filter.
response = self.client.get(self._get_url(item)) response = self.client.get(self._get_url(item))
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, data) assert response.data == data
# Tests that the decimal filter set that should fail. # Tests that the decimal filter set that should fail.
search_decimal = Decimal('4.25') search_decimal = Decimal('4.25')
...@@ -360,7 +360,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase): ...@@ -360,7 +360,7 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
response = self.client.get( response = self.client.get(
'{url}'.format(url=self._get_url(high_item)), '{url}'.format(url=self._get_url(high_item)),
{'decimal': '{param}'.format(param=search_decimal)}) {'decimal': '{param}'.format(param=search_decimal)})
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
# Tests that the decimal filter set that should succeed. # Tests that the decimal filter set that should succeed.
search_decimal = Decimal('4.25') search_decimal = Decimal('4.25')
...@@ -369,8 +369,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase): ...@@ -369,8 +369,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
response = self.client.get( response = self.client.get(
'{url}'.format(url=self._get_url(low_item)), '{url}'.format(url=self._get_url(low_item)),
{'decimal': '{param}'.format(param=search_decimal)}) {'decimal': '{param}'.format(param=search_decimal)})
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, low_item_data) assert response.data == low_item_data
# Tests that multiple filters works. # Tests that multiple filters works.
search_decimal = Decimal('5.25') search_decimal = Decimal('5.25')
...@@ -382,8 +382,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase): ...@@ -382,8 +382,8 @@ class IntegrationTestDetailFiltering(CommonFilteringTestCase):
'decimal': '{decimal}'.format(decimal=search_decimal), 'decimal': '{decimal}'.format(decimal=search_decimal),
'date': '{date}'.format(date=search_date) 'date': '{date}'.format(date=search_date)
}) })
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, valid_item_data) assert response.data == valid_item_data
class SearchFilterModel(models.Model): class SearchFilterModel(models.Model):
...@@ -424,13 +424,10 @@ class SearchFilterTests(TestCase): ...@@ -424,13 +424,10 @@ class SearchFilterTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'search': 'b'}) request = factory.get('/', {'search': 'b'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'z', 'text': 'abc'}, {'id': 1, 'title': 'z', 'text': 'abc'},
{'id': 2, 'title': 'zz', 'text': 'bcd'} {'id': 2, 'title': 'zz', 'text': 'bcd'}
] ]
)
def test_exact_search(self): def test_exact_search(self):
class SearchListView(generics.ListAPIView): class SearchListView(generics.ListAPIView):
...@@ -442,12 +439,9 @@ class SearchFilterTests(TestCase): ...@@ -442,12 +439,9 @@ class SearchFilterTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'search': 'zzz'}) request = factory.get('/', {'search': 'zzz'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'title': 'zzz', 'text': 'cde'} {'id': 3, 'title': 'zzz', 'text': 'cde'}
] ]
)
def test_startswith_search(self): def test_startswith_search(self):
class SearchListView(generics.ListAPIView): class SearchListView(generics.ListAPIView):
...@@ -459,12 +453,9 @@ class SearchFilterTests(TestCase): ...@@ -459,12 +453,9 @@ class SearchFilterTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'search': 'b'}) request = factory.get('/', {'search': 'b'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 2, 'title': 'zz', 'text': 'bcd'} {'id': 2, 'title': 'zz', 'text': 'bcd'}
] ]
)
def test_regexp_search(self): def test_regexp_search(self):
class SearchListView(generics.ListAPIView): class SearchListView(generics.ListAPIView):
...@@ -476,12 +467,9 @@ class SearchFilterTests(TestCase): ...@@ -476,12 +467,9 @@ class SearchFilterTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'search': 'z{2} ^b'}) request = factory.get('/', {'search': 'z{2} ^b'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 2, 'title': 'zz', 'text': 'bcd'} {'id': 2, 'title': 'zz', 'text': 'bcd'}
] ]
)
def test_search_with_nonstandard_search_param(self): def test_search_with_nonstandard_search_param(self):
with override_settings(REST_FRAMEWORK={'SEARCH_PARAM': 'query'}): with override_settings(REST_FRAMEWORK={'SEARCH_PARAM': 'query'}):
...@@ -496,13 +484,10 @@ class SearchFilterTests(TestCase): ...@@ -496,13 +484,10 @@ class SearchFilterTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'query': 'b'}) request = factory.get('/', {'query': 'b'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'z', 'text': 'abc'}, {'id': 1, 'title': 'z', 'text': 'abc'},
{'id': 2, 'title': 'zz', 'text': 'bcd'} {'id': 2, 'title': 'zz', 'text': 'bcd'}
] ]
)
reload_module(filters) reload_module(filters)
...@@ -528,15 +513,13 @@ class SearchFilterFkTests(TestCase): ...@@ -528,15 +513,13 @@ class SearchFilterFkTests(TestCase):
filter_ = filters.SearchFilter() filter_ = filters.SearchFilter()
prefixes = [''] + list(filter_.lookup_prefixes) prefixes = [''] + list(filter_.lookup_prefixes)
for prefix in prefixes: for prefix in prefixes:
self.assertFalse( assert not filter_.must_call_distinct(
filter_.must_call_distinct( SearchFilterModelFk._meta,
SearchFilterModelFk._meta, ["%stitle" % prefix] ["%stitle" % prefix]
)
)
self.assertFalse(
filter_.must_call_distinct(
SearchFilterModelFk._meta, ["%stitle" % prefix, "%sattribute__label" % prefix]
) )
assert not filter_.must_call_distinct(
SearchFilterModelFk._meta,
["%stitle" % prefix, "%sattribute__label" % prefix]
) )
def test_must_call_distinct_restores_meta_for_each_field(self): def test_must_call_distinct_restores_meta_for_each_field(self):
...@@ -545,10 +528,9 @@ class SearchFilterFkTests(TestCase): ...@@ -545,10 +528,9 @@ class SearchFilterFkTests(TestCase):
filter_ = filters.SearchFilter() filter_ = filters.SearchFilter()
prefixes = [''] + list(filter_.lookup_prefixes) prefixes = [''] + list(filter_.lookup_prefixes)
for prefix in prefixes: for prefix in prefixes:
self.assertFalse( assert not filter_.must_call_distinct(
filter_.must_call_distinct( SearchFilterModelFk._meta,
SearchFilterModelFk._meta, ["%sattribute__label" % prefix, "%stitle" % prefix] ["%sattribute__label" % prefix, "%stitle" % prefix]
)
) )
...@@ -596,21 +578,20 @@ class SearchFilterM2MTests(TestCase): ...@@ -596,21 +578,20 @@ class SearchFilterM2MTests(TestCase):
view = SearchListView.as_view() view = SearchListView.as_view()
request = factory.get('/', {'search': 'zz'}) request = factory.get('/', {'search': 'zz'})
response = view(request) response = view(request)
self.assertEqual(len(response.data), 1) assert len(response.data) == 1
def test_must_call_distinct(self): def test_must_call_distinct(self):
filter_ = filters.SearchFilter() filter_ = filters.SearchFilter()
prefixes = [''] + list(filter_.lookup_prefixes) prefixes = [''] + list(filter_.lookup_prefixes)
for prefix in prefixes: for prefix in prefixes:
self.assertFalse( assert not filter_.must_call_distinct(
filter_.must_call_distinct( SearchFilterModelM2M._meta,
SearchFilterModelM2M._meta, ["%stitle" % prefix] ["%stitle" % prefix]
)
)
self.assertTrue(
filter_.must_call_distinct(
SearchFilterModelM2M._meta, ["%stitle" % prefix, "%sattributes__label" % prefix]
) )
assert filter_.must_call_distinct(
SearchFilterModelM2M._meta,
["%stitle" % prefix, "%sattributes__label" % prefix]
) )
...@@ -672,14 +653,11 @@ class DjangoFilterOrderingTests(TestCase): ...@@ -672,14 +653,11 @@ class DjangoFilterOrderingTests(TestCase):
request = factory.get('/') request = factory.get('/')
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'date': '2014-10-08', 'text': 'cde'}, {'id': 3, 'date': '2014-10-08', 'text': 'cde'},
{'id': 2, 'date': '2013-10-08', 'text': 'bcd'}, {'id': 2, 'date': '2013-10-08', 'text': 'bcd'},
{'id': 1, 'date': '2012-10-08', 'text': 'abc'} {'id': 1, 'date': '2012-10-08', 'text': 'abc'}
] ]
)
class OrderingFilterTests(TestCase): class OrderingFilterTests(TestCase):
...@@ -713,14 +691,11 @@ class OrderingFilterTests(TestCase): ...@@ -713,14 +691,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'text'}) request = factory.get('/', {'ordering': 'text'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
] ]
)
def test_reverse_ordering(self): def test_reverse_ordering(self):
class OrderingListView(generics.ListAPIView): class OrderingListView(generics.ListAPIView):
...@@ -733,14 +708,11 @@ class OrderingFilterTests(TestCase): ...@@ -733,14 +708,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'ordering': '-text'}) request = factory.get('/', {'ordering': '-text'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
] ]
)
def test_incorrectfield_ordering(self): def test_incorrectfield_ordering(self):
class OrderingListView(generics.ListAPIView): class OrderingListView(generics.ListAPIView):
...@@ -753,14 +725,11 @@ class OrderingFilterTests(TestCase): ...@@ -753,14 +725,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'foobar'}) request = factory.get('/', {'ordering': 'foobar'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
] ]
)
def test_default_ordering(self): def test_default_ordering(self):
class OrderingListView(generics.ListAPIView): class OrderingListView(generics.ListAPIView):
...@@ -773,14 +742,11 @@ class OrderingFilterTests(TestCase): ...@@ -773,14 +742,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('') request = factory.get('')
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
] ]
)
def test_default_ordering_using_string(self): def test_default_ordering_using_string(self):
class OrderingListView(generics.ListAPIView): class OrderingListView(generics.ListAPIView):
...@@ -793,14 +759,11 @@ class OrderingFilterTests(TestCase): ...@@ -793,14 +759,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('') request = factory.get('')
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
] ]
)
def test_ordering_by_aggregate_field(self): def test_ordering_by_aggregate_field(self):
# create some related models to aggregate order by # create some related models to aggregate order by
...@@ -824,14 +787,11 @@ class OrderingFilterTests(TestCase): ...@@ -824,14 +787,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'relateds__count'}) request = factory.get('/', {'ordering': 'relateds__count'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
] ]
)
def test_ordering_with_nonstandard_ordering_param(self): def test_ordering_with_nonstandard_ordering_param(self):
with override_settings(REST_FRAMEWORK={'ORDERING_PARAM': 'order'}): with override_settings(REST_FRAMEWORK={'ORDERING_PARAM': 'order'}):
...@@ -847,14 +807,11 @@ class OrderingFilterTests(TestCase): ...@@ -847,14 +807,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'order': 'text'}) request = factory.get('/', {'order': 'text'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
] ]
)
reload_module(filters) reload_module(filters)
...@@ -884,14 +841,11 @@ class OrderingFilterTests(TestCase): ...@@ -884,14 +841,11 @@ class OrderingFilterTests(TestCase):
view = OrderingListView.as_view() view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'text'}) request = factory.get('/', {'ordering': 'text'})
response = view(request) response = view(request)
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, 'title': 'zyx', 'text': 'abc'}, {'id': 1, 'title': 'zyx', 'text': 'abc'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'}, {'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 3, 'title': 'xwv', 'text': 'cde'}, {'id': 3, 'title': 'xwv', 'text': 'cde'},
] ]
)
def test_ordering_with_improper_configuration(self): def test_ordering_with_improper_configuration(self):
class OrderingListView(generics.ListAPIView): class OrderingListView(generics.ListAPIView):
...@@ -967,14 +921,11 @@ class SensitiveOrderingFilterTests(TestCase): ...@@ -967,14 +921,11 @@ class SensitiveOrderingFilterTests(TestCase):
username_field = 'username' username_field = 'username'
# Note: Inverse username ordering correctly applied. # Note: Inverse username ordering correctly applied.
self.assertEqual( assert response.data == [
response.data,
[
{'id': 3, username_field: 'userC'}, {'id': 3, username_field: 'userC'},
{'id': 2, username_field: 'userB'}, {'id': 2, username_field: 'userB'},
{'id': 1, username_field: 'userA'}, {'id': 1, username_field: 'userA'},
] ]
)
def test_cannot_order_by_non_serializer_fields(self): def test_cannot_order_by_non_serializer_fields(self):
for serializer_cls in [ for serializer_cls in [
...@@ -997,11 +948,8 @@ class SensitiveOrderingFilterTests(TestCase): ...@@ -997,11 +948,8 @@ class SensitiveOrderingFilterTests(TestCase):
username_field = 'username' username_field = 'username'
# Note: The passwords are not in order. Default ordering is used. # Note: The passwords are not in order. Default ordering is used.
self.assertEqual( assert response.data == [
response.data,
[
{'id': 1, username_field: 'userA'}, # PassB {'id': 1, username_field: 'userA'}, # PassB
{'id': 2, username_field: 'userB'}, # PassC {'id': 2, username_field: 'userB'}, # PassC
{'id': 3, username_field: 'userC'}, # PassA {'id': 3, username_field: 'userC'}, # PassA
] ]
)
...@@ -98,8 +98,8 @@ class TestRootView(TestCase): ...@@ -98,8 +98,8 @@ class TestRootView(TestCase):
request = factory.get('/') request = factory.get('/')
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(response.data, self.data) assert response.data == self.data
def test_post_root_view(self): def test_post_root_view(self):
""" """
...@@ -109,10 +109,10 @@ class TestRootView(TestCase): ...@@ -109,10 +109,10 @@ class TestRootView(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_201_CREATED) assert response.status_code == status.HTTP_201_CREATED
self.assertEqual(response.data, {'id': 4, 'text': 'foobar'}) assert response.data == {'id': 4, 'text': 'foobar'}
created = self.objects.get(id=4) created = self.objects.get(id=4)
self.assertEqual(created.text, 'foobar') assert created.text == 'foobar'
def test_put_root_view(self): def test_put_root_view(self):
""" """
...@@ -122,8 +122,8 @@ class TestRootView(TestCase): ...@@ -122,8 +122,8 @@ class TestRootView(TestCase):
request = factory.put('/', data, format='json') request = factory.put('/', data, format='json')
with self.assertNumQueries(0): with self.assertNumQueries(0):
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
self.assertEqual(response.data, {"detail": 'Method "PUT" not allowed.'}) assert response.data == {"detail": 'Method "PUT" not allowed.'}
def test_delete_root_view(self): def test_delete_root_view(self):
""" """
...@@ -132,8 +132,8 @@ class TestRootView(TestCase): ...@@ -132,8 +132,8 @@ class TestRootView(TestCase):
request = factory.delete('/') request = factory.delete('/')
with self.assertNumQueries(0): with self.assertNumQueries(0):
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
self.assertEqual(response.data, {"detail": 'Method "DELETE" not allowed.'}) assert response.data == {"detail": 'Method "DELETE" not allowed.'}
def test_post_cannot_set_id(self): def test_post_cannot_set_id(self):
""" """
...@@ -143,10 +143,10 @@ class TestRootView(TestCase): ...@@ -143,10 +143,10 @@ class TestRootView(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_201_CREATED) assert response.status_code == status.HTTP_201_CREATED
self.assertEqual(response.data, {'id': 4, 'text': 'foobar'}) assert response.data == {'id': 4, 'text': 'foobar'}
created = self.objects.get(id=4) created = self.objects.get(id=4)
self.assertEqual(created.text, 'foobar') assert created.text == 'foobar'
def test_post_error_root_view(self): def test_post_error_root_view(self):
""" """
...@@ -156,7 +156,7 @@ class TestRootView(TestCase): ...@@ -156,7 +156,7 @@ class TestRootView(TestCase):
request = factory.post('/', data, HTTP_ACCEPT='text/html') request = factory.post('/', data, HTTP_ACCEPT='text/html')
response = self.view(request).render() response = self.view(request).render()
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>' expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
self.assertIn(expected_error, response.rendered_content.decode('utf-8')) assert expected_error in response.rendered_content.decode('utf-8')
EXPECTED_QUERIES_FOR_PUT = 2 EXPECTED_QUERIES_FOR_PUT = 2
...@@ -185,8 +185,8 @@ class TestInstanceView(TestCase): ...@@ -185,8 +185,8 @@ class TestInstanceView(TestCase):
request = factory.get('/1') request = factory.get('/1')
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data[0]) assert response.data == self.data[0]
def test_post_instance_view(self): def test_post_instance_view(self):
""" """
...@@ -196,8 +196,8 @@ class TestInstanceView(TestCase): ...@@ -196,8 +196,8 @@ class TestInstanceView(TestCase):
request = factory.post('/', data, format='json') request = factory.post('/', data, format='json')
with self.assertNumQueries(0): with self.assertNumQueries(0):
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
self.assertEqual(response.data, {"detail": 'Method "POST" not allowed.'}) assert response.data == {"detail": 'Method "POST" not allowed.'}
def test_put_instance_view(self): def test_put_instance_view(self):
""" """
...@@ -207,10 +207,10 @@ class TestInstanceView(TestCase): ...@@ -207,10 +207,10 @@ class TestInstanceView(TestCase):
request = factory.put('/1', data, format='json') request = factory.put('/1', data, format='json')
with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT): with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk='1').render() response = self.view(request, pk='1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(dict(response.data), {'id': 1, 'text': 'foobar'}) assert dict(response.data) == {'id': 1, 'text': 'foobar'}
updated = self.objects.get(id=1) updated = self.objects.get(id=1)
self.assertEqual(updated.text, 'foobar') assert updated.text == 'foobar'
def test_patch_instance_view(self): def test_patch_instance_view(self):
""" """
...@@ -221,10 +221,10 @@ class TestInstanceView(TestCase): ...@@ -221,10 +221,10 @@ class TestInstanceView(TestCase):
with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT): with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'}) assert response.data == {'id': 1, 'text': 'foobar'}
updated = self.objects.get(id=1) updated = self.objects.get(id=1)
self.assertEqual(updated.text, 'foobar') assert updated.text == 'foobar'
def test_delete_instance_view(self): def test_delete_instance_view(self):
""" """
...@@ -233,10 +233,10 @@ class TestInstanceView(TestCase): ...@@ -233,10 +233,10 @@ class TestInstanceView(TestCase):
request = factory.delete('/1') request = factory.delete('/1')
with self.assertNumQueries(2): with self.assertNumQueries(2):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) assert response.status_code == status.HTTP_204_NO_CONTENT
self.assertEqual(response.content, six.b('')) assert response.content == six.b('')
ids = [obj.id for obj in self.objects.all()] ids = [obj.id for obj in self.objects.all()]
self.assertEqual(ids, [2, 3]) assert ids == [2, 3]
def test_get_instance_view_incorrect_arg(self): def test_get_instance_view_incorrect_arg(self):
""" """
...@@ -246,7 +246,7 @@ class TestInstanceView(TestCase): ...@@ -246,7 +246,7 @@ class TestInstanceView(TestCase):
request = factory.get('/a') request = factory.get('/a')
with self.assertNumQueries(0): with self.assertNumQueries(0):
response = self.view(request, pk='a').render() response = self.view(request, pk='a').render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_put_cannot_set_id(self): def test_put_cannot_set_id(self):
""" """
...@@ -256,10 +256,10 @@ class TestInstanceView(TestCase): ...@@ -256,10 +256,10 @@ class TestInstanceView(TestCase):
request = factory.put('/1', data, format='json') request = factory.put('/1', data, format='json')
with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT): with self.assertNumQueries(EXPECTED_QUERIES_FOR_PUT):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'}) assert response.data == {'id': 1, 'text': 'foobar'}
updated = self.objects.get(id=1) updated = self.objects.get(id=1)
self.assertEqual(updated.text, 'foobar') assert updated.text == 'foobar'
def test_put_to_deleted_instance(self): def test_put_to_deleted_instance(self):
""" """
...@@ -271,7 +271,7 @@ class TestInstanceView(TestCase): ...@@ -271,7 +271,7 @@ class TestInstanceView(TestCase):
request = factory.put('/1', data, format='json') request = factory.put('/1', data, format='json')
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_put_to_filtered_out_instance(self): def test_put_to_filtered_out_instance(self):
""" """
...@@ -282,7 +282,7 @@ class TestInstanceView(TestCase): ...@@ -282,7 +282,7 @@ class TestInstanceView(TestCase):
filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk
request = factory.put('/{0}'.format(filtered_out_pk), data, format='json') request = factory.put('/{0}'.format(filtered_out_pk), data, format='json')
response = self.view(request, pk=filtered_out_pk).render() response = self.view(request, pk=filtered_out_pk).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_patch_cannot_create_an_object(self): def test_patch_cannot_create_an_object(self):
""" """
...@@ -292,8 +292,8 @@ class TestInstanceView(TestCase): ...@@ -292,8 +292,8 @@ class TestInstanceView(TestCase):
request = factory.patch('/999', data, format='json') request = factory.patch('/999', data, format='json')
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request, pk=999).render() response = self.view(request, pk=999).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
self.assertFalse(self.objects.filter(id=999).exists()) assert not self.objects.filter(id=999).exists()
def test_put_error_instance_view(self): def test_put_error_instance_view(self):
""" """
...@@ -303,7 +303,7 @@ class TestInstanceView(TestCase): ...@@ -303,7 +303,7 @@ class TestInstanceView(TestCase):
request = factory.put('/', data, HTTP_ACCEPT='text/html') request = factory.put('/', data, HTTP_ACCEPT='text/html')
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>' expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
self.assertIn(expected_error, response.rendered_content.decode('utf-8')) assert expected_error in response.rendered_content.decode('utf-8')
class TestFKInstanceView(TestCase): class TestFKInstanceView(TestCase):
...@@ -363,8 +363,8 @@ class TestOverriddenGetObject(TestCase): ...@@ -363,8 +363,8 @@ class TestOverriddenGetObject(TestCase):
request = factory.get('/1') request = factory.get('/1')
with self.assertNumQueries(1): with self.assertNumQueries(1):
response = self.view(request, pk=1).render() response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, self.data[0]) assert response.data == self.data[0]
# Regression test for #285 # Regression test for #285
...@@ -394,9 +394,9 @@ class TestCreateModelWithAutoNowAddField(TestCase): ...@@ -394,9 +394,9 @@ class TestCreateModelWithAutoNowAddField(TestCase):
data = {'email': 'foobar@example.com', 'content': 'foobar'} data = {'email': 'foobar@example.com', 'content': 'foobar'}
request = factory.post('/', data, format='json') request = factory.post('/', data, format='json')
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.status_code, status.HTTP_201_CREATED) assert response.status_code == status.HTTP_201_CREATED
created = self.objects.get(id=1) created = self.objects.get(id=1)
self.assertEqual(created.content, 'foobar') assert created.content == 'foobar'
# Test for particularly ugly regression with m2m in browsable API # Test for particularly ugly regression with m2m in browsable API
...@@ -432,7 +432,7 @@ class TestM2MBrowsableAPI(TestCase): ...@@ -432,7 +432,7 @@ class TestM2MBrowsableAPI(TestCase):
request = factory.get('/', HTTP_ACCEPT='text/html') request = factory.get('/', HTTP_ACCEPT='text/html')
view = ExampleView().as_view() view = ExampleView().as_view()
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
class InclusiveFilterBackend(object): class InclusiveFilterBackend(object):
...@@ -489,9 +489,9 @@ class TestFilterBackendAppliedToViews(TestCase): ...@@ -489,9 +489,9 @@ class TestFilterBackendAppliedToViews(TestCase):
root_view = RootView.as_view(filter_backends=(InclusiveFilterBackend,)) root_view = RootView.as_view(filter_backends=(InclusiveFilterBackend,))
request = factory.get('/') request = factory.get('/')
response = root_view(request).render() response = root_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), 1) assert len(response.data) == 1
self.assertEqual(response.data, [{'id': 1, 'text': 'foo'}]) assert response.data == [{'id': 1, 'text': 'foo'}]
def test_get_root_view_filters_out_all_models_with_exclusive_filter_backend(self): def test_get_root_view_filters_out_all_models_with_exclusive_filter_backend(self):
""" """
...@@ -500,8 +500,8 @@ class TestFilterBackendAppliedToViews(TestCase): ...@@ -500,8 +500,8 @@ class TestFilterBackendAppliedToViews(TestCase):
root_view = RootView.as_view(filter_backends=(ExclusiveFilterBackend,)) root_view = RootView.as_view(filter_backends=(ExclusiveFilterBackend,))
request = factory.get('/') request = factory.get('/')
response = root_view(request).render() response = root_view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, []) assert response.data == []
def test_get_instance_view_filters_out_name_with_filter_backend(self): def test_get_instance_view_filters_out_name_with_filter_backend(self):
""" """
...@@ -510,8 +510,8 @@ class TestFilterBackendAppliedToViews(TestCase): ...@@ -510,8 +510,8 @@ class TestFilterBackendAppliedToViews(TestCase):
instance_view = InstanceView.as_view(filter_backends=(ExclusiveFilterBackend,)) instance_view = InstanceView.as_view(filter_backends=(ExclusiveFilterBackend,))
request = factory.get('/1') request = factory.get('/1')
response = instance_view(request, pk=1).render() response = instance_view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) assert response.status_code == status.HTTP_404_NOT_FOUND
self.assertEqual(response.data, {'detail': 'Not found.'}) assert response.data == {'detail': 'Not found.'}
def test_get_instance_view_will_return_single_object_when_filter_does_not_exclude_it(self): def test_get_instance_view_will_return_single_object_when_filter_does_not_exclude_it(self):
""" """
...@@ -520,8 +520,8 @@ class TestFilterBackendAppliedToViews(TestCase): ...@@ -520,8 +520,8 @@ class TestFilterBackendAppliedToViews(TestCase):
instance_view = InstanceView.as_view(filter_backends=(InclusiveFilterBackend,)) instance_view = InstanceView.as_view(filter_backends=(InclusiveFilterBackend,))
request = factory.get('/1') request = factory.get('/1')
response = instance_view(request, pk=1).render() response = instance_view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) assert response.status_code == status.HTTP_200_OK
self.assertEqual(response.data, {'id': 1, 'text': 'foo'}) assert response.data == {'id': 1, 'text': 'foo'}
def test_dynamic_serializer_form_in_browsable_api(self): def test_dynamic_serializer_form_in_browsable_api(self):
""" """
...@@ -530,8 +530,9 @@ class TestFilterBackendAppliedToViews(TestCase): ...@@ -530,8 +530,9 @@ class TestFilterBackendAppliedToViews(TestCase):
view = DynamicSerializerView.as_view() view = DynamicSerializerView.as_view()
request = factory.get('/') request = factory.get('/')
response = view(request).render() response = view(request).render()
self.assertContains(response, 'field_b') content = response.content.decode('utf8')
self.assertNotContains(response, 'field_a') assert 'field_b' in content
assert 'field_a' not in content
class TestGuardedQueryset(TestCase): class TestGuardedQueryset(TestCase):
......
...@@ -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
...@@ -84,7 +84,7 @@ class PKManyToManyTests(TestCase): ...@@ -84,7 +84,7 @@ class PKManyToManyTests(TestCase):
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]} {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
] ]
with self.assertNumQueries(4): with self.assertNumQueries(4):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_many_to_many_retrieve_prefetch_related(self): def test_many_to_many_retrieve_prefetch_related(self):
queryset = ManyToManySource.objects.all().prefetch_related('targets') queryset = ManyToManySource.objects.all().prefetch_related('targets')
...@@ -101,15 +101,15 @@ class PKManyToManyTests(TestCase): ...@@ -101,15 +101,15 @@ class PKManyToManyTests(TestCase):
{'id': 3, 'name': 'target-3', 'sources': [3]} {'id': 3, 'name': 'target-3', 'sources': [3]}
] ]
with self.assertNumQueries(4): with self.assertNumQueries(4):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_many_to_many_update(self): def test_many_to_many_update(self):
data = {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]} data = {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]}
instance = ManyToManySource.objects.get(pk=1) instance = ManyToManySource.objects.get(pk=1)
serializer = ManyToManySourceSerializer(instance, data=data) serializer = ManyToManySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
# Ensure source 1 is updated, and everything else is as expected # Ensure source 1 is updated, and everything else is as expected
queryset = ManyToManySource.objects.all() queryset = ManyToManySource.objects.all()
...@@ -119,15 +119,15 @@ class PKManyToManyTests(TestCase): ...@@ -119,15 +119,15 @@ class PKManyToManyTests(TestCase):
{'id': 2, 'name': 'source-2', 'targets': [1, 2]}, {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]} {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_reverse_many_to_many_update(self): def test_reverse_many_to_many_update(self):
data = {'id': 1, 'name': 'target-1', 'sources': [1]} data = {'id': 1, 'name': 'target-1', 'sources': [1]}
instance = ManyToManyTarget.objects.get(pk=1) instance = ManyToManyTarget.objects.get(pk=1)
serializer = ManyToManyTargetSerializer(instance, data=data) serializer = ManyToManyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
# Ensure target 1 is updated, and everything else is as expected # Ensure target 1 is updated, and everything else is as expected
queryset = ManyToManyTarget.objects.all() queryset = ManyToManyTarget.objects.all()
...@@ -137,15 +137,15 @@ class PKManyToManyTests(TestCase): ...@@ -137,15 +137,15 @@ class PKManyToManyTests(TestCase):
{'id': 2, 'name': 'target-2', 'sources': [2, 3]}, {'id': 2, 'name': 'target-2', 'sources': [2, 3]},
{'id': 3, 'name': 'target-3', 'sources': [3]} {'id': 3, 'name': 'target-3', 'sources': [3]}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_many_to_many_create(self): def test_many_to_many_create(self):
data = {'id': 4, 'name': 'source-4', 'targets': [1, 3]} data = {'id': 4, 'name': 'source-4', 'targets': [1, 3]}
serializer = ManyToManySourceSerializer(data=data) serializer = ManyToManySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
self.assertEqual(obj.name, 'source-4') assert obj.name == 'source-4'
# Ensure source 4 is added, and everything else is as expected # Ensure source 4 is added, and everything else is as expected
queryset = ManyToManySource.objects.all() queryset = ManyToManySource.objects.all()
...@@ -156,7 +156,7 @@ class PKManyToManyTests(TestCase): ...@@ -156,7 +156,7 @@ class PKManyToManyTests(TestCase):
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}, {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]},
{'id': 4, 'name': 'source-4', 'targets': [1, 3]}, {'id': 4, 'name': 'source-4', 'targets': [1, 3]},
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_many_to_many_unsaved(self): def test_many_to_many_unsaved(self):
source = ManyToManySource(name='source-unsaved') source = ManyToManySource(name='source-unsaved')
...@@ -166,15 +166,15 @@ class PKManyToManyTests(TestCase): ...@@ -166,15 +166,15 @@ class PKManyToManyTests(TestCase):
expected = {'id': None, 'name': 'source-unsaved', 'targets': []} expected = {'id': None, 'name': 'source-unsaved', 'targets': []}
# no query if source hasn't been created yet # no query if source hasn't been created yet
with self.assertNumQueries(0): with self.assertNumQueries(0):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_reverse_many_to_many_create(self): def test_reverse_many_to_many_create(self):
data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]} data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
serializer = ManyToManyTargetSerializer(data=data) serializer = ManyToManyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
self.assertEqual(obj.name, 'target-4') assert obj.name == 'target-4'
# Ensure target 4 is added, and everything else is as expected # Ensure target 4 is added, and everything else is as expected
queryset = ManyToManyTarget.objects.all() queryset = ManyToManyTarget.objects.all()
...@@ -185,7 +185,7 @@ class PKManyToManyTests(TestCase): ...@@ -185,7 +185,7 @@ class PKManyToManyTests(TestCase):
{'id': 3, 'name': 'target-3', 'sources': [3]}, {'id': 3, 'name': 'target-3', 'sources': [3]},
{'id': 4, 'name': 'target-4', 'sources': [1, 3]} {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
class PKForeignKeyTests(TestCase): class PKForeignKeyTests(TestCase):
...@@ -207,7 +207,7 @@ class PKForeignKeyTests(TestCase): ...@@ -207,7 +207,7 @@ class PKForeignKeyTests(TestCase):
{'id': 3, 'name': 'source-3', 'target': 1} {'id': 3, 'name': 'source-3', 'target': 1}
] ]
with self.assertNumQueries(1): with self.assertNumQueries(1):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_reverse_foreign_key_retrieve(self): def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
...@@ -217,7 +217,7 @@ class PKForeignKeyTests(TestCase): ...@@ -217,7 +217,7 @@ class PKForeignKeyTests(TestCase):
{'id': 2, 'name': 'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
] ]
with self.assertNumQueries(3): with self.assertNumQueries(3):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_reverse_foreign_key_retrieve_prefetch_related(self): def test_reverse_foreign_key_retrieve_prefetch_related(self):
queryset = ForeignKeyTarget.objects.all().prefetch_related('sources') queryset = ForeignKeyTarget.objects.all().prefetch_related('sources')
...@@ -229,9 +229,9 @@ class PKForeignKeyTests(TestCase): ...@@ -229,9 +229,9 @@ class PKForeignKeyTests(TestCase):
data = {'id': 1, 'name': 'source-1', 'target': 2} data = {'id': 1, 'name': 'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
# Ensure source 1 is updated, and everything else is as expected # Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
...@@ -241,20 +241,20 @@ class PKForeignKeyTests(TestCase): ...@@ -241,20 +241,20 @@ class PKForeignKeyTests(TestCase):
{'id': 2, 'name': 'source-2', 'target': 1}, {'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': 1} {'id': 3, 'name': 'source-3', 'target': 1}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_update_incorrect_type(self): def test_foreign_key_update_incorrect_type(self):
data = {'id': 1, 'name': 'source-1', 'target': 'foo'} data = {'id': 1, 'name': 'source-1', 'target': 'foo'}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]}) assert serializer.errors == {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]}
def test_reverse_foreign_key_update(self): def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]} data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
instance = ForeignKeyTarget.objects.get(pk=2) instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data) serializer = ForeignKeyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
# We shouldn't have saved anything to the db yet since save # We shouldn't have saved anything to the db yet since save
# hasn't been called. # hasn't been called.
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
...@@ -263,10 +263,10 @@ class PKForeignKeyTests(TestCase): ...@@ -263,10 +263,10 @@ class PKForeignKeyTests(TestCase):
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': 'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
] ]
self.assertEqual(new_serializer.data, expected) assert new_serializer.data == expected
serializer.save() serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
# Ensure target 2 is update, and everything else is as expected # Ensure target 2 is update, and everything else is as expected
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
...@@ -275,15 +275,15 @@ class PKForeignKeyTests(TestCase): ...@@ -275,15 +275,15 @@ class PKForeignKeyTests(TestCase):
{'id': 1, 'name': 'target-1', 'sources': [2]}, {'id': 1, 'name': 'target-1', 'sources': [2]},
{'id': 2, 'name': 'target-2', 'sources': [1, 3]}, {'id': 2, 'name': 'target-2', 'sources': [1, 3]},
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_create(self): def test_foreign_key_create(self):
data = {'id': 4, 'name': 'source-4', 'target': 2} data = {'id': 4, 'name': 'source-4', 'target': 2}
serializer = ForeignKeySourceSerializer(data=data) serializer = ForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
self.assertEqual(obj.name, 'source-4') assert obj.name == 'source-4'
# Ensure source 4 is added, and everything else is as expected # Ensure source 4 is added, and everything else is as expected
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
...@@ -294,15 +294,15 @@ class PKForeignKeyTests(TestCase): ...@@ -294,15 +294,15 @@ class PKForeignKeyTests(TestCase):
{'id': 3, 'name': 'source-3', 'target': 1}, {'id': 3, 'name': 'source-3', 'target': 1},
{'id': 4, 'name': 'source-4', 'target': 2}, {'id': 4, 'name': 'source-4', 'target': 2},
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_reverse_foreign_key_create(self): def test_reverse_foreign_key_create(self):
data = {'id': 3, 'name': 'target-3', 'sources': [1, 3]} data = {'id': 3, 'name': 'target-3', 'sources': [1, 3]}
serializer = ForeignKeyTargetSerializer(data=data) serializer = ForeignKeyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
self.assertEqual(obj.name, 'target-3') assert obj.name == 'target-3'
# Ensure target 3 is added, and everything else is as expected # Ensure target 3 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
...@@ -312,14 +312,14 @@ class PKForeignKeyTests(TestCase): ...@@ -312,14 +312,14 @@ class PKForeignKeyTests(TestCase):
{'id': 2, 'name': 'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
{'id': 3, 'name': 'target-3', 'sources': [1, 3]}, {'id': 3, 'name': 'target-3', 'sources': [1, 3]},
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_update_with_invalid_null(self): def test_foreign_key_update_with_invalid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None} data = {'id': 1, 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual(serializer.errors, {'target': ['This field may not be null.']}) assert serializer.errors == {'target': ['This field may not be null.']}
def test_foreign_key_with_unsaved(self): def test_foreign_key_with_unsaved(self):
source = ForeignKeySource(name='source-unsaved') source = ForeignKeySource(name='source-unsaved')
...@@ -329,7 +329,7 @@ class PKForeignKeyTests(TestCase): ...@@ -329,7 +329,7 @@ class PKForeignKeyTests(TestCase):
# no query if source hasn't been created yet # no query if source hasn't been created yet
with self.assertNumQueries(0): with self.assertNumQueries(0):
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_with_empty(self): def test_foreign_key_with_empty(self):
""" """
...@@ -338,7 +338,7 @@ class PKForeignKeyTests(TestCase): ...@@ -338,7 +338,7 @@ class PKForeignKeyTests(TestCase):
https://github.com/tomchristie/django-rest-framework/issues/1072 https://github.com/tomchristie/django-rest-framework/issues/1072
""" """
serializer = NullableForeignKeySourceSerializer() serializer = NullableForeignKeySourceSerializer()
self.assertEqual(serializer.data['target'], None) assert serializer.data['target'] is None
def test_foreign_key_not_required(self): def test_foreign_key_not_required(self):
""" """
...@@ -350,7 +350,7 @@ class PKForeignKeyTests(TestCase): ...@@ -350,7 +350,7 @@ class PKForeignKeyTests(TestCase):
extra_kwargs = {'target': {'required': False}} extra_kwargs = {'target': {'required': False}}
serializer = ModelSerializer(data={'name': 'test'}) serializer = ModelSerializer(data={'name': 'test'})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
self.assertNotIn('target', serializer.validated_data) assert 'target' not in serializer.validated_data
class PKNullableForeignKeyTests(TestCase): class PKNullableForeignKeyTests(TestCase):
...@@ -371,15 +371,15 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -371,15 +371,15 @@ class PKNullableForeignKeyTests(TestCase):
{'id': 2, 'name': 'source-2', 'target': 1}, {'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_create_with_valid_null(self): def test_foreign_key_create_with_valid_null(self):
data = {'id': 4, 'name': 'source-4', 'target': None} data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data) serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
self.assertEqual(obj.name, 'source-4') assert obj.name == 'source-4'
# Ensure source 4 is created, and everything else is as expected # Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
...@@ -390,7 +390,7 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -390,7 +390,7 @@ class PKNullableForeignKeyTests(TestCase):
{'id': 3, 'name': 'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None} {'id': 4, 'name': 'source-4', 'target': None}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_create_with_valid_emptystring(self): def test_foreign_key_create_with_valid_emptystring(self):
""" """
...@@ -400,10 +400,10 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -400,10 +400,10 @@ class PKNullableForeignKeyTests(TestCase):
data = {'id': 4, 'name': 'source-4', 'target': ''} data = {'id': 4, 'name': 'source-4', 'target': ''}
expected_data = {'id': 4, 'name': 'source-4', 'target': None} expected_data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data) serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
obj = serializer.save() obj = serializer.save()
self.assertEqual(serializer.data, expected_data) assert serializer.data == expected_data
self.assertEqual(obj.name, 'source-4') assert obj.name == 'source-4'
# Ensure source 4 is created, and everything else is as expected # Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
...@@ -414,15 +414,15 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -414,15 +414,15 @@ class PKNullableForeignKeyTests(TestCase):
{'id': 3, 'name': 'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None} {'id': 4, 'name': 'source-4', 'target': None}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_update_with_valid_null(self): def test_foreign_key_update_with_valid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None} data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1) instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data) serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
self.assertEqual(serializer.data, data) assert serializer.data == data
# Ensure source 1 is updated, and everything else is as expected # Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
...@@ -432,7 +432,7 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -432,7 +432,7 @@ class PKNullableForeignKeyTests(TestCase):
{'id': 2, 'name': 'source-2', 'target': 1}, {'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None} {'id': 3, 'name': 'source-3', 'target': None}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_foreign_key_update_with_valid_emptystring(self): def test_foreign_key_update_with_valid_emptystring(self):
""" """
...@@ -443,9 +443,9 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -443,9 +443,9 @@ class PKNullableForeignKeyTests(TestCase):
expected_data = {'id': 1, 'name': 'source-1', 'target': None} expected_data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1) instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data) serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
self.assertEqual(serializer.data, expected_data) assert serializer.data == expected_data
# Ensure source 1 is updated, and everything else is as expected # Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
...@@ -455,18 +455,18 @@ class PKNullableForeignKeyTests(TestCase): ...@@ -455,18 +455,18 @@ class PKNullableForeignKeyTests(TestCase):
{'id': 2, 'name': 'source-2', 'target': 1}, {'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None} {'id': 3, 'name': 'source-3', 'target': None}
] ]
self.assertEqual(serializer.data, expected) assert serializer.data == expected
def test_null_uuid_foreign_key_serializes_as_none(self): def test_null_uuid_foreign_key_serializes_as_none(self):
source = NullableUUIDForeignKeySource(name='Source') source = NullableUUIDForeignKeySource(name='Source')
serializer = NullableUUIDForeignKeySourceSerializer(source) serializer = NullableUUIDForeignKeySourceSerializer(source)
data = serializer.data data = serializer.data
self.assertEqual(data["target"], None) assert data["target"] is None
def test_nullable_uuid_foreign_key_is_valid_when_none(self): def test_nullable_uuid_foreign_key_is_valid_when_none(self):
data = {"name": "Source", "target": None} data = {"name": "Source", "target": None}
serializer = NullableUUIDForeignKeySourceSerializer(data=data) serializer = NullableUUIDForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid(), serializer.errors) assert serializer.is_valid(), serializer.errors
class PKNullableOneToOneTests(TestCase): class PKNullableOneToOneTests(TestCase):
...@@ -485,4 +485,4 @@ class PKNullableOneToOneTests(TestCase): ...@@ -485,4 +485,4 @@ class PKNullableOneToOneTests(TestCase):
{'id': 1, 'name': 'target-1', 'nullable_source': None}, {'id': 1, 'name': 'target-1', 'nullable_source': None},
{'id': 2, 'name': 'target-2', 'nullable_source': 1}, {'id': 2, 'name': 'target-2', 'nullable_source': 1},
] ]
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