Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 12 additions & 23 deletions docs/api-guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions docs/api-guide/caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 3 additions & 5 deletions docs/api-guide/content-negotiation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.
!!! 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.

# Custom content negotiation

Expand Down
14 changes: 4 additions & 10 deletions docs/api-guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
7 changes: 2 additions & 5 deletions docs/api-guide/generic-views.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 4 additions & 7 deletions docs/api-guide/parsers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 wanted.
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.

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

Expand Down
45 changes: 18 additions & 27 deletions docs/api-guide/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:

Expand All @@ -131,17 +129,16 @@ 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 = {
'status': 'request was permitted'
}
return Response(content)

__Note:__ it supports & (and), | (or) and ~ (not).

---
!!! note
Composition of permissions supports `&` (and), `|` (or) and `~` (not) operators.

# API Reference

Expand Down Expand Up @@ -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].

Expand All @@ -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

Expand All @@ -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.

Expand Down
77 changes: 34 additions & 43 deletions docs/api-guide/relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:** 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.

---
!!! 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.

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.

Expand Down Expand Up @@ -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**:

Expand Down
Loading
Loading