Skip to content

Commit e221d9a

Browse files
authored
Style notes using admonition in the documentation (#9846)
1 parent 78db4dd commit e221d9a

22 files changed

+211
-302
lines changed

docs/api-guide/authentication.md

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@ The `request.user` property will typically be set to an instance of the `contrib
1919

2020
The `request.auth` property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.
2121

22-
---
23-
24-
**Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with.
22+
!!! note
23+
Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with.
2524

26-
For information on how to set up the permission policies for your API please see the [permissions documentation][permission].
27-
28-
---
25+
For information on how to set up the permission policies for your API please see the [permissions documentation][permission].
2926

3027
## How authentication is determined
3128

@@ -122,17 +119,15 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401
122119

123120
WWW-Authenticate: Basic realm="api"
124121

125-
**Note:** If you use `BasicAuthentication` in production you must ensure that your API is only available over `https`. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.
122+
!!! note
123+
If you use `BasicAuthentication` in production you must ensure that your API is only available over `https`. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.
126124

127125
## TokenAuthentication
128126

129-
---
130-
131-
**Note:** The token authentication provided by Django REST framework is a fairly simple implementation.
127+
!!! note
128+
The token authentication provided by Django REST framework is a fairly simple implementation.
132129

133-
For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the [Django REST Knox][django-rest-knox] third party package.
134-
135-
---
130+
For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the [Django REST Knox][django-rest-knox] third party package.
136131

137132
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
138133

@@ -173,11 +168,8 @@ The `curl` command line tool may be useful for testing token authenticated APIs.
173168

174169
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
175170

176-
---
177-
178-
**Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https`.
179-
180-
---
171+
!!! note
172+
If you use `TokenAuthentication` in production you must ensure that your API is only available over `https`.
181173

182174
### Generating Tokens
183175

@@ -335,11 +327,8 @@ You *may* also override the `.authenticate_header(self, request)` method. If im
335327

336328
If the `.authenticate_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access.
337329

338-
---
339-
340-
**Note:** When your custom authenticator is invoked by the request object's `.user` or `.auth` properties, you may see an `AttributeError` re-raised as a `WrappedAttributeError`. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from your custom authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. These errors should be fixed or otherwise handled by your authenticator.
341-
342-
---
330+
!!! note
331+
When your custom authenticator is invoked by the request object's `.user` or `.auth` properties, you may see an `AttributeError` re-raised as a `WrappedAttributeError`. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from your custom authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. These errors should be fixed or otherwise handled by your authenticator.
343332

344333
## Example
345334

docs/api-guide/caching.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ def get_user_list(request):
8282
```
8383

8484

85-
**NOTE:** The [`cache_page`][page] decorator only caches the
86-
`GET` and `HEAD` responses with status 200.
85+
!!! note
86+
The [`cache_page`][page] decorator only caches the `GET` and `HEAD` responses with status 200.
8787

8888
[page]: https://docs.djangoproject.com/en/stable/topics/cache/#the-per-view-cache
8989
[cookie]: https://docs.djangoproject.com/en/stable/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie

docs/api-guide/content-negotiation.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,11 @@ If the requested view was only configured with renderers for `YAML` and `HTML`,
3434

3535
For more information on the `HTTP Accept` header, see [RFC 2616][accept-header]
3636

37-
---
38-
39-
**Note**: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.
4037

41-
This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.
38+
!!! note
39+
"q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.
4240

43-
---
41+
This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.
4442

4543
# Custom content negotiation
4644

docs/api-guide/fields.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ source:
1111
1212
Serializer fields handle converting between primitive values and internal datatypes. They also deal with validating input values, as well as retrieving and setting the values from their parent objects.
1313

14-
---
15-
16-
**Note:** The serializer fields are declared in `fields.py`, but by convention you should import them using `from rest_framework import serializers` and refer to fields as `serializers.<FieldName>`.
17-
18-
---
14+
!!! note
15+
The serializer fields are declared in `fields.py`, but by convention you should import them using `from rest_framework import serializers` and refer to fields as `serializers.<FieldName>`.
1916

2017
## Core arguments
2118

@@ -565,11 +562,8 @@ The `HiddenField` class is usually only needed if you have some validation that
565562

566563
For further examples on `HiddenField` see the [validators](validators.md) documentation.
567564

568-
---
569-
570-
**Note:** `HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
571-
572-
---
565+
!!! note
566+
`HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
573567

574568
## ModelField
575569

docs/api-guide/generic-views.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,8 @@ For example:
9696
user = self.request.user
9797
return user.accounts.all()
9898

99-
---
100-
101-
**Note:** If the `serializer_class` used in the generic view spans orm relations, leading to an n+1 problem, you could optimize your queryset in this method using `select_related` and `prefetch_related`. To get more information about n+1 problem and use cases of the mentioned methods refer to related section in [django documentation][django-docs-select-related].
102-
103-
---
99+
!!! tip
100+
If the `serializer_class` used in the generic view spans ORM relations, leading to an N+1 problem, you could optimize your queryset in this method using `select_related` and `prefetch_related`. To get more information about N+1 problem and use cases of the mentioned methods refer to related section in [django documentation][django-docs-select-related].
104101

105102
### Avoiding N+1 Queries
106103

docs/api-guide/parsers.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@ REST framework includes a number of built-in Parser classes, that allow you to a
1717

1818
The set of valid parsers for a view is always defined as a list of classes. When `request.data` is accessed, REST framework will examine the `Content-Type` header on the incoming request, and determine which parser to use to parse the request content.
1919

20-
---
21-
22-
**Note**: When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request.
20+
!!! note
21+
When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request.
2322

24-
If you don't set the content type, most clients will default to using `'application/x-www-form-urlencoded'`, which may not be what you wanted.
23+
If you don't set the content type, most clients will default to using `'application/x-www-form-urlencoded'`, which may not be what you want.
2524

26-
As an example, if you are sending `json` encoded data using jQuery with the [.ajax() method][jquery-ajax], you should make sure to include the `contentType: 'application/json'` setting.
27-
28-
---
25+
As an example, if you are sending `json` encoded data using jQuery with the [.ajax() method][jquery-ajax], you should make sure to include the `contentType: 'application/json'` setting.
2926

3027
## Setting the parsers
3128

docs/api-guide/permissions.md

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,15 @@ For example:
5151
self.check_object_permissions(self.request, obj)
5252
return obj
5353

54-
---
55-
56-
**Note**: With the exception of `DjangoObjectPermissions`, the provided
57-
permission classes in `rest_framework.permissions` **do not** implement the
58-
methods necessary to check object permissions.
54+
!!! note
55+
With the exception of `DjangoObjectPermissions`, the provided
56+
permission classes in `rest_framework.permissions` **do not** implement the
57+
methods necessary to check object permissions.
5958

60-
If you wish to use the provided permission classes in order to check object
61-
permissions, **you must** subclass them and implement the
62-
`has_object_permission()` method described in the [_Custom
63-
permissions_](#custom-permissions) section (below).
64-
65-
---
59+
If you wish to use the provided permission classes in order to check object
60+
permissions, **you must** subclass them and implement the
61+
`has_object_permission()` method described in the [_Custom
62+
permissions_](#custom-permissions) section (below).
6663

6764
#### Limitations of object level permissions
6865

@@ -118,7 +115,8 @@ Or, if you're using the `@api_view` decorator with function based views.
118115
}
119116
return Response(content)
120117

121-
__Note:__ when you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the __settings.py__ file.
118+
!!! note
119+
When you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the ``settings.py`` file.
122120

123121
Provided they inherit from `rest_framework.permissions.BasePermission`, permissions can be composed using standard Python bitwise operators. For example, `IsAuthenticatedOrReadOnly` could be written:
124122

@@ -131,17 +129,16 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi
131129
return request.method in SAFE_METHODS
132130

133131
class ExampleView(APIView):
134-
permission_classes = [IsAuthenticated|ReadOnly]
132+
permission_classes = [IsAuthenticated | ReadOnly]
135133

136134
def get(self, request, format=None):
137135
content = {
138136
'status': 'request was permitted'
139137
}
140138
return Response(content)
141139

142-
__Note:__ it supports & (and), | (or) and ~ (not).
143-
144-
---
140+
!!! note
141+
Composition of permissions supports `&` (and), `|` (or) and `~` (not) operators.
145142

146143
# API Reference
147144

@@ -185,7 +182,7 @@ To use custom model permissions, override `DjangoModelPermissions` and set the `
185182

186183
Similar to `DjangoModelPermissions`, but also allows unauthenticated users to have read-only access to the API.
187184

188-
## DjangoObjectPermissions
185+
## DjangoObjectPermissions
189186

190187
This permission class ties into Django's standard [object permissions framework][objectpermissions] that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as [django-guardian][guardian].
191188

@@ -199,11 +196,8 @@ Note that `DjangoObjectPermissions` **does not** require the `django-guardian` p
199196

200197
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.
201198

202-
---
203-
204-
**Note**: If you need object level `view` permissions for `GET`, `HEAD` and `OPTIONS` requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the `DjangoObjectPermissionsFilter` class provided by the [`djangorestframework-guardian` package][django-rest-framework-guardian]. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.
205-
206-
---
199+
!!! note
200+
If you need object level `view` permissions for `GET`, `HEAD` and `OPTIONS` requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the `DjangoObjectPermissionsFilter` class provided by the [`djangorestframework-guardian` package][django-rest-framework-guardian]. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.
207201

208202
# Custom permissions
209203

@@ -221,11 +215,8 @@ If you need to test if a request is a read operation or a write operation, you s
221215
else:
222216
# Check permissions for write request
223217

224-
---
225-
226-
**Note**: The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `.check_object_permissions(request, obj)`. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising `PermissionDenied` on failure.)
227-
228-
---
218+
!!! note
219+
The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `.check_object_permissions(request, obj)`. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising `PermissionDenied` on failure.)
229220

230221
Custom permissions will raise a `PermissionDenied` exception if the test fails. To change the error message associated with the exception, implement a `message` attribute directly on your custom permission. Otherwise the `default_detail` attribute from `PermissionDenied` will be used. Similarly, to change the code identifier associated with the exception, implement a `code` attribute directly on your custom permission - otherwise the `default_code` attribute from `PermissionDenied` will be used.
231222

docs/api-guide/relations.md

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,36 @@ source:
1111
1212
Relational fields are used to represent model relationships. They can be applied to `ForeignKey`, `ManyToManyField` and `OneToOneField` relationships, as well as to reverse relationships, and custom relationships such as `GenericForeignKey`.
1313

14-
---
15-
16-
**Note:** The relational fields are declared in `relations.py`, but by convention you should import them from the `serializers` module, using `from rest_framework import serializers` and refer to fields as `serializers.<FieldName>`.
17-
18-
---
19-
20-
---
21-
22-
**Note:** REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer.
23-
24-
For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:
25-
26-
class AlbumSerializer(serializers.ModelSerializer):
27-
tracks = serializers.SlugRelatedField(
28-
many=True,
29-
read_only=True,
30-
slug_field='title'
31-
)
32-
33-
class Meta:
34-
model = Album
35-
fields = ['album_name', 'artist', 'tracks']
36-
37-
# For each album object, tracks should be fetched from database
38-
qs = Album.objects.all()
39-
print(AlbumSerializer(qs, many=True).data)
40-
41-
If `AlbumSerializer` is used to serialize a fairly large queryset with `many=True` then it could be a serious performance problem. Optimizing the queryset passed to `AlbumSerializer` with:
42-
43-
qs = Album.objects.prefetch_related('tracks')
44-
# No additional database hits required
45-
print(AlbumSerializer(qs, many=True).data)
46-
47-
would solve the issue.
48-
49-
---
14+
!!! note
15+
The relational fields are declared in `relations.py`, but by convention you should import them from the `serializers` module, using `from rest_framework import serializers` and refer to fields as `serializers.<FieldName>`.
16+
17+
!!! note
18+
REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an ORM relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer.
19+
20+
For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:
21+
22+
class AlbumSerializer(serializers.ModelSerializer):
23+
tracks = serializers.SlugRelatedField(
24+
many=True,
25+
read_only=True,
26+
slug_field='title'
27+
)
28+
29+
class Meta:
30+
model = Album
31+
fields = ['album_name', 'artist', 'tracks']
32+
33+
# For each album object, tracks should be fetched from database
34+
qs = Album.objects.all()
35+
print(AlbumSerializer(qs, many=True).data)
36+
37+
If `AlbumSerializer` is used to serialize a fairly large queryset with `many=True` then it could be a serious performance problem. Optimizing the queryset passed to `AlbumSerializer` with:
38+
39+
qs = Album.objects.prefetch_related('tracks')
40+
# No additional database hits required
41+
print(AlbumSerializer(qs, many=True).data)
42+
43+
would solve the issue.
5044

5145
#### Inspecting relationships.
5246

@@ -183,15 +177,12 @@ Would serialize to a representation like this:
183177

184178
By default this field is read-write, although you can change this behavior using the `read_only` flag.
185179

186-
---
180+
!!! note
181+
This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the `lookup_field` and `lookup_url_kwarg` arguments.
187182

188-
**Note**: This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the `lookup_field` and `lookup_url_kwarg` arguments.
183+
This is suitable for URLs that contain a single primary key or slug argument as part of the URL.
189184

190-
This is suitable for URLs that contain a single primary key or slug argument as part of the URL.
191-
192-
If you require more complex hyperlinked representation you'll need to customize the field, as described in the [custom hyperlinked fields](#custom-hyperlinked-fields) section, below.
193-
194-
---
185+
If you require more complex hyperlinked representation you'll need to customize the field, as described in the [custom hyperlinked fields](#custom-hyperlinked-fields) section, below.
195186

196187
**Arguments**:
197188

0 commit comments

Comments
 (0)