Style notes using admonition in the documentation (#9846)

This commit is contained in:
Bruno Alla 2025-12-12 12:53:09 +01:00 committed by GitHub
parent 78db4dd543
commit e221d9a1d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 208 additions and 299 deletions

View File

@ -19,13 +19,10 @@ The `request.user` property will typically be set to an instance of the `contrib
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.
---
!!! 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.
**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.
For information on how to set up the permission policies for your API please see the [permissions documentation][permission].
---
For information on how to set up the permission policies for your API please see the [permissions documentation][permission].
## How authentication is determined
@ -122,17 +119,15 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401
WWW-Authenticate: Basic realm="api"
**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.
!!! 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.
## TokenAuthentication
---
!!! note
The token authentication provided by Django REST framework is a fairly simple implementation.
**Note:** The token authentication provided by Django REST framework is a fairly simple implementation.
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.
---
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.
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.
@ -173,11 +168,8 @@ The `curl` command line tool may be useful for testing token authenticated APIs.
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
---
**Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https`.
---
!!! note
If you use `TokenAuthentication` in production you must ensure that your API is only available over `https`.
### Generating Tokens
@ -335,11 +327,8 @@ You *may* also override the `.authenticate_header(self, request)` method. If im
If the `.authenticate_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access.
---
**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.
---
!!! 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.
## Example

View File

@ -82,8 +82,8 @@ def get_user_list(request):
```
**NOTE:** The [`cache_page`][page] decorator only caches the
`GET` and `HEAD` responses with status 200.
!!! note
The [`cache_page`][page] decorator only caches the `GET` and `HEAD` responses with status 200.
[page]: https://docs.djangoproject.com/en/stable/topics/cache/#the-per-view-cache
[cookie]: https://docs.djangoproject.com/en/stable/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie

View File

@ -34,13 +34,11 @@ If the requested view was only configured with renderers for `YAML` and `HTML`,
For more information on the `HTTP Accept` header, see [RFC 2616][accept-header]
---
**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.
!!! 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.
This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.
---
This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.
# Custom content negotiation

View File

@ -11,11 +11,8 @@ source:
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.
---
**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>`.
---
!!! 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>`.
## Core arguments
@ -565,11 +562,8 @@ The `HiddenField` class is usually only needed if you have some validation that
For further examples on `HiddenField` see the [validators](validators.md) documentation.
---
**Note:** `HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
---
!!! note
`HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
## ModelField

View File

@ -96,11 +96,8 @@ For example:
user = self.request.user
return user.accounts.all()
---
**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].
---
!!! tip
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].
### Avoiding N+1 Queries

View File

@ -17,15 +17,12 @@ REST framework includes a number of built-in Parser classes, that allow you to a
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.
---
!!! note
When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request.
**Note**: When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request.
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.
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.
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.
---
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.
## Setting the parsers

View File

