Docs: fix code block style

This commit is contained in:
Shyamkumar Yadav 2022-10-15 13:41:31 +05:30
parent 9407833a83
commit 3fa4affce2
12 changed files with 269 additions and 343 deletions

View File

@ -16,7 +16,6 @@ decorators with class based views. This can be used with
other cache decorators such as [`cache_page`][page], other cache decorators such as [`cache_page`][page],
[`vary_on_cookie`][cookie] and [`vary_on_headers`][headers]. [`vary_on_cookie`][cookie] and [`vary_on_headers`][headers].
```python
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie, vary_on_headers from django.views.decorators.vary import vary_on_cookie, vary_on_headers
@ -57,7 +56,6 @@ class PostView(APIView):
'body': 'Post content' 'body': 'Post content'
} }
return Response(content) return Response(content)
```
**NOTE:** The [`cache_page`][page] decorator only caches the **NOTE:** The [`cache_page`][page] decorator only caches the
`GET` and `HEAD` responses with status 200. `GET` and `HEAD` responses with status 200.

View File

@ -107,9 +107,7 @@ The TemplateHTMLRenderer will create a `RequestContext`, using the `response.dat
**Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the TemplateHTMLRenderer to render it. For example: **Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the TemplateHTMLRenderer to render it. For example:
```
response.data = {'results': response.data} response.data = {'results': response.data}
```
--- ---

View File

@ -48,9 +48,7 @@ The following sections explain more.
If your schema is static, you can use the `generateschema` management command: If your schema is static, you can use the `generateschema` management command:
```bash
./manage.py generateschema --file openapi-schema.yml ./manage.py generateschema --file openapi-schema.yml
```
Once you've generated a schema in this way you can annotate it with any Once you've generated a schema in this way you can annotate it with any
additional information that cannot be automatically inferred by the schema additional information that cannot be automatically inferred by the schema
@ -69,7 +67,6 @@ To route a `SchemaView`, use the `get_schema_view()` helper.
In `urls.py`: In `urls.py`:
```python
from rest_framework.schemas import get_schema_view from rest_framework.schemas import get_schema_view
urlpatterns = [ urlpatterns = [
@ -84,7 +81,6 @@ urlpatterns = [
), name='openapi-schema'), ), name='openapi-schema'),
# ... # ...
] ]
```
#### `get_schema_view()` #### `get_schema_view()`
@ -139,9 +135,7 @@ The `get_schema_view()` helper takes the following keyword arguments:
**Schema-level customization** **Schema-level customization**
```python
from rest_framework.schemas.openapi import SchemaGenerator from rest_framework.schemas.openapi import SchemaGenerator
```
`SchemaGenerator` is a class that walks a list of routed URL patterns, requests `SchemaGenerator` is a class that walks a list of routed URL patterns, requests
the schema for each view and collates the resulting OpenAPI schema. the schema for each view and collates the resulting OpenAPI schema.
@ -179,21 +173,17 @@ This is a good point to override if you want to customize the generated
dictionary For example you might wish to add terms of service to the [top-level dictionary For example you might wish to add terms of service to the [top-level
`info` object][info-object]: `info` object][info-object]:
```
class TOSSchemaGenerator(SchemaGenerator): class TOSSchemaGenerator(SchemaGenerator):
def get_schema(self, *args, **kwargs): def get_schema(self, *args, **kwargs):
schema = super().get_schema(*args, **kwargs) schema = super().get_schema(*args, **kwargs)
schema["info"]["termsOfService"] = "https://example.com/tos.html" schema["info"]["termsOfService"] = "https://example.com/tos.html"
return schema return schema
```
## AutoSchema ## AutoSchema
**Per-View Customization** **Per-View Customization**
```python
from rest_framework.schemas.openapi import AutoSchema from rest_framework.schemas.openapi import AutoSchema
```
By default, view introspection is performed by an `AutoSchema` instance By default, view introspection is performed by an `AutoSchema` instance
accessible via the `schema` attribute on `APIView`. accessible via the `schema` attribute on `APIView`.
@ -209,10 +199,8 @@ and path:
the endpoint, including path and query parameters for pagination, filtering, the endpoint, including path and query parameters for pagination, filtering,
and so on. and so on.
```python
components = auto_schema.get_components(...) components = auto_schema.get_components(...)
operation = auto_schema.get_operation(...) operation = auto_schema.get_operation(...)
```
In compiling the schema, `SchemaGenerator` calls `get_components()` and In compiling the schema, `SchemaGenerator` calls `get_components()` and
`get_operation()` for each view, allowed method, and path. `get_operation()` for each view, allowed method, and path.
@ -236,7 +224,6 @@ Keeping with this pattern, try not to let schema logic leak into your own
views, serializers, or fields when customizing the schema generation. You might views, serializers, or fields when customizing the schema generation. You might
be tempted to do something like this: be tempted to do something like this:
```python
class CustomSchema(AutoSchema): class CustomSchema(AutoSchema):
""" """
AutoSchema subclass using schema_extra_info on the view. AutoSchema subclass using schema_extra_info on the view.
@ -246,7 +233,6 @@ class CustomSchema(AutoSchema):
class CustomView(APIView): class CustomView(APIView):
schema = CustomSchema() schema = CustomSchema()
schema_extra_info = ... some extra info ... schema_extra_info = ... some extra info ...
```
Here, the `AutoSchema` subclass goes looking for `schema_extra_info` on the Here, the `AutoSchema` subclass goes looking for `schema_extra_info` on the
view. This is _OK_ (it doesn't actually hurt) but it means you'll end up with view. This is _OK_ (it doesn't actually hurt) but it means you'll end up with
@ -255,7 +241,6 @@ your schema logic spread out in a number of different places.
Instead try to subclass `AutoSchema` such that the `extra_info` doesn't leak Instead try to subclass `AutoSchema` such that the `extra_info` doesn't leak
out into the view: out into the view:
```python
class BaseSchema(AutoSchema): class BaseSchema(AutoSchema):
""" """
AutoSchema subclass that knows how to use extra_info. AutoSchema subclass that knows how to use extra_info.
@ -267,7 +252,6 @@ class CustomSchema(BaseSchema):
class CustomView(APIView): class CustomView(APIView):
schema = CustomSchema() schema = CustomSchema()
```
This style is slightly more verbose but maintains the encapsulation of the This style is slightly more verbose but maintains the encapsulation of the
schema related code. It's more _cohesive_ in the _parlance_. It'll keep the schema related code. It's more _cohesive_ in the _parlance_. It'll keep the
@ -277,7 +261,6 @@ If an option applies to many view classes, rather than creating a specific
subclass per-view, you may find it more convenient to allow specifying the subclass per-view, you may find it more convenient to allow specifying the
option as an `__init__()` kwarg to your base `AutoSchema` subclass: option as an `__init__()` kwarg to your base `AutoSchema` subclass:
```python
class CustomSchema(BaseSchema): class CustomSchema(BaseSchema):
def __init__(self, **kwargs): def __init__(self, **kwargs):
# store extra_info for later # store extra_info for later
@ -288,7 +271,6 @@ class CustomView(APIView):
schema = CustomSchema( schema = CustomSchema(
extra_info=... some extra info ... extra_info=... some extra info ...
) )
```
This saves you having to create a custom subclass per-view for a commonly used option. This saves you having to create a custom subclass per-view for a commonly used option.
@ -333,7 +315,6 @@ will handle the default fields that Django REST Framework provides.
For `SerializerMethodField` instances, for which the schema is unknown, or custom field subclasses you should override `map_field()` to generate the correct schema: For `SerializerMethodField` instances, for which the schema is unknown, or custom field subclasses you should override `map_field()` to generate the correct schema:
```python
class CustomSchema(AutoSchema): class CustomSchema(AutoSchema):
"""Extension of ``AutoSchema`` to add support for custom field schemas.""" """Extension of ``AutoSchema`` to add support for custom field schemas."""
@ -341,7 +322,6 @@ class CustomSchema(AutoSchema):
# Handle SerializerMethodFields or custom fields here... # Handle SerializerMethodFields or custom fields here...
# ... # ...
return super().map_field(field) return super().map_field(field)
```
Authors of third-party packages should aim to provide an `AutoSchema` subclass, Authors of third-party packages should aim to provide an `AutoSchema` subclass,
and a mixin, overriding `map_field()` so that users can easily generate schemas and a mixin, overriding `map_field()` so that users can easily generate schemas
@ -407,7 +387,6 @@ The available kwargs are:
You pass the kwargs when declaring the `AutoSchema` instance on your view: You pass the kwargs when declaring the `AutoSchema` instance on your view:
```
class PetDetailView(generics.RetrieveUpdateDestroyAPIView): class PetDetailView(generics.RetrieveUpdateDestroyAPIView):
schema = AutoSchema( schema = AutoSchema(
tags=['Pets'], tags=['Pets'],
@ -415,7 +394,6 @@ class PetDetailView(generics.RetrieveUpdateDestroyAPIView):
operation_id_base='Pet', operation_id_base='Pet',
) )
... ...
```
Assuming a `Pet` model and `PetSerializer` serializer, the kwargs in this Assuming a `Pet` model and `PetSerializer` serializer, the kwargs in this
example are probably not needed. Often, though, you'll need to pass the kwargs example are probably not needed. Often, though, you'll need to pass the kwargs

View File

@ -193,7 +193,6 @@ To view all extra actions, call the `.get_extra_actions()` method.
Extra actions can map additional HTTP methods to separate `ViewSet` methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments. Extra actions can map additional HTTP methods to separate `ViewSet` methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments.
```python
@action(detail=True, methods=['put'], name='Change Password') @action(detail=True, methods=['put'], name='Change Password')
def password(self, request, pk=None): def password(self, request, pk=None):
"""Update the user's password.""" """Update the user's password."""
@ -203,7 +202,6 @@ Extra actions can map additional HTTP methods to separate `ViewSet` methods. For
def delete_password(self, request, pk=None): def delete_password(self, request, pk=None):
"""Delete the user's password.""" """Delete the user's password."""
... ...
```
## Reversing action URLs ## Reversing action URLs
@ -213,17 +211,13 @@ Note that the `basename` is provided by the router during `ViewSet` registration
Using the example from the previous section: Using the example from the previous section:
```python
>>> view.reverse_action('set-password', args=['1']) >>> view.reverse_action('set-password', args=['1'])
'http://localhost:8000/api/users/1/set_password' 'http://localhost:8000/api/users/1/set_password'
```
Alternatively, you can use the `url_name` attribute set by the `@action` decorator. Alternatively, you can use the `url_name` attribute set by the `@action` decorator.
```python
>>> view.reverse_action(view.set_password.url_name, args=['1']) >>> view.reverse_action(view.set_password.url_name, args=['1'])
'http://localhost:8000/api/users/1/set_password' 'http://localhost:8000/api/users/1/set_password'
```
The `url_name` argument for `.reverse_action()` should match the same argument to the `@action` decorator. Additionally, this method can be used to reverse the default actions, such as `list` and `create`. The `url_name` argument for `.reverse_action()` should match the same argument to the `@action` decorator. Additionally, this method can be used to reverse the default actions, such as `list` and `create`.

View File

@ -39,12 +39,10 @@ update your REST framework settings to include `DEFAULT_SCHEMA_CLASS` explicitly
**settings.py**: **settings.py**:
```python
REST_FRAMEWORK = { REST_FRAMEWORK = {
... ...
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
} }
```
You'll still be able to keep using CoreAPI schemas, API docs, and client for the You'll still be able to keep using CoreAPI schemas, API docs, and client for the
foreseeable future. We'll aim to ensure that the CoreAPI schema generator remains foreseeable future. We'll aim to ensure that the CoreAPI schema generator remains
@ -66,7 +64,6 @@ shortcut.
In your `urls.py`: In your `urls.py`:
```python
from rest_framework.schemas import get_schema_view from rest_framework.schemas import get_schema_view
urlpatterns = [ urlpatterns = [
@ -80,7 +77,6 @@ urlpatterns = [
), name='openapi-schema'), ), name='openapi-schema'),
# ... # ...
] ]
```
### Customization ### Customization

View File

@ -41,7 +41,6 @@ include:
In this example view operation descriptions for the `get` and `post` methods will In this example view operation descriptions for the `get` and `post` methods will
be extracted from the class docstring: be extracted from the class docstring:
```python
class DocStringExampleListView(APIView): class DocStringExampleListView(APIView):
""" """
get: A description of my GET operation. get: A description of my GET operation.
@ -54,7 +53,6 @@ post: A description of my POST operation.
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
... ...
```
## Validator / Default Context ## Validator / Default Context
@ -71,23 +69,19 @@ The `__call__` method should then include an additional `serializer_field` argum
Validator implementations will look like this: Validator implementations will look like this:
```python
class CustomValidator: class CustomValidator:
requires_context = True requires_context = True
def __call__(self, value, serializer_field): def __call__(self, value, serializer_field):
... ...
```
Default implementations will look like this: Default implementations will look like this:
```python
class CustomDefault: class CustomDefault:
requires_context = True requires_context = True
def __call__(self, serializer_field): def __call__(self, serializer_field):
... ...
```
--- ---

View File

@ -39,11 +39,9 @@ Method | Path | Tags
The tags used for a particular view may also be overridden... The tags used for a particular view may also be overridden...
```python
class MyOrders(APIView): class MyOrders(APIView):
schema = AutoSchema(tags=['users', 'orders']) schema = AutoSchema(tags=['users', 'orders'])
... ...
```
See [the schema documentation](https://www.django-rest-framework.org/api-guide/schemas/#grouping-operations-with-tags) for more information. See [the schema documentation](https://www.django-rest-framework.org/api-guide/schemas/#grouping-operations-with-tags) for more information.
@ -66,10 +64,8 @@ The names used for a component default to using the serializer class name, [but
may be overridden if needed](https://www.django-rest-framework.org/api-guide/schemas/#components may be overridden if needed](https://www.django-rest-framework.org/api-guide/schemas/#components
)... )...
```python
class MyOrders(APIView): class MyOrders(APIView):
schema = AutoSchema(component_name="OrderDetails") schema = AutoSchema(component_name="OrderDetails")
```
## More Public API ## More Public API
@ -111,7 +107,6 @@ The class now supports nested search within `JSONField` and `HStoreField`, using
the double underscore notation for traversing which element of the field the the double underscore notation for traversing which element of the field the
search should apply to. search should apply to.
```python
class SitesSearchView(generics.ListAPIView): class SitesSearchView(generics.ListAPIView):
""" """
An API view to return a list of archaeological sites, optionally filtered An API view to return a list of archaeological sites, optionally filtered
@ -122,14 +117,12 @@ class SitesSearchView(generics.ListAPIView):
serializer_class = SitesSerializer serializer_class = SitesSerializer
filter_backends = [filters.SearchFilter] filter_backends = [filters.SearchFilter]
search_fields = ['site_name', 'location__region', 'location__country'] search_fields = ['site_name', 'location__region', 'location__country']
```
### Searches against annotate fields ### Searches against annotate fields
Django allows querysets to create additional virtual fields, using the `.annotate` Django allows querysets to create additional virtual fields, using the `.annotate`
method. We now support searching against annotate fields. method. We now support searching against annotate fields.
```python
class PublisherSearchView(generics.ListAPIView): class PublisherSearchView(generics.ListAPIView):
""" """
Search for publishers, optionally filtering the search against the average Search for publishers, optionally filtering the search against the average
@ -139,7 +132,6 @@ class PublisherSearchView(generics.ListAPIView):
serializer_class = PublisherSerializer serializer_class = PublisherSerializer
filter_backends = [filters.SearchFilter] filter_backends = [filters.SearchFilter]
search_fields = ['avg_rating'] search_fields = ['avg_rating']
```
--- ---

View File

@ -40,15 +40,11 @@ From REST framework 3.13 onwards, this is now *explicitly enforced*.
The most feasible cases where users might be accidentally omitting the keyword arguments The most feasible cases where users might be accidentally omitting the keyword arguments
are likely in the composite fields, `ListField` and `DictField`. For instance... are likely in the composite fields, `ListField` and `DictField`. For instance...
```python
aliases = serializers.ListField(serializers.CharField()) aliases = serializers.ListField(serializers.CharField())
```
They must now use the more explicit keyword argument style... They must now use the more explicit keyword argument style...
```python
aliases = serializers.ListField(child=serializers.CharField()) aliases = serializers.ListField(child=serializers.CharField())
```
This change has been made because using positional arguments here *does not* result in the expected behaviour. This change has been made because using positional arguments here *does not* result in the expected behaviour.

View File

@ -59,7 +59,6 @@ For example, to include a swagger schema to your API, you would do the following
* Include the schema view in your URL conf: * Include the schema view in your URL conf:
```py
from rest_framework.schemas import get_schema_view from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
@ -72,7 +71,6 @@ urlpatterns = [
path('swagger/', schema_view), path('swagger/', schema_view),
... ...
] ]
```
There have been a large number of fixes to the schema generation. These should There have been a large number of fixes to the schema generation. These should
resolve issues for anyone using the latest version of the `django-rest-swagger` resolve issues for anyone using the latest version of the `django-rest-swagger`

View File

@ -59,7 +59,6 @@ the schema into your repository.
Here's an example of adding an OpenAPI schema to the URL conf: Here's an example of adding an OpenAPI schema to the URL conf:
```python
from rest_framework.schemas import get_schema_view from rest_framework.schemas import get_schema_view
from rest_framework.renderers import JSONOpenAPIRenderer from rest_framework.renderers import JSONOpenAPIRenderer
from django.urls import path from django.urls import path
@ -74,13 +73,10 @@ urlpatterns = [
path('schema.json', schema_view), path('schema.json', schema_view),
... ...
] ]
```
And here's how you can use the `generateschema` management command: And here's how you can use the `generateschema` management command:
```shell
$ python manage.py generateschema --format openapi > schema.yml $ python manage.py generateschema --format openapi > schema.yml
```
There's lots of different tooling that you can use for working with OpenAPI There's lots of different tooling that you can use for working with OpenAPI
schemas. One option that we're working on is the [API Star](https://docs.apistar.com/) schemas. One option that we're working on is the [API Star](https://docs.apistar.com/)
@ -88,17 +84,13 @@ command line tool.
You can use `apistar` to validate your API schema: You can use `apistar` to validate your API schema:
```shell
$ apistar validate --path schema.json --format openapi $ apistar validate --path schema.json --format openapi
✓ Valid OpenAPI schema. ✓ Valid OpenAPI schema.
```
Or to build API documentation: Or to build API documentation:
```shell
$ apistar docs --path schema.json --format openapi $ apistar docs --path schema.json --format openapi
✓ Documentation built at "build/index.html". ✓ Documentation built at "build/index.html".
```
API Star also includes a [dynamic client library](https://docs.apistar.com/client-library/) API Star also includes a [dynamic client library](https://docs.apistar.com/client-library/)
that uses an API schema to automatically provide a client library interface for making requests. that uses an API schema to automatically provide a client library interface for making requests.
@ -109,9 +101,7 @@ You can now compose permission classes using the and/or operators, `&` and `|`.
For example... For example...
```python
permission_classes = [IsAuthenticated & (ReadOnly | IsAdminUser)] permission_classes = [IsAuthenticated & (ReadOnly | IsAdminUser)]
```
If you're using custom permission classes then make sure that you are subclassing If you're using custom permission classes then make sure that you are subclassing
from `BasePermission` in order to enable this support. from `BasePermission` in order to enable this support.

View File

@ -301,12 +301,12 @@ Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10.
* Deprecate the `Router.get_default_base_name` method in favor of `Router.get_default_basename`. [#5990][gh5990] * Deprecate the `Router.get_default_base_name` method in favor of `Router.get_default_basename`. [#5990][gh5990]
* Change `CharField` to disallow null bytes. [#6073][gh6073] * Change `CharField` to disallow null bytes. [#6073][gh6073]
To revert to the old behavior, subclass `CharField` and remove `ProhibitNullCharactersValidator` from the validators. To revert to the old behavior, subclass `CharField` and remove `ProhibitNullCharactersValidator` from the validators.
```python
class NullableCharField(serializers.CharField): class NullableCharField(serializers.CharField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)] self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]
```
* Add `OpenAPIRenderer` and `generate_schema` management command. [#6229][gh6229] * Add `OpenAPIRenderer` and `generate_schema` management command. [#6229][gh6229]
* Add OpenAPIRenderer by default, and add schema docs. [#6233][gh6233] * Add OpenAPIRenderer by default, and add schema docs. [#6233][gh6233]
* Allow permissions to be composed [#5753][gh5753] * Allow permissions to be composed [#5753][gh5753]

View File

@ -25,7 +25,6 @@ Assuming you've followed the example from the schemas documentation for routing
a dynamic `SchemaView`, a minimal Django template for using Swagger UI might be a dynamic `SchemaView`, a minimal Django template for using Swagger UI might be
this: this:
```html
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -54,12 +53,10 @@ this:
</script> </script>
</body> </body>
</html> </html>
```
Save this in your templates folder as `swagger-ui.html`. Then route a Save this in your templates folder as `swagger-ui.html`. Then route a
`TemplateView` in your project's URL conf: `TemplateView` in your project's URL conf:
```python
from django.views.generic import TemplateView from django.views.generic import TemplateView
urlpatterns = [ urlpatterns = [
@ -71,7 +68,6 @@ urlpatterns = [
extra_context={'schema_url':'openapi-schema'} extra_context={'schema_url':'openapi-schema'}
), name='swagger-ui'), ), name='swagger-ui'),
] ]
```
See the [Swagger UI documentation][swagger-ui] for advanced usage. See the [Swagger UI documentation][swagger-ui] for advanced usage.
@ -81,7 +77,6 @@ Assuming you've followed the example from the schemas documentation for routing
a dynamic `SchemaView`, a minimal Django template for using ReDoc might be a dynamic `SchemaView`, a minimal Django template for using ReDoc might be
this: this:
```html
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -103,12 +98,10 @@ this:
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script> <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body> </body>
</html> </html>
```
Save this in your templates folder as `redoc.html`. Then route a `TemplateView` Save this in your templates folder as `redoc.html`. Then route a `TemplateView`
in your project's URL conf: in your project's URL conf:
```python
from django.views.generic import TemplateView from django.views.generic import TemplateView
urlpatterns = [ urlpatterns = [
@ -120,7 +113,6 @@ urlpatterns = [
extra_context={'schema_url':'openapi-schema'} extra_context={'schema_url':'openapi-schema'}
), name='redoc'), ), name='redoc'),
] ]
```
See the [ReDoc documentation][redoc] for advanced usage. See the [ReDoc documentation][redoc] for advanced usage.