diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 2cb29d5f8..51a6c00c6 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -765,10 +765,21 @@ Valid only if a `location="body"` field is included on the `Link`. A short description of the meaning and intended usage of the input field. +--- + +# Third party packages + +## DRF OpenAPI + +[DRF OpenAPI][drf-openapi] renders the schema generated by Django Rest Framework +in [OpenAPI][open-api] format. + + [cite]: https://blog.heroku.com/archives/2014/1/8/json_schema_for_heroku_platform_api [coreapi]: http://www.coreapi.org/ [corejson]: http://www.coreapi.org/specification/encoding/#core-json-encoding [open-api]: https://openapis.org/ +[drf-openapi]: https://github.com/limdauto/drf_openapi [json-hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html [api-blueprint]: https://apiblueprint.org/ [static-files]: https://docs.djangoproject.com/en/stable/howto/static-files/ diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index e95f2849b..515e7cad8 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -993,7 +993,7 @@ The following class is an example of a generic serializer that can handle coerci ## Overriding serialization and deserialization behavior -If you need to alter the serialization, deserialization or validation of a serializer class you can do so by overriding the `.to_representation()` or `.to_internal_value()` methods. +If you need to alter the serialization or deserialization behavior of a serializer class, you can do so by overriding the `.to_representation()` or `.to_internal_value()` methods. Some reasons this might be useful include... @@ -1011,7 +1011,7 @@ Takes the object instance that requires serialization, and should return a primi Takes the unvalidated incoming data as input and should return the validated data that will be made available as `serializer.validated_data`. The return value will also be passed to the `.create()` or `.update()` methods if `.save()` is called on the serializer class. -If any of the validation fails, then the method should raise a `serializers.ValidationError(errors)`. Typically the `errors` argument here will be a dictionary mapping field names to error messages. +If any of the validation fails, then the method should raise a `serializers.ValidationError(errors)`. The `errors` argument should be a dictionary mapping field names (or `settings.NON_FIELD_ERRORS_KEY`) to a list of error messages. If you don't need to alter deserialization behavior and instead want to provide object-level validation, it's recommended that you intead override the [`.validate()`](#object-level-validation) method. 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. @@ -1155,7 +1155,7 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali ## QueryFields -[djangorestframework-queryfields][djangorestframework-queryfields] allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters. +[djangorestframework-queryfields][djangorestframework-queryfields] allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters. ## DRF Writable Nested diff --git a/docs/img/drf-openapi.png b/docs/img/drf-openapi.png new file mode 100644 index 000000000..7a37e19d6 Binary files /dev/null and b/docs/img/drf-openapi.png differ diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index da1dbe358..b68eb64ec 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -75,6 +75,23 @@ When using viewsets, you should use the relevant action names as delimiters. There are a number of mature third-party packages for providing API documentation. +#### DRF OpenAPI + +[DRF OpenAPI][drf-openapi] bridges the gap between OpenAPI specification and tool chain with the schema exposed +out-of-the-box by Django Rest Framework. Its goals are: + + * To be dropped into any existing DRF project without any code change necessary. + * Provide clear disctinction between request schema and response schema. + * Provide a versioning mechanism for each schema. Support defining schema by version range syntax, e.g. >1.0, <=2.0 + * Support multiple response codes, not just 200 + * All this information should be bound to view methods, not view classes. + +It also tries to stay current with the maturing schema generation mechanism provided by DRF. + +![Screenshot - DRF OpenAPI][image-drf-openapi] + +--- + #### DRF Docs [DRF Docs][drfdocs-repo] allows you to document Web APIs made with Django REST Framework and it is authored by Emmanouil Konstantinidis. It's made to work out of the box and its setup should not take more than a couple of minutes. Complete documentation can be found on the [website][drfdocs-website] while there is also a [demo][drfdocs-demo] available for people to see what it looks like. **Live API Endpoints** allow you to utilize the endpoints from within the documentation in a neat way. @@ -197,6 +214,8 @@ In this approach, rather than documenting the available API endpoints up front, To implement a hypermedia API you'll need to decide on an appropriate media type for the API, and implement a custom renderer and parser for that media type. The [REST, Hypermedia & HATEOAS][hypermedia-docs] section of the documentation includes pointers to background reading, as well as links to various hypermedia formats. [cite]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven +[drf-openapi]: https://github.com/limdauto/drf_openapi/ +[image-drf-openapi]: ../img/drf-openapi.png [drfdocs-repo]: https://github.com/ekonstantinidis/django-rest-framework-docs [drfdocs-website]: http://www.drfdocs.com/ [drfdocs-demo]: http://demo.drfdocs.com/ diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index 6189c7771..252021e39 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -26,6 +26,7 @@ Here we've used the `ReadOnlyModelViewSet` class to automatically provide the de Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighlight` view classes. We can remove the three views, and again replace them with a single class. from rest_framework.decorators import detail_route + from rest_framework.response import Response class SnippetViewSet(viewsets.ModelViewSet): """ diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 614745a66..abf1d7136 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -252,6 +252,7 @@ try: md = markdown.Markdown( extensions=extensions, extension_configs=extension_configs ) + md_filter_add_syntax_highlight(md) return md.convert(text) except ImportError: apply_markdown = None @@ -281,6 +282,38 @@ except ImportError: def pygments_css(style): return None +if markdown is not None and pygments is not None: + # starting from this blogpost and modified to support current markdown extensions API + # https://zerokspot.com/weblog/2008/06/18/syntax-highlighting-in-markdown-with-pygments/ + + from markdown.preprocessors import Preprocessor + import re + + class CodeBlockPreprocessor(Preprocessor): + pattern = re.compile( + r'^\s*@@ (.+?) @@\s*(.+?)^\s*@@', re.M|re.S) + + formatter = HtmlFormatter() + + def run(self, lines): + def repl(m): + try: + lexer = get_lexer_by_name(m.group(1)) + except (ValueError, NameError): + lexer = TextLexer() + code = m.group(2).replace('\t',' ') + code = pygments.highlight(code, lexer, self.formatter) + code = code.replace('\n\n', '\n \n').replace('\n', '
').replace('\\@','@') + return '\n\n%s\n\n' % code + ret = self.pattern.sub(repl, "\n".join(lines)) + return ret.split("\n") + + def md_filter_add_syntax_highlight(md): + md.preprocessors.add('highlight', CodeBlockPreprocessor(), "_begin") + return True +else: + def md_filter_add_syntax_highlight(md): + return False try: import pytz diff --git a/rest_framework/templates/rest_framework/docs/document.html b/rest_framework/templates/rest_framework/docs/document.html index 7a438f68d..7922142f3 100644 --- a/rest_framework/templates/rest_framework/docs/document.html +++ b/rest_framework/templates/rest_framework/docs/document.html @@ -13,8 +13,8 @@ {% if 'javascript' in langs %}{% include "rest_framework/docs/langs/javascript-intro.html" %}{% endif %} -{% if document.data %} -{% for section_key, section in document.data|items %} +{% if document|data %} +{% for section_key, section in document|data|items %} {% if section_key %}

{{ section_key }}

diff --git a/rest_framework/templates/rest_framework/docs/sidebar.html b/rest_framework/templates/rest_framework/docs/sidebar.html index 31708e784..d23787025 100644 --- a/rest_framework/templates/rest_framework/docs/sidebar.html +++ b/rest_framework/templates/rest_framework/docs/sidebar.html @@ -5,8 +5,8 @@