@ -51,18 +51,15 @@ For example:
self.check_object_permissions(self.request, obj)
return obj
---
!!! note
With the exception of `DjangoObjectPermissions`, the provided
permission classes in `rest_framework.permissions` **do not** implement the
methods necessary to check object permissions.
**Note**: With the exception of `DjangoObjectPermissions`, the provided
permission classes in `rest_framework.permissions` **do not** implement the
methods necessary to check object permissions.
If you wish to use the provided permission classes in order to check object
permissions, **you must** subclass them and implement the
`has_object_permission()` method described in the [_Custom
permissions_](#custom-permissions) section (below).
---
If you wish to use the provided permission classes in order to check object
permissions, **you must** subclass them and implement the
`has_object_permission()` method described in the [_Custom
permissions_](#custom-permissions) section (below).
#### Limitations of object level permissions
@ -118,7 +115,8 @@ Or, if you're using the `@api_view` decorator with function based views.
}
return Response(content)
__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.
!!! 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.
Provided they inherit from `rest_framework.permissions.BasePermission`, permissions can be composed using standard Python bitwise operators. For example, `IsAuthenticatedOrReadOnly` could be written:
@ -131,7 +129,7 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi
return request.method in SAFE_METHODS
class ExampleView(APIView):
permission_classes = [IsAuthenticated|ReadOnly]
permission_classes = [IsAuthenticated | ReadOnly]
def get(self, request, format=None):
content = {
@ -139,9 +137,8 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi
}
return Response(content)
__Note:__ it supports & (and), | (or) and ~ (not).
---
!!! note
Composition of permissions supports `&` (and), `|` (or) and `~` (not) operators.
# API Reference
@ -185,7 +182,7 @@ To use custom model permissions, override `DjangoModelPermissions` and set the `
Similar to `DjangoModelPermissions`, but also allows unauthenticated users to have read-only access to the API.
## DjangoObjectPermissions
## DjangoObjectPermissions
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].
@ -199,11 +196,8 @@ Note that `DjangoObjectPermissions` **does not** require the `django-guardian` p
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.
---
**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.
---
!!! 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.
# Custom permissions
@ -221,11 +215,8 @@ If you need to test if a request is a read operation or a write operation, you s
else:
# Check permissions for write request
---
**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.)
---
!!! 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.)
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.

View File

@ -11,42 +11,36 @@ source:
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`.
---
!!! 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>`.
**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>`.
!!! 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.
---
---
**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.
For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
# For each album object, tracks should be fetched from database
qs = Album.objects.all()
print(AlbumSerializer(qs, many=True).data)
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:
qs = Album.objects.prefetch_related('tracks')
# No additional database hits required
print(AlbumSerializer(qs, many=True).data)
would solve the issue.
---
For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
# For each album object, tracks should be fetched from database
qs = Album.objects.all()
print(AlbumSerializer(qs, many=True).data)
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:
qs = Album.objects.prefetch_related('tracks')
# No additional database hits required
print(AlbumSerializer(qs, many=True).data)
would solve the issue.
#### Inspecting relationships.
@ -183,15 +177,12 @@ Would serialize to a representation like this:
By default this field is read-write, although you can change this behavior using the `read_only` flag.
---
!!! 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.
**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.
This is suitable for URLs that contain a single primary key or slug argument as part of the URL.
This is suitable for URLs that contain a single primary key or slug argument as part of the URL.
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.
---
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.
**Arguments**:

View File

@ -103,15 +103,10 @@ Unlike other renderers, the data passed to the `Response` does not need to be se
The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context.
---
!!! 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}
The template name is determined by (in order of preference):
@ -202,13 +197,16 @@ This renderer is suitable for CRUD-style web APIs that should also present a use
Note that views that have nested or list serializers for their input won't work well with the `AdminRenderer`, as the HTML forms are unable to properly support them.
**Note**: The `AdminRenderer` is only able to include links to detail pages when a properly configured `URL_FIELD_NAME` (`url` by default) attribute is present in the data. For `HyperlinkedModelSerializer` this will be the case, but for `ModelSerializer` or plain `Serializer` classes you'll need to make sure to include the field explicitly. For example here we use models `get_absolute_url` method:
!!! note
The `AdminRenderer` is only able to include links to detail pages when a properly configured `URL_FIELD_NAME` (`url` by default) attribute is present in the data. For `HyperlinkedModelSerializer` this will be the case, but for `ModelSerializer` or plain `Serializer` classes you'll need to make sure to include the field explicitly.
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
For example here we use models `get_absolute_url` method:
class Meta:
model = Account
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = Account
**.media_type**: `text/html`
@ -390,9 +388,8 @@ Exceptions raised and handled by an HTML renderer will attempt to render using o
Templates will render with a `RequestContext` which includes the `status_code` and `details` keys.
**Note**: If `DEBUG=True`, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.
---
!!! note
If `DEBUG=True`, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.
# Third party packages

View File

@ -39,13 +39,10 @@ The `APIView` class or `@api_view` decorator will ensure that this property is a
You won't typically need to access this property.
---
!!! note
If a client sends malformed content, then accessing `request.data` may raise a `ParseError`. By default REST framework's `APIView` class or `@api_view` decorator will catch the error and return a `400 Bad Request` response.
**Note:** If a client sends malformed content, then accessing `request.data` may raise a `ParseError`. By default REST framework's `APIView` class or `@api_view` decorator will catch the error and return a `400 Bad Request` response.
If a client sends a request with a content-type that cannot be parsed then a `UnsupportedMediaType` exception will be raised, which by default will be caught and return a `415 Unsupported Media Type` response.
---
If a client sends a request with a content-type that cannot be parsed then a `UnsupportedMediaType` exception will be raised, which by default will be caught and return a `415 Unsupported Media Type` response.
# Content negotiation
@ -91,11 +88,8 @@ The `APIView` class or `@api_view` decorator will ensure that this property is a
You won't typically need to access this property.
---
**Note:** You may see a `WrappedAttributeError` raised when calling the `.user` or `.auth` properties. These errors originate from an authenticator as a standard `AttributeError`, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from the authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. The authenticator will need to be fixed.
---
!!! note
You may see a `WrappedAttributeError` raised when calling the `.user` or `.auth` properties. These errors originate from an authenticator as a standard `AttributeError`, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from the authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. The authenticator will need to be fixed.
# Browser enhancements

View File

@ -40,17 +40,14 @@ The example above would generate the following URL patterns:
* URL pattern: `^accounts/$` Name: `'account-list'`
* URL pattern: `^accounts/{pk}/$` Name: `'account-detail'`
---
!!! note
The `basename` argument is used to specify the initial part of the view name pattern. In the example above, that's the `user` or `account` part.
**Note**: The `basename` argument is used to specify the initial part of the view name pattern. In the example above, that's the `user` or `account` part.
Typically you won't *need* to specify the `basename` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have a `.queryset` attribute set. If you try to register that viewset you'll see an error like this:
Typically you won't *need* to specify the `basename` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have a `.queryset` attribute set. If you try to register that viewset you'll see an error like this:
'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
This means you'll need to explicitly set the `basename` argument when registering the viewset, as it could not be automatically determined from the model name.
---
This means you'll need to explicitly set the `basename` argument when registering the viewset, as it could not be automatically determined from the model name.
### Using `include` with routers
@ -91,16 +88,13 @@ Or both an application and instance namespace:
See Django's [URL namespaces docs][url-namespace-docs] and the [`include` API reference][include-api-reference] for more details.
---
**Note**: If using namespacing with hyperlinked serializers you'll also need to ensure that any `view_name` parameters
on the serializers correctly reflect the namespace. In the examples above you'd need to include a parameter such as
`view_name='app_name:user-detail'` for serializer fields hyperlinked to the user detail view.
The automatic `view_name` generation uses a pattern like `%(model_name)-detail`. Unless your models names actually clash
you may be better off **not** namespacing your Django REST Framework views when using hyperlinked serializers.
---
!!! note
If using namespacing with hyperlinked serializers you'll also need to ensure that any `view_name` parameters
on the serializers correctly reflect the namespace. In the examples above you'd need to include a parameter such as
`view_name='app_name:user-detail'` for serializer fields hyperlinked to the user detail view.
The automatic `view_name` generation uses a pattern like `%(model_name)-detail`. Unless your models names actually clash
you may be better off **not** namespacing your Django REST Framework views when using hyperlinked serializers.
### Routing for extra actions

View File

@ -238,15 +238,12 @@ operation = auto_schema.get_operation(...)
In compiling the schema, `SchemaGenerator` calls `get_components()` and
`get_operation()` for each view, allowed method, and path.
----
**Note**: The automatic introspection of components, and many operation
parameters relies on the relevant attributes and methods of
`GenericAPIView`: `get_serializer()`, `pagination_class`, `filter_backends`,
etc. For basic `APIView` subclasses, default introspection is essentially limited to
the URL kwarg path parameters for this reason.
----
!!! note
The automatic introspection of components, and many operation
parameters relies on the relevant attributes and methods of
`GenericAPIView`: `get_serializer()`, `pagination_class`, `filter_backends`,
etc. For basic `APIView` subclasses, default introspection is essentially limited to
the URL kwarg path parameters for this reason.
`AutoSchema` encapsulates the view introspection needed for schema generation.
Because of this all the schema generation logic is kept in a single place,

View File

@ -192,11 +192,8 @@ Your `validate_<field_name>` methods should return the validated value or raise
raise serializers.ValidationError("Blog post is not about Django")
return value
---
**Note:** If your `<field_name>` is declared on your serializer with the parameter `required=False` then this validation step will not take place if the field is not included.
---
!!! note
If your `<field_name>` is declared on your serializer with the parameter `required=False` then this validation step will not take place if the field is not included.
#### Object-level validation
@ -542,20 +539,16 @@ This option should be a list or tuple of field names, and is declared as follows
Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option.
---
!!! note
There is a special-case where a read-only field is part of a `unique_together` constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.
**Note**: There is a special-case where a read-only field is part of a `unique_together` constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.
The right way to deal with this is to specify the field explicitly on the serializer, providing both the `read_only=True` and `default=…` keyword arguments.
The right way to deal with this is to specify the field explicitly on the serializer, providing both the `read_only=True` and `default=…` keyword arguments.
One example of this is a read-only relation to the currently authenticated `User` which is `unique_together` with another identifier. In this case you would declare the user field like so:
One example of this is a read-only relation to the currently authenticated `User` which is `unique_together` with another identifier. In this case you would declare the user field like so:
user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
Please review the [Validators Documentation](/api-guide/validators/) for details on the [UniqueTogetherValidator](/api-guide/validators/#uniquetogethervalidator) and [CurrentUserDefault](/api-guide/validators/#currentuserdefault) classes.
---
user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
Please review the [Validators Documentation](/api-guide/validators/) for details on the [UniqueTogetherValidator](/api-guide/validators/#uniquetogethervalidator) and [CurrentUserDefault](/api-guide/validators/#currentuserdefault) classes.
## Additional keyword arguments

View File

@ -90,36 +90,32 @@ For example, when forcibly authenticating using a token, you might do something
request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user, token=user.auth_token)
---
!!! note
`force_authenticate` directly sets `request.user` to the in-memory `user` instance. If you are reusing the same `user` instance across multiple tests that update the saved `user` state, you may need to call [`refresh_from_db()`][refresh_from_db_docs] between tests.
**Note**: `force_authenticate` directly sets `request.user` to the in-memory `user` instance. If you are reusing the same `user` instance across multiple tests that update the saved `user` state, you may need to call [`refresh_from_db()`][refresh_from_db_docs] between tests.
!!! note
When using `APIRequestFactory`, the object that is returned is Django's standard `HttpRequest`, and not REST framework's `Request` object, which is only generated once the view is called.
---
**Note**: When using `APIRequestFactory`, the object that is returned is Django's standard `HttpRequest`, and not REST framework's `Request` object, which is only generated once the view is called.
This means that setting attributes directly on the request object may not always have the effect you expect. For example, setting `.token` directly will have no effect, and setting `.user` directly will only work if session authentication is being used.
# Request will only authenticate if `SessionAuthentication` is in use.
request = factory.get('/accounts/django-superstars/')
request.user = user
response = view(request)
If you want to test a request involving the REST frameworks 'Request' object, youll need to manually transform it first:
class DummyView(APIView):
...
factory = APIRequestFactory()
request = factory.get('/', {'demo': 'test'})
drf_request = DummyView().initialize_request(request)
assert drf_request.query_params == {'demo': ['test']}
request = factory.post('/', {'example': 'test'})
drf_request = DummyView().initialize_request(request)
assert drf_request.data.get('example') == 'test'
---
This means that setting attributes directly on the request object may not always have the effect you expect. For example, setting `.token` directly will have no effect, and setting `.user` directly will only work if session authentication is being used.
# Request will only authenticate if `SessionAuthentication` is in use.
request = factory.get('/accounts/django-superstars/')
request.user = user
response = view(request)
If you want to test a request involving the REST frameworks 'Request' object, youll need to manually transform it first:
class DummyView(APIView):
...
factory = APIRequestFactory()
request = factory.get('/', {'demo': 'test'})
drf_request = DummyView().initialize_request(request)
assert drf_request.query_params == {'demo': ['test']}
request = factory.post('/', {'example': 'test'})
drf_request = DummyView().initialize_request(request)
assert drf_request.data.get('example') == 'test'
## Forcing CSRF validation
@ -127,11 +123,8 @@ By default, requests created with `APIRequestFactory` will not have CSRF validat
factory = APIRequestFactory(enforce_csrf_checks=True)
---
**Note**: It's worth noting that Django's standard `RequestFactory` doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.
---
!!! note
It's worth noting that Django's standard `RequestFactory` doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.
# APIClient

View File

@ -101,11 +101,8 @@ The validator should be applied to *serializer classes*, like so:
)
]
---
**Note**: The `UniqueTogetherValidator` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
---
!!! note
The `UniqueTogetherValidator` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
## UniqueForDateValidator
@ -158,24 +155,19 @@ If you want the date field to be entirely hidden from the user, then use `Hidden
published = serializers.HiddenField(default=timezone.now)
---
!!! note
The `UniqueFor<Range>Validator` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
**Note**: The `UniqueFor<Range>Validator` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
---
---
**Note:** `HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
---
!!! note
`HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
# Advanced field defaults
Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that *is* available as input to the validator.
For this purposes use `HiddenField`. This field will be present in `validated_data` but *will not* be used in the serializer output representation.
**Note:** Using a `read_only=True` field is excluded from writable fields so it won't use a `default=…` argument. Look [3.8 announcement](https://www.django-rest-framework.org/community/3.8-announcement/#altered-the-behavior-of-read_only-plus-default-on-field).
!!! note
Using a `read_only=True` field is excluded from writable fields so it won't use a `default=…` argument. Look [3.8 announcement](https://www.django-rest-framework.org/community/3.8-announcement/#altered-the-behavior-of-read_only-plus-default-on-field).
REST framework includes a couple of defaults that may be useful in this context.

View File

@ -45,11 +45,8 @@ For example:
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
---
**Note**: The full methods, attributes on, and relations between Django REST Framework's `APIView`, `GenericAPIView`, various `Mixins`, and `Viewsets` can be initially complex. In addition to the documentation here, the [Classy Django REST Framework][classy-drf] resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views.
---
!!! note
The full methods, attributes on, and relations between Django REST Framework's `APIView`, `GenericAPIView`, various `Mixins`, and `Viewsets` can be initially complex. In addition to the documentation here, the [Classy Django REST Framework][classy-drf] resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views.
## API policy attributes

View File

@ -131,7 +131,8 @@ You may inspect these attributes to adjust behavior based on the current action.
permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes]
**Note**: the `action` attribute is not available in the `get_parsers`, `get_authenticators` and `get_content_negotiator` methods, as it is set _after_ they are called in the framework lifecycle. If you override one of these methods and try to access the `action` attribute in them, you will get an `AttributeError` error.
!!! note
The `action` attribute is not available in the `get_parsers`, `get_authenticators` and `get_content_negotiator` methods, as it is set _after_ they are called in the framework lifecycle. If you override one of these methods and try to access the `action` attribute in them, you will get an `AttributeError` error.
## Marking extra actions for routing

View File

@ -81,32 +81,29 @@ To run the tests, clone the repository, and then:
# Run the tests
./runtests.py
---
!!! tip
If your tests require access to the database, do not forget to inherit from `django.test.TestCase` or use the `@pytest.mark.django_db()` decorator.
**Note:** if your tests require access to the database, do not forget to inherit from `django.test.TestCase` or use the `@pytest.mark.django_db()` decorator.
For example, with TestCase:
from django.test import TestCase
class MyDatabaseTest(TestCase):
def test_something(self):
# Your test code here
pass
Or with decorator:
import pytest
@pytest.mark.django_db()
class MyDatabaseTest:
def test_something(self):
# Your test code here
pass
You can reuse existing models defined in `tests/models.py` for your tests.
---
For example, with TestCase:
from django.test import TestCase
class MyDatabaseTest(TestCase):
def test_something(self):
# Your test code here
pass
Or with decorator:
import pytest
@pytest.mark.django_db()
class MyDatabaseTest:
def test_something(self):
# Your test code here
pass
You can reuse existing models defined in `tests/models.py` for your tests.
### Test options
@ -133,7 +130,8 @@ Shorter form to run the tests for a given test method.
./runtests.py test_this_method
Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.
!!! note
The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.
### Running against multiple environments
@ -225,13 +223,12 @@ Linking in this style means you'll be able to click the hyperlink in your Markdo
##### 3. Notes
If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:
If you want to draw attention to a note or warning, use an [admonition], like so:
---
!!! note
A useful documentation note.
**Note:** A useful documentation note.
---
The documentation theme styles `info`, `warning`, `tip` and `danger` admonition types, but more could be added if the need arise.
[cite]: https://www.w3.org/People/Berners-Lee/FAQ.html
@ -247,3 +244,4 @@ If you want to draw attention to a note or warning, use a pair of enclosing line
[mou]: http://mouapp.com/
[repo]: https://github.com/encode/django-rest-framework
[how-to-fork]: https://help.github.com/articles/fork-a-repo/
[admonition]: https://python-markdown.github.io/extensions/admonition/

View File

@ -6,11 +6,8 @@ This tutorial will cover creating a simple pastebin code highlighting Web API.
The tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the [quickstart] documentation instead.
---
**Note**: The code for this tutorial is available in the [encode/rest-framework-tutorial][repo] repository on GitHub. Feel free to clone the repository and see the code in action.
---
!!! note
The code for this tutorial is available in the [encode/rest-framework-tutorial][repo] repository on GitHub. Feel free to clone the repository and see the code in action.
## Setting up a new environment
@ -29,7 +26,8 @@ pip install djangorestframework
pip install pygments # We'll be using this for the code highlighting
```
**Note:** To exit the virtual environment at any time, just type `deactivate`. For more information see the [venv documentation][venv].
!!! tip
To exit the virtual environment at any time, just type `deactivate`. For more information see the [venv documentation][venv].
## Getting started

View File

@ -135,7 +135,8 @@ Now that snippets are associated with the user that created them, let's update o
owner = serializers.ReadOnlyField(source="owner.username")
```
**Note**: Make sure you also add `'owner',` to the list of fields in the inner `Meta` class.
!!! note
Make sure you also add `'owner',` to the list of fields in the inner `Meta` class.
This field is doing something quite interesting. The `source` argument controls which attribute is used to populate a field, and can point at any attribute on the serialized instance. It can also take the dotted notation shown above, in which case it will traverse the given attributes, in a similar way as it is used with Django's template language.

View File

@ -120,25 +120,16 @@ Notice that we've also added a new `'highlight'` field. This field is of the sa
Because we've included format suffixed URLs such as `'.json'`, we also need to indicate on the `highlight` field that any format suffixed hyperlinks it returns should use the `'.html'` suffix.
---
!!! note
When you are manually instantiating these serializers inside your views (e.g., in `SnippetDetail` or `SnippetList`), you **must** pass `context={'request': request}` so the serializer knows how to build absolute URLs. For example, instead of:
**Note:**
serializer = SnippetSerializer(snippet)
You must write:
When you are manually instantiating these serializers inside your views (e.g., in `SnippetDetail` or `SnippetList`), you **must** pass `context={'request': request}` so the serializer knows how to build absolute URLs. For example, instead of:
```python
serializer = SnippetSerializer(snippet)
```
You must write:
```python
serializer = SnippetSerializer(snippet, context={"request": request})
```
If your view is a subclass of `GenericAPIView`, you may use the `get_serializer_context()` as a convenience method.
---
serializer = SnippetSerializer(snippet, context={"request": request})
If your view is a subclass of `GenericAPIView`, you may use the `get_serializer_context()` as a convenience method.
## Making sure our URL patterns are named

View File

@ -452,6 +452,12 @@ ul.sponsor {
margin: 0 -.6rem 1em;
padding: 0.4rem 0.6rem;
}
.admonition.tip {
border: .075rem solid #1e8d21;
}
.admonition.tip .admonition-title {
background: #1e8d211a;
}
.admonition.warning {
border: .075rem solid #ff9844;
}