diff --git a/README.md b/README.md index 155f8dead..7bf90ba6a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The initial aim is to provide a single full-time position on REST framework.

- +

diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index bf3a31eb7..4a01188f3 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -363,7 +363,7 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [oauth]: http://oauth.net/2/ [permission]: permissions.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 [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/ diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 17168b721..b527b016b 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -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)` -- `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. - `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. @@ -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. -[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 -[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 -[strftime]: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior -[django-widgets]: https://docs.djangoproject.com/en/dev/ref/forms/widgets/ +[strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior +[django-widgets]: https://docs.djangoproject.com/en/stable/ref/forms/widgets/ [iso8601]: http://www.w3.org/TR/NOTE-datetime [drf-compound-fields]: https://drf-compound-fields.readthedocs.io [drf-extra-fields]: https://github.com/Hipo/drf-extra-fields diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 3f212ced3..8a23a2ea3 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -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. -[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-docs]: https://django-filter.readthedocs.io/en/latest/index.html [guardian]: https://django-guardian.readthedocs.io/ [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 [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-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter [django-url-filter]: https://github.com/miki725/django-url-filter diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index c368d0b46..606a3787a 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -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. -[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 [ListModelMixin]: #listmodelmixin [CreateModelMixin]: #createmodelmixin diff --git a/docs/api-guide/metadata.md b/docs/api-guide/metadata.md index e12aeb7fd..e98a9a311 100644 --- a/docs/api-guide/metadata.md +++ b/docs/api-guide/metadata.md @@ -104,6 +104,18 @@ Then configure your settings to use this custom class: 'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata' } +# Third party packages + +The following third party packages provide additional metadata implementations. + +## DRF-schema-adapter + +[drf-schema-adapter][drf-schema-adapter] is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate [json-schema][json-schema] as well as schema information readable by various libraries. + +You can also write your own adapter to work with your specific frontend. +If you whish to do so, it also provides an exporter that can export those schema information to json files. + [cite]: http://tools.ietf.org/html/rfc7231#section-4.3.7 [no-options]: https://www.mnot.net/blog/2012/10/29/NO_OPTIONS [json-schema]: http://json-schema.org/ +[drf-schema-adapter]: https://github.com/drf-forms/drf-schema-adapter diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index f82614eca..bc7a5602d 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -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. -[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/ [link-header]: ../img/link-header-pagination.png [drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index ef2859fe1..7bf932d06 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -224,7 +224,7 @@ Modify your REST framework settings. [jquery-ajax]: http://api.jquery.com/jQuery.ajax/ [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-xml]: http://jpadilla.github.io/django-rest-framework-xml/ [yaml]: http://www.yaml.org/ diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 7cdb59531..be2981327 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -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. -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 [authentication]: authentication.md [throttling]: throttling.md [filtering]: filtering.md -[contribauth]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-permissions -[objectpermissions]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#handling-object-permissions +[contribauth]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions +[objectpermissions]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#handling-object-permissions [guardian]: https://github.com/lukaszb/django-guardian [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 diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index aabe49412..662fd4809 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -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. - See: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ + See: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/ """ tag_name = models.SlugField() 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 The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys. [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 -[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 [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index a95778350..236504850 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -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. +See the [_HTML & Forms_ Topic Page][html-and-forms] for further examples of `TemplateHTMLRenderer` usage. + **.media_type**: `text/html` **.format**: `'.html'` @@ -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]. -[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 [html-and-forms]: ../topics/html-and-forms.md [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 [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.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/ [cors]: http://www.w3.org/TR/cors/ [cors-docs]: http://www.django-rest-framework.org/topics/ajax-csrf-cors/ diff --git a/docs/api-guide/responses.md b/docs/api-guide/responses.md index 97f312710..8ee14eefa 100644 --- a/docs/api-guide/responses.md +++ b/docs/api-guide/responses.md @@ -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. -[cite]: https://docs.djangoproject.com/en/dev/ref/template-response/ +[cite]: https://docs.djangoproject.com/en/stable/stable/template-response/ [statuscodes]: status-codes.md diff --git a/docs/api-guide/reverse.md b/docs/api-guide/reverse.md index 35d88e2db..ee0b2054f 100644 --- a/docs/api-guide/reverse.md +++ b/docs/api-guide/reverse.md @@ -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) [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-lazy]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy +[reverse]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse +[reverse-lazy]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 7da619034..95eb05a40 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -281,8 +281,8 @@ A generic view with sections in the class docstring, using single-line style. class UserList(generics.ListCreateAPIView): """ - get: Create a new user. - post: List all the users. + get: List all the users. + post: Create a new user. """ queryset = User.objects.all() serializer_class = UserSerializer @@ -541,5 +541,5 @@ A short description of the meaning and intended usage of the input field. [open-api]: https://openapis.org/ [json-hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html [api-blueprint]: https://apiblueprint.org/ -[static-files]: https://docs.djangoproject.com/en/dev/howto/static-files/ -[named-arguments]: https://docs.djangoproject.com/en/dev/topics/http/urls/#named-groups +[static-files]: https://docs.djangoproject.com/en/stable/howto/static-files/ +[named-arguments]: https://docs.djangoproject.com/en/stable/topics/http/urls/#named-groups diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 290e32f4f..b5aa78875 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -578,16 +578,6 @@ Alternative representations include serializing using hyperlinks, serializing co For full details see the [serializer relations][relations] documentation. -## Inheritance of the 'Meta' class - -The inner `Meta` class on serializers is not inherited from parent classes by default. This is the same behavior as with Django's `Model` and `ModelForm` classes. If you want the `Meta` class to inherit from a parent class you must do so explicitly. For example: - - class AccountSerializer(MyBaseSerializer): - class Meta(MyBaseSerializer.Meta): - model = Account - -Typically we would recommend *not* using inheritance on inner Meta classes, but instead declaring all options explicitly. - ## Customizing field mappings The ModelSerializer class also exposes an API that you can override in order to alter how serializer fields are automatically determined when instantiating the serializer. @@ -1025,6 +1015,40 @@ If any of the validation fails, then the method should raise a `serializers.Vali The `data` argument passed to this method will normally be the value of `request.data`, so the datatype it provides will depend on the parser classes you have configured for your API. +## Serializer Inheritance + +Similar to Django forms, you can extend and reuse serializers through inheritance. This allows you to declare a common set of fields or methods on a parent class that can then be used in a number of serializers. For example, + + class MyBaseSerializer(Serializer): + my_field = serializers.CharField() + + def validate_my_field(self): + ... + + class MySerializer(MyBaseSerializer): + ... + +Like Django's `Model` and `ModelForm` classes, the inner `Meta` class on serializers does not implicitly inherit from it's parents' inner `Meta` classes. If you want the `Meta` class to inherit from a parent class you must do so explicitly. For example: + + class AccountSerializer(MyBaseSerializer): + class Meta(MyBaseSerializer.Meta): + model = Account + +Typically we would recommend *not* using inheritance on inner Meta classes, but instead declaring all options explicitly. + +Additionally, the following caveats apply to serializer inheritance: + +* Normal Python name resolution rules apply. If you have multiple base classes that declare a `Meta` inner class, only the first one will be used. This means the child’s `Meta`, if it exists, otherwise the `Meta` of the first parent, etc. +* It’s possible to declaratively remove a `Field` inherited from a parent class by setting the name to be `None` on the subclass. + + class MyBaseSerializer(ModelSerializer): + my_field = serializers.CharField() + + class MySerializer(MyBaseSerializer): + my_field = None + + However, you can only use this technique to opt out from a field defined declaratively by a parent class; it won’t prevent the `ModelSerializer` from generating a default field. To opt-out from default fields, see [Specifying which fields to include](#specifying-which-fields-to-include). + ## Dynamically modifying fields Once a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the `.fields` attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer. @@ -1112,13 +1136,28 @@ The [dynamic-rest][dynamic-rest] package extends the ModelSerializer and ModelVi The [drf-dynamic-fields][drf-dynamic-fields] package provides a mixin to dynamically limit the fields per serializer to a subset specified by an URL parameter. +## DRF FlexFields + +The [drf-flex-fields][drf-flex-fields] package extends the ModelSerializer and ModelViewSet to provide commonly used functionality for dynamically setting fields and expanding primitive fields to nested models, both from URL parameters and your serializer class definitions. + +## Serializer Extensions + +The [django-rest-framework-serializer-extensions][drf-serializer-extensions] +package provides a collection of tools to DRY up your serializers, by allowing +fields to be defined on a per-view/request basis. Fields can be whitelisted, +blacklisted and child serializers can be optionally expanded. + ## HTML JSON Forms The [html-json-forms][html-json-forms] package provides an algorithm and serializer for processing `
` submissions per the (inactive) [HTML JSON Form specification][json-form-spec]. The serializer facilitates processing of arbitrarily nested JSON structures within HTML. For example, `` will be interpreted as `{"items": [{"id": "5"}]}`. +## DRF-Base64 + +[DRF-Base64][drf-base64] provides a set of field and model serializers that handles the upload of base64-encoded files. + [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion [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/ [django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/ [marshmallow]: https://marshmallow.readthedocs.io/en/latest/ @@ -1129,5 +1168,8 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali [django-hstore]: https://github.com/djangonauts/django-hstore [dynamic-rest]: https://github.com/AltSchool/dynamic-rest [html-json-forms]: https://github.com/wq/html-json-forms +[drf-flex-fields]: https://github.com/rsinger86/drf-flex-fields [json-form-spec]: https://www.w3.org/TR/html-json-forms/ [drf-dynamic-fields]: https://github.com/dbrgn/drf-dynamic-fields +[drf-base64]: https://bitbucket.org/levit_scs/drf_base64 +[drf-serializer-extensions]: https://github.com/evenicoulddoit/django-rest-framework-serializer-extensions diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 58ceeeeb4..a1ea12d6e 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -456,7 +456,7 @@ An integer of 0 or more, that may be used to specify the number of application p 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 [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 diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index de79a1e2f..13c746017 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -205,7 +205,9 @@ Note that the requests client requires you to pass fully qualified URLs. ## `RequestsClient` and working with the database -The `RequestsClient` class is useful if +The `RequestsClient` class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API. + +If you're using `RequestsClient` you'll want to ensure that test setup, and results assertions are performed as regular API calls, rather than interacting with the database models directly. For example, rather than checking that `Customer.objects.count() == 3` you would list the customers endpoint, and ensure that it contains three records. ## Headers & Authentication @@ -373,6 +375,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 -[client]: https://docs.djangoproject.com/en/dev/topics/testing/tools/#the-test-client -[requestfactory]: https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.client.RequestFactory +[client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client +[requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory [configuration]: #configuration diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index da4d5f725..58578a23e 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -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 [permissions]: permissions.md [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-docs]: https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache +[cache-setting]: https://docs.djangoproject.com/en/stable/ref/settings/#caches +[cache-docs]: https://docs.djangoproject.com/en/stable/topics/cache/#setting-up-the-cache diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md index e041e9072..0e58c6fff 100644 --- a/docs/api-guide/validators.md +++ b/docs/api-guide/validators.md @@ -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. 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/ diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 55f6664e0..c0c4f67e4 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -73,6 +73,8 @@ The following methods are used by REST framework to instantiate the various plug ### .get_content_negotiator(self) +### .get_exception_handler(self) + ## API policy implementation methods The following methods are called before dispatching to the handler method. diff --git a/docs/index.md b/docs/index.md index 9b0913f00..b035c4a7c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -73,7 +73,7 @@ The initial aim is to provide a single full-time position on REST framework.
diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index e6220f427..ca4ed2efa 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -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`. [xordoquy]: https://github.com/xordoquy -[django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 -[porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ -[python-compat]: https://docs.djangoproject.com/en/dev/releases/1.5/#python-compatibility -[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy +[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/stable/topics/python3/ +[python-compat]: https://docs.djangoproject.com/en/stable/releases/1.5/#python-compatibility +[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 [mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs diff --git a/docs/topics/2.4-announcement.md b/docs/topics/2.4-announcement.md index 3009daa49..96f68c865 100644 --- a/docs/topics/2.4-announcement.md +++ b/docs/topics/2.4-announcement.md @@ -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! -[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 [view-name-and-description-settings]: ../api-guide/settings#view-names-and-descriptions [client-ip-identification]: ../api-guide/throttling#how-clients-are-identified diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index e6cbf7238..25ab4fd5b 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -870,7 +870,7 @@ The `COMPACT_JSON` setting has been added, and can be used to revert this behavi #### 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: @@ -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 [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 -[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 diff --git a/docs/topics/ajax-csrf-cors.md b/docs/topics/ajax-csrf-cors.md index ad88810da..4960e0881 100644 --- a/docs/topics/ajax-csrf-cors.md +++ b/docs/topics/ajax-csrf-cors.md @@ -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 [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/ [ottoyiu]: https://github.com/ottoyiu/ [django-cors-headers]: https://github.com/ottoyiu/django-cors-headers/ diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index e7d2cde0c..38f365d7d 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -38,6 +38,34 @@ Both this package and DRF docs are fully documented, well supported, and come hi --- +### DRF AutoDocs + +Oleksander Mashianovs' [DRF Auto Docs][drfautodocs-repo] automated api renderer. + +Collects almost all the code you written into documentation effortlessly. + +Supports: + + * functional view docs + * tree-like structure + * Docstrings: + * markdown + * preserve space & newlines + * formatting with nice syntax + * Fields: + * choices rendering + * help_text (to specify SerializerMethodField output, etc) + * smart read_only/required rendering + * Endpoint properties: + * filter_backends + * authentication_classes + * permission_classes + * extra url params(GET params) + +![whole structure](http://joxi.ru/52aBGNI4k3oyA0.jpg) + +--- + #### Apiary There are various other online tools and services for providing API documentation. One notable service is [Apiary][apiary]. With Apiary, you describe your API using a simple markdown-like syntax. The generated documentation includes API interaction, a mock server for testing & prototyping, and various other tools. @@ -109,6 +137,7 @@ To implement a hypermedia API you'll need to decide on an appropriate media type [drfdocs-repo]: https://github.com/ekonstantinidis/django-rest-framework-docs [drfdocs-website]: http://www.drfdocs.com/ [drfdocs-demo]: http://demo.drfdocs.com/ +[drfautodocs-repo]: https://github.com/iMakedonsky/drf-autodocs [django-rest-swagger]: https://github.com/marcgibbons/django-rest-swagger [swagger]: https://developers.helloreverb.com/swagger/ [rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index e5683360b..5628bcaec 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -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 [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 [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 diff --git a/docs/topics/third-party-resources.md b/docs/topics/third-party-resources.md index 1713da1a1..462bd922a 100644 --- a/docs/topics/third-party-resources.md +++ b/docs/topics/third-party-resources.md @@ -189,6 +189,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [djangorestframework-httpsignature][djangorestframework-httpsignature] - Provides an easy to use HTTP Signature Authentication mechanism. * [djoser][djoser] - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. * [django-rest-auth][django-rest-auth] - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. +* [drf-oidc-auth][drf-oidc-auth] - Implements OpenID Connect token authentication for DRF. ### Permissions @@ -203,7 +204,9 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [djangorestframework-gis][djangorestframework-gis] - Geographic add-ons * [djangorestframework-hstore][djangorestframework-hstore] - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature. * [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec. -* [html-json-forms][html-json-forms]: Provides an algorithm and serializer to process HTML JSON Form submissions per the (inactive) spec. +* [html-json-forms][html-json-forms] - Provides an algorithm and serializer to process HTML JSON Form submissions per the (inactive) spec. +* [django-rest-framework-serializer-extensions][drf-serializer-extensions] - + Enables black/whitelisting fields, and conditionally expanding child serializers on a per-view/request basis. ### Serializer fields @@ -365,3 +368,5 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [medium-django-rest-framework]: https://medium.com/django-rest-framework [django-rest-framework-course]: https://teamtreehouse.com/library/django-rest-framework [drf_tweaks]: https://github.com/ArabellaTech/drf_tweaks +[drf-oidc-auth]: https://github.com/ByteInternet/drf-oidc-auth +[drf-serializer-extensions]: https://github.com/evenicoulddoit/django-rest-framework-serializer-extensions diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 96fed2767..e8a4c8ef6 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -118,7 +118,9 @@ We'd also like to set a few global settings. We'd like to turn on pagination, a ) REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',), + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.IsAdminUser', + ], 'PAGE_SIZE': 10 } diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 13b5145ba..f68b5eaf3 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1652,7 +1652,7 @@ class ReadOnlyField(Field): A read-only field that simply returns the field value. If the field is a method with no parameters, the method will be called - and it's return value used as the representation. + and its return value used as the representation. For example, the following would call `get_expiry_date()` on the object: diff --git a/rest_framework/schemas.py b/rest_framework/schemas.py index a882a0fac..fb7d12985 100644 --- a/rest_framework/schemas.py +++ b/rest_framework/schemas.py @@ -453,7 +453,7 @@ class SchemaGenerator(object): current_section, seperator, lead = line.partition(':') sections[current_section] = lead.strip() else: - sections[current_section] += line + '\n' + sections[current_section] += '\n' + line header = getattr(view, 'action', method.lower()) if header in sections: diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 02c24b70e..3556447bb 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -305,7 +305,11 @@ class SerializerMetaclass(type): # in order to maintain the correct order of fields. for base in reversed(bases): if hasattr(base, '_declared_fields'): - fields = list(base._declared_fields.items()) + fields + fields = [ + (field_name, obj) for field_name, obj + in base._declared_fields.items() + if field_name not in attrs + ] + fields return OrderedDict(fields) diff --git a/rest_framework/utils/breadcrumbs.py b/rest_framework/utils/breadcrumbs.py index 74f4f7840..e6e7e3cc3 100644 --- a/rest_framework/utils/breadcrumbs.py +++ b/rest_framework/utils/breadcrumbs.py @@ -28,7 +28,9 @@ def get_breadcrumbs(url, request=None): # Don't list the same view twice in a row. # Probably an optional trailing slash. if not seen or seen[-1] != view: - name = cls().get_view_name() + c = cls() + c.suffix = getattr(view, 'suffix', None) + name = c.get_view_name() insert_url = preserve_builtin_query_params(prefix + url, request) breadcrumbs_list.insert(0, (name, insert_url)) seen.append(view) diff --git a/rest_framework/views.py b/rest_framework/views.py index a8710c7a0..92911e8df 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -286,6 +286,12 @@ class APIView(View): self._negotiator = self.content_negotiation_class() return self._negotiator + def get_exception_handler(self): + """ + Returns the exception handler that this view uses. + """ + return api_settings.EXCEPTION_HANDLER + # API policy implementation methods def perform_content_negotiation(self, request, force=False): @@ -428,7 +434,7 @@ class APIView(View): else: exc.status_code = status.HTTP_403_FORBIDDEN - exception_handler = self.settings.EXCEPTION_HANDLER + exception_handler = self.get_exception_handler() context = self.get_exception_handler_context() response = exception_handler(exc, context) diff --git a/tests/browsable_api/test_browsable_api.py b/tests/browsable_api/test_browsable_api.py index 3d49c353b..684d7ae14 100644 --- a/tests/browsable_api/test_browsable_api.py +++ b/tests/browsable_api/test_browsable_api.py @@ -26,16 +26,19 @@ class DropdownWithAuthTests(TestCase): def test_name_shown_when_logged_in(self): self.client.login(username=self.username, password=self.password) 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): self.client.login(username=self.username, password=self.password) 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): 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') @@ -58,13 +61,16 @@ class NoDropdownWithoutAuthTests(TestCase): def test_name_shown_when_logged_in(self): self.client.login(username=self.username, password=self.password) 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): self.client.login(username=self.username, password=self.password) response = self.client.get('/') - self.assertNotContains(response, '