mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 08:14:16 +03:00
Update docs to use lists instead of tuples (#6797)
This commit is contained in:
parent
5c922fb39d
commit
f0dbf0a264
10
README.md
10
README.md
|
@ -67,10 +67,10 @@ Install using `pip`...
|
||||||
|
|
||||||
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
|
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
)
|
]
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ from rest_framework import serializers, viewsets, routers
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('url', 'username', 'email', 'is_staff')
|
fields = ['url', 'username', 'email', 'is_staff']
|
||||||
|
|
||||||
|
|
||||||
# ViewSets define the view behavior.
|
# ViewSets define the view behavior.
|
||||||
|
@ -123,10 +123,10 @@ We'd also like to configure a couple of settings for our API.
|
||||||
Add the following to your `settings.py` module:
|
Add the following to your `settings.py` module:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
... # Make sure to include the default installed apps here.
|
... # Make sure to include the default installed apps here.
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
)
|
]
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
# Use Django's standard `django.contrib.auth` permissions,
|
# Use Django's standard `django.contrib.auth` permissions,
|
||||||
|
|
|
@ -40,10 +40,10 @@ The value of `request.user` and `request.auth` for unauthenticated requests can
|
||||||
The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example.
|
The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||||
'rest_framework.authentication.BasicAuthentication',
|
'rest_framework.authentication.BasicAuthentication',
|
||||||
'rest_framework.authentication.SessionAuthentication',
|
'rest_framework.authentication.SessionAuthentication',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
You can also set the authentication scheme on a per-view or per-viewset basis,
|
You can also set the authentication scheme on a per-view or per-viewset basis,
|
||||||
|
@ -55,8 +55,8 @@ using the `APIView` class-based views.
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
class ExampleView(APIView):
|
class ExampleView(APIView):
|
||||||
authentication_classes = (SessionAuthentication, BasicAuthentication)
|
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
content = {
|
content = {
|
||||||
|
@ -68,8 +68,8 @@ using the `APIView` class-based views.
|
||||||
Or, if you're using the `@api_view` decorator with function based views.
|
Or, if you're using the `@api_view` decorator with function based views.
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@authentication_classes((SessionAuthentication, BasicAuthentication))
|
@authentication_classes([SessionAuthentication, BasicAuthentication])
|
||||||
@permission_classes((IsAuthenticated,))
|
@permission_classes([IsAuthenticated])
|
||||||
def example_view(request, format=None):
|
def example_view(request, format=None):
|
||||||
content = {
|
content = {
|
||||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||||
|
@ -124,10 +124,10 @@ This authentication scheme uses a simple token-based HTTP Authentication scheme.
|
||||||
|
|
||||||
To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting:
|
To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting:
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'rest_framework.authtoken'
|
'rest_framework.authtoken'
|
||||||
)
|
]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ It is also possible to create Tokens manually through admin interface. In case y
|
||||||
|
|
||||||
from rest_framework.authtoken.admin import TokenAdmin
|
from rest_framework.authtoken.admin import TokenAdmin
|
||||||
|
|
||||||
TokenAdmin.raw_id_fields = ('user',)
|
TokenAdmin.raw_id_fields = ['user']
|
||||||
|
|
||||||
|
|
||||||
#### Using Django manage.py command
|
#### Using Django manage.py command
|
||||||
|
@ -367,15 +367,15 @@ Install using `pip`.
|
||||||
|
|
||||||
Add the package to your `INSTALLED_APPS` and modify your REST framework settings.
|
Add the package to your `INSTALLED_APPS` and modify your REST framework settings.
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'oauth2_provider',
|
'oauth2_provider',
|
||||||
)
|
]
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||||
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
|
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
For more details see the [Django REST framework - Getting started][django-oauth-toolkit-getting-started] documentation.
|
For more details see the [Django REST framework - Getting started][django-oauth-toolkit-getting-started] documentation.
|
||||||
|
|
|
@ -526,7 +526,7 @@ For example, if `has_expired` was a property on the `Account` model, then the fo
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'has_expired')
|
fields = ['id', 'account_name', 'has_expired']
|
||||||
|
|
||||||
## HiddenField
|
## HiddenField
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ Generic filters can also present themselves as HTML controls in the browsable AP
|
||||||
The default filter backends may be set globally, using the `DEFAULT_FILTER_BACKENDS` setting. For example.
|
The default filter backends may be set globally, using the `DEFAULT_FILTER_BACKENDS` setting. For example.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
|
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
|
||||||
}
|
}
|
||||||
|
|
||||||
You can also set the filter backends on a per-view, or per-viewset basis,
|
You can also set the filter backends on a per-view, or per-viewset basis,
|
||||||
|
@ -109,7 +109,7 @@ using the `GenericAPIView` class-based views.
|
||||||
class UserListView(generics.ListAPIView):
|
class UserListView(generics.ListAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
|
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
|
||||||
|
|
||||||
## Filtering and object lookups
|
## Filtering and object lookups
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ To use `DjangoFilterBackend`, first install `django-filter`. Then add `django_fi
|
||||||
You should now either add the filter backend to your settings:
|
You should now either add the filter backend to your settings:
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
|
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
|
||||||
}
|
}
|
||||||
|
|
||||||
Or add the filter backend to an individual View or ViewSet.
|
Or add the filter backend to an individual View or ViewSet.
|
||||||
|
@ -161,15 +161,15 @@ Or add the filter backend to an individual View or ViewSet.
|
||||||
|
|
||||||
class UserListView(generics.ListAPIView):
|
class UserListView(generics.ListAPIView):
|
||||||
...
|
...
|
||||||
filter_backends = (DjangoFilterBackend,)
|
filter_backends = [DjangoFilterBackend]
|
||||||
|
|
||||||
If all you need is simple equality-based filtering, you can set a `filterset_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against.
|
If all you need is simple equality-based filtering, you can set a `filterset_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against.
|
||||||
|
|
||||||
class ProductList(generics.ListAPIView):
|
class ProductList(generics.ListAPIView):
|
||||||
queryset = Product.objects.all()
|
queryset = Product.objects.all()
|
||||||
serializer_class = ProductSerializer
|
serializer_class = ProductSerializer
|
||||||
filter_backends = (DjangoFilterBackend,)
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ('category', 'in_stock')
|
filterset_fields = ['category', 'in_stock']
|
||||||
|
|
||||||
This will automatically create a `FilterSet` class for the given fields, and will allow you to make requests such as:
|
This will automatically create a `FilterSet` class for the given fields, and will allow you to make requests such as:
|
||||||
|
|
||||||
|
@ -195,8 +195,8 @@ The `SearchFilter` class will only be applied if the view has a `search_fields`
|
||||||
class UserListView(generics.ListAPIView):
|
class UserListView(generics.ListAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
filter_backends = (filters.SearchFilter,)
|
filter_backends = [filters.SearchFilter]
|
||||||
search_fields = ('username', 'email')
|
search_fields = ['username', 'email']
|
||||||
|
|
||||||
This will allow the client to filter the items in the list by making queries such as:
|
This will allow the client to filter the items in the list by making queries such as:
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ This will allow the client to filter the items in the list by making queries suc
|
||||||
|
|
||||||
You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:
|
You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:
|
||||||
|
|
||||||
search_fields = ('username', 'email', 'profile__profession')
|
search_fields = ['username', 'email', 'profile__profession']
|
||||||
|
|
||||||
By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.
|
By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ The search behavior may be restricted by prepending various characters to the `s
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
search_fields = ('=username', '=email')
|
search_fields = ['=username', '=email']
|
||||||
|
|
||||||
By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting.
|
By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting.
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ To dynamically change search fields based on request content, it's possible to s
|
||||||
class CustomSearchFilter(filters.SearchFilter):
|
class CustomSearchFilter(filters.SearchFilter):
|
||||||
def get_search_fields(self, view, request):
|
def get_search_fields(self, view, request):
|
||||||
if request.query_params.get('title_only'):
|
if request.query_params.get('title_only'):
|
||||||
return ('title',)
|
return ['title']
|
||||||
return super(CustomSearchFilter, self).get_search_fields(view, request)
|
return super(CustomSearchFilter, self).get_search_fields(view, request)
|
||||||
|
|
||||||
For more details, see the [Django documentation][search-django-admin].
|
For more details, see the [Django documentation][search-django-admin].
|
||||||
|
@ -262,8 +262,8 @@ It's recommended that you explicitly specify which fields the API should allowin
|
||||||
class UserListView(generics.ListAPIView):
|
class UserListView(generics.ListAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
filter_backends = (filters.OrderingFilter,)
|
filter_backends = [filters.OrderingFilter]
|
||||||
ordering_fields = ('username', 'email')
|
ordering_fields = ['username', 'email']
|
||||||
|
|
||||||
This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.
|
This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ If you are confident that the queryset being used by the view doesn't contain an
|
||||||
class BookingsListView(generics.ListAPIView):
|
class BookingsListView(generics.ListAPIView):
|
||||||
queryset = Booking.objects.all()
|
queryset = Booking.objects.all()
|
||||||
serializer_class = BookingSerializer
|
serializer_class = BookingSerializer
|
||||||
filter_backends = (filters.OrderingFilter,)
|
filter_backends = [filters.OrderingFilter]
|
||||||
ordering_fields = '__all__'
|
ordering_fields = '__all__'
|
||||||
|
|
||||||
### Specifying a default ordering
|
### Specifying a default ordering
|
||||||
|
@ -286,9 +286,9 @@ Typically you'd instead control this by setting `order_by` on the initial querys
|
||||||
class UserListView(generics.ListAPIView):
|
class UserListView(generics.ListAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
filter_backends = (filters.OrderingFilter,)
|
filter_backends = [filters.OrderingFilter]
|
||||||
ordering_fields = ('username', 'email')
|
ordering_fields = ['username', 'email']
|
||||||
ordering = ('username',)
|
ordering = ['username']
|
||||||
|
|
||||||
The `ordering` attribute may be either a string or a list/tuple of strings.
|
The `ordering` attribute may be either a string or a list/tuple of strings.
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ Example:
|
||||||
|
|
||||||
When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example:
|
When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example:
|
||||||
|
|
||||||
@api_view(('GET', 'POST'))
|
@api_view(['GET', 'POST'])
|
||||||
def comment_list(request, format=None):
|
def comment_list(request, format=None):
|
||||||
# do stuff...
|
# do stuff...
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,14 @@ Typically when using the generic views, you'll override the view, and set severa
|
||||||
class UserList(generics.ListCreateAPIView):
|
class UserList(generics.ListCreateAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
permission_classes = (IsAdminUser,)
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
For more complex cases you might also want to override various methods on the view class. For example.
|
For more complex cases you might also want to override various methods on the view class. For example.
|
||||||
|
|
||||||
class UserList(generics.ListCreateAPIView):
|
class UserList(generics.ListCreateAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
permission_classes = (IsAdminUser,)
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
def list(self, request):
|
def list(self, request):
|
||||||
# Note the use of `get_queryset()` instead of `self.queryset`
|
# Note the use of `get_queryset()` instead of `self.queryset`
|
||||||
|
@ -123,12 +123,12 @@ Given a queryset, filter it with whichever filter backends are in use, returning
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
def filter_queryset(self, queryset):
|
||||||
filter_backends = (CategoryFilter,)
|
filter_backends = [CategoryFilter]
|
||||||
|
|
||||||
if 'geo_route' in self.request.query_params:
|
if 'geo_route' in self.request.query_params:
|
||||||
filter_backends = (GeoRouteFilter, CategoryFilter)
|
filter_backends = [GeoRouteFilter, CategoryFilter]
|
||||||
elif 'geo_point' in self.request.query_params:
|
elif 'geo_point' in self.request.query_params:
|
||||||
filter_backends = (GeoPointFilter, CategoryFilter)
|
filter_backends = [GeoPointFilter, CategoryFilter]
|
||||||
|
|
||||||
for backend in list(filter_backends):
|
for backend in list(filter_backends):
|
||||||
queryset = backend().filter_queryset(self.request, queryset, view=self)
|
queryset = backend().filter_queryset(self.request, queryset, view=self)
|
||||||
|
@ -342,7 +342,7 @@ You can then simply apply this mixin to a view or viewset anytime you need to ap
|
||||||
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
|
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
lookup_fields = ('account', 'username')
|
lookup_fields = ['account', 'username']
|
||||||
|
|
||||||
Using custom mixins is a good option if you have custom behavior that needs to be used.
|
Using custom mixins is a good option if you have custom behavior that needs to be used.
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,9 @@ As an example, if you are sending `json` encoded data using jQuery with the [.aj
|
||||||
The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow only requests with `JSON` content, instead of the default of JSON or form data.
|
The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow only requests with `JSON` content, instead of the default of JSON or form data.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework.parsers.JSONParser',
|
'rest_framework.parsers.JSONParser',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
You can also set the parsers used for an individual view, or viewset,
|
You can also set the parsers used for an individual view, or viewset,
|
||||||
|
@ -48,7 +48,7 @@ using the `APIView` class-based views.
|
||||||
"""
|
"""
|
||||||
A view that can accept POST requests with JSON content.
|
A view that can accept POST requests with JSON content.
|
||||||
"""
|
"""
|
||||||
parser_classes = (JSONParser,)
|
parser_classes = [JSONParser]
|
||||||
|
|
||||||
def post(self, request, format=None):
|
def post(self, request, format=None):
|
||||||
return Response({'received data': request.data})
|
return Response({'received data': request.data})
|
||||||
|
@ -60,7 +60,7 @@ Or, if you're using the `@api_view` decorator with function based views.
|
||||||
from rest_framework.parsers import JSONParser
|
from rest_framework.parsers import JSONParser
|
||||||
|
|
||||||
@api_view(['POST'])
|
@api_view(['POST'])
|
||||||
@parser_classes((JSONParser,))
|
@parser_classes([JSONParser])
|
||||||
def example_view(request, format=None):
|
def example_view(request, format=None):
|
||||||
"""
|
"""
|
||||||
A view that can accept POST requests with JSON content.
|
A view that can accept POST requests with JSON content.
|
||||||
|
@ -113,7 +113,7 @@ If it is called without a `filename` URL keyword argument, then the client must
|
||||||
|
|
||||||
# views.py
|
# views.py
|
||||||
class FileUploadView(views.APIView):
|
class FileUploadView(views.APIView):
|
||||||
parser_classes = (FileUploadParser,)
|
parser_classes = [FileUploadParser]
|
||||||
|
|
||||||
def put(self, request, filename, format=None):
|
def put(self, request, filename, format=None):
|
||||||
file_obj = request.data['file']
|
file_obj = request.data['file']
|
||||||
|
@ -189,12 +189,12 @@ Install using pip.
|
||||||
Modify your REST framework settings.
|
Modify your REST framework settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework_yaml.parsers.YAMLParser',
|
'rest_framework_yaml.parsers.YAMLParser',
|
||||||
),
|
],
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework_yaml.renderers.YAMLRenderer',
|
'rest_framework_yaml.renderers.YAMLRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
## XML
|
## XML
|
||||||
|
@ -210,12 +210,12 @@ Install using pip.
|
||||||
Modify your REST framework settings.
|
Modify your REST framework settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework_xml.parsers.XMLParser',
|
'rest_framework_xml.parsers.XMLParser',
|
||||||
),
|
],
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework_xml.renderers.XMLRenderer',
|
'rest_framework_xml.renderers.XMLRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
## MessagePack
|
## MessagePack
|
||||||
|
|
|
@ -75,16 +75,16 @@ Often when you're using object level permissions you'll also want to [filter the
|
||||||
The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example.
|
The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PERMISSION_CLASSES': (
|
'DEFAULT_PERMISSION_CLASSES': [
|
||||||
'rest_framework.permissions.IsAuthenticated',
|
'rest_framework.permissions.IsAuthenticated',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
If not specified, this setting defaults to allowing unrestricted access:
|
If not specified, this setting defaults to allowing unrestricted access:
|
||||||
|
|
||||||
'DEFAULT_PERMISSION_CLASSES': (
|
'DEFAULT_PERMISSION_CLASSES': [
|
||||||
'rest_framework.permissions.AllowAny',
|
'rest_framework.permissions.AllowAny',
|
||||||
)
|
]
|
||||||
|
|
||||||
You can also set the authentication policy on a per-view, or per-viewset basis,
|
You can also set the authentication policy on a per-view, or per-viewset basis,
|
||||||
using the `APIView` class-based views.
|
using the `APIView` class-based views.
|
||||||
|
@ -94,7 +94,7 @@ using the `APIView` class-based views.
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
class ExampleView(APIView):
|
class ExampleView(APIView):
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
content = {
|
content = {
|
||||||
|
@ -109,7 +109,7 @@ Or, if you're using the `@api_view` decorator with function based views.
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@permission_classes((IsAuthenticated, ))
|
@permission_classes([IsAuthenticated])
|
||||||
def example_view(request, format=None):
|
def example_view(request, format=None):
|
||||||
content = {
|
content = {
|
||||||
'status': 'request was permitted'
|
'status': 'request was permitted'
|
||||||
|
@ -129,7 +129,7 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi
|
||||||
return request.method in SAFE_METHODS
|
return request.method in SAFE_METHODS
|
||||||
|
|
||||||
class ExampleView(APIView):
|
class ExampleView(APIView):
|
||||||
permission_classes = (IsAuthenticated|ReadOnly,)
|
permission_classes = [IsAuthenticated|ReadOnly]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
content = {
|
content = {
|
||||||
|
|
|
@ -46,7 +46,7 @@ In order to explain the various types of relational fields, we'll use a couple o
|
||||||
duration = models.IntegerField()
|
duration = models.IntegerField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('album', 'order')
|
unique_together = ['album', 'order']
|
||||||
ordering = ['order']
|
ordering = ['order']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -63,7 +63,7 @@ For example, the following serializer.
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
Would serialize to the following representation.
|
Would serialize to the following representation.
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ For example, the following serializer:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
Would serialize to a representation like this:
|
Would serialize to a representation like this:
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ For example, the following serializer:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
Would serialize to a representation like this:
|
Would serialize to a representation like this:
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ For example, the following serializer:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
Would serialize to a representation like this:
|
Would serialize to a representation like this:
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ This field can be applied as an identity relationship, such as the `'url'` field
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'track_listing')
|
fields = ['album_name', 'artist', 'track_listing']
|
||||||
|
|
||||||
Would serialize to a representation like this:
|
Would serialize to a representation like this:
|
||||||
|
|
||||||
|
@ -256,14 +256,14 @@ For example, the following serializer:
|
||||||
class TrackSerializer(serializers.ModelSerializer):
|
class TrackSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Track
|
model = Track
|
||||||
fields = ('order', 'title', 'duration')
|
fields = ['order', 'title', 'duration']
|
||||||
|
|
||||||
class AlbumSerializer(serializers.ModelSerializer):
|
class AlbumSerializer(serializers.ModelSerializer):
|
||||||
tracks = TrackSerializer(many=True, read_only=True)
|
tracks = TrackSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
Would serialize to a nested representation like this:
|
Would serialize to a nested representation like this:
|
||||||
|
|
||||||
|
@ -294,14 +294,14 @@ By default nested serializers are read-only. If you want to support write-operat
|
||||||
class TrackSerializer(serializers.ModelSerializer):
|
class TrackSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Track
|
model = Track
|
||||||
fields = ('order', 'title', 'duration')
|
fields = ['order', 'title', 'duration']
|
||||||
|
|
||||||
class AlbumSerializer(serializers.ModelSerializer):
|
class AlbumSerializer(serializers.ModelSerializer):
|
||||||
tracks = TrackSerializer(many=True)
|
tracks = TrackSerializer(many=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
tracks_data = validated_data.pop('tracks')
|
tracks_data = validated_data.pop('tracks')
|
||||||
|
@ -355,7 +355,7 @@ For example, we could define a relational field to serialize a track to a custom
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('album_name', 'artist', 'tracks')
|
fields = ['album_name', 'artist', 'tracks']
|
||||||
|
|
||||||
This custom field would then serialize to the following representation.
|
This custom field would then serialize to the following representation.
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ Note that reverse relationships are not automatically included by the `ModelSeri
|
||||||
|
|
||||||
class AlbumSerializer(serializers.ModelSerializer):
|
class AlbumSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('tracks', ...)
|
fields = ['tracks', ...]
|
||||||
|
|
||||||
You'll normally want to ensure that you've set an appropriate `related_name` argument on the relationship, that you can use as the field name. For example:
|
You'll normally want to ensure that you've set an appropriate `related_name` argument on the relationship, that you can use as the field name. For example:
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ If you have not set a related name for the reverse relationship, you'll need to
|
||||||
|
|
||||||
class AlbumSerializer(serializers.ModelSerializer):
|
class AlbumSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('track_set', ...)
|
fields = ['track_set', ...]
|
||||||
|
|
||||||
See the Django documentation on [reverse relationships][reverse-relationships] for more details.
|
See the Django documentation on [reverse relationships][reverse-relationships] for more details.
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ For more information see the documentation on [content negotiation][conneg].
|
||||||
The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CLASSES` setting. For example, the following settings would use `JSON` as the main media type and also include the self describing API.
|
The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CLASSES` setting. For example, the following settings would use `JSON` as the main media type and also include the self describing API.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework.renderers.JSONRenderer',
|
'rest_framework.renderers.JSONRenderer',
|
||||||
'rest_framework.renderers.BrowsableAPIRenderer',
|
'rest_framework.renderers.BrowsableAPIRenderer',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
You can also set the renderers used for an individual view, or viewset,
|
You can also set the renderers used for an individual view, or viewset,
|
||||||
|
@ -42,7 +42,7 @@ using the `APIView` class-based views.
|
||||||
"""
|
"""
|
||||||
A view that returns the count of active users in JSON.
|
A view that returns the count of active users in JSON.
|
||||||
"""
|
"""
|
||||||
renderer_classes = (JSONRenderer, )
|
renderer_classes = [JSONRenderer]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
user_count = User.objects.filter(active=True).count()
|
user_count = User.objects.filter(active=True).count()
|
||||||
|
@ -52,7 +52,7 @@ using the `APIView` class-based views.
|
||||||
Or, if you're using the `@api_view` decorator with function based views.
|
Or, if you're using the `@api_view` decorator with function based views.
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@renderer_classes((JSONRenderer,))
|
@renderer_classes([JSONRenderer])
|
||||||
def user_count_view(request, format=None):
|
def user_count_view(request, format=None):
|
||||||
"""
|
"""
|
||||||
A view that returns the count of active users in JSON.
|
A view that returns the count of active users in JSON.
|
||||||
|
@ -116,7 +116,7 @@ An example of a view that uses `TemplateHTMLRenderer`:
|
||||||
A view that returns a templated HTML representation of a given user.
|
A view that returns a templated HTML representation of a given user.
|
||||||
"""
|
"""
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
renderer_classes = (TemplateHTMLRenderer,)
|
renderer_classes = [TemplateHTMLRenderer]
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
|
@ -142,8 +142,8 @@ A simple renderer that simply returns pre-rendered HTML. Unlike other renderers
|
||||||
|
|
||||||
An example of a view that uses `StaticHTMLRenderer`:
|
An example of a view that uses `StaticHTMLRenderer`:
|
||||||
|
|
||||||
@api_view(('GET',))
|
@api_view(['GET'])
|
||||||
@renderer_classes((StaticHTMLRenderer,))
|
@renderer_classes([StaticHTMLRenderer])
|
||||||
def simple_html_view(request):
|
def simple_html_view(request):
|
||||||
data = '<html><body><h1>Hello, world</h1></body></html>'
|
data = '<html><body><h1>Hello, world</h1></body></html>'
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
@ -328,8 +328,8 @@ In some cases you might want your view to use different serialization styles dep
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
@api_view(('GET',))
|
@api_view(['GET'])
|
||||||
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
@renderer_classes([TemplateHTMLRenderer, JSONRenderer])
|
||||||
def list_users(request):
|
def list_users(request):
|
||||||
"""
|
"""
|
||||||
A view that can return JSON or HTML representations
|
A view that can return JSON or HTML representations
|
||||||
|
@ -401,12 +401,12 @@ Install using pip.
|
||||||
Modify your REST framework settings.
|
Modify your REST framework settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework_yaml.parsers.YAMLParser',
|
'rest_framework_yaml.parsers.YAMLParser',
|
||||||
),
|
],
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework_yaml.renderers.YAMLRenderer',
|
'rest_framework_yaml.renderers.YAMLRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
## XML
|
## XML
|
||||||
|
@ -422,12 +422,12 @@ Install using pip.
|
||||||
Modify your REST framework settings.
|
Modify your REST framework settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework_xml.parsers.XMLParser',
|
'rest_framework_xml.parsers.XMLParser',
|
||||||
),
|
],
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework_xml.renderers.XMLRenderer',
|
'rest_framework_xml.renderers.XMLRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
## JSONP
|
## JSONP
|
||||||
|
@ -451,9 +451,9 @@ Install using pip.
|
||||||
Modify your REST framework settings.
|
Modify your REST framework settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework_jsonp.renderers.JSONPRenderer',
|
'rest_framework_jsonp.renderers.JSONPRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
## MessagePack
|
## MessagePack
|
||||||
|
@ -475,11 +475,11 @@ Modify your REST framework settings.
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
...
|
...
|
||||||
|
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework.renderers.JSONRenderer',
|
'rest_framework.renderers.JSONRenderer',
|
||||||
'rest_framework.renderers.BrowsableAPIRenderer',
|
'rest_framework.renderers.BrowsableAPIRenderer',
|
||||||
'drf_renderer_xlsx.renderers.XLSXRenderer',
|
'drf_renderer_xlsx.renderers.XLSXRenderer',
|
||||||
),
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
To avoid having a file streamed without a filename (which the browser will often default to the filename "download", with no extension), we need to use a mixin to override the `Content-Disposition` header. If no filename is provided, it will default to `export.xlsx`. For example:
|
To avoid having a file streamed without a filename (which the browser will often default to the filename "download", with no extension), we need to use a mixin to override the `Content-Disposition` header. If no filename is provided, it will default to `export.xlsx`. For example:
|
||||||
|
@ -494,7 +494,7 @@ To avoid having a file streamed without a filename (which the browser will often
|
||||||
class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
|
class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
|
||||||
queryset = MyExampleModel.objects.all()
|
queryset = MyExampleModel.objects.all()
|
||||||
serializer_class = MyExampleSerializer
|
serializer_class = MyExampleSerializer
|
||||||
renderer_classes = (XLSXRenderer,)
|
renderer_classes = [XLSXRenderer]
|
||||||
filename = 'my_export.xlsx'
|
filename = 'my_export.xlsx'
|
||||||
|
|
||||||
## CSV
|
## CSV
|
||||||
|
|
|
@ -311,7 +311,7 @@ The following example demonstrates how you might handle creating a user with a n
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('username', 'email', 'profile')
|
fields = ['username', 'email', 'profile']
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
profile_data = validated_data.pop('profile')
|
profile_data = validated_data.pop('profile')
|
||||||
|
@ -441,7 +441,7 @@ Declaring a `ModelSerializer` looks like this:
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'users', 'created')
|
fields = ['id', 'account_name', 'users', 'created']
|
||||||
|
|
||||||
By default, all the model fields on the class will be mapped to a corresponding serializer fields.
|
By default, all the model fields on the class will be mapped to a corresponding serializer fields.
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ For example:
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'users', 'created')
|
fields = ['id', 'account_name', 'users', 'created']
|
||||||
|
|
||||||
You can also set the `fields` attribute to the special value `'__all__'` to indicate that all fields in the model should be used.
|
You can also set the `fields` attribute to the special value `'__all__'` to indicate that all fields in the model should be used.
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ For example:
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
exclude = ('users',)
|
exclude = ['users']
|
||||||
|
|
||||||
In the example above, if the `Account` model had 3 fields `account_name`, `users`, and `created`, this will result in the fields `account_name` and `created` to be serialized.
|
In the example above, if the `Account` model had 3 fields `account_name`, `users`, and `created`, this will result in the fields `account_name` and `created` to be serialized.
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ The default `ModelSerializer` uses primary keys for relationships, but you can a
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'users', 'created')
|
fields = ['id', 'account_name', 'users', 'created']
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
|
The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
|
||||||
|
@ -534,8 +534,8 @@ This option should be a list or tuple of field names, and is declared as follows
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('id', 'account_name', 'users', 'created')
|
fields = ['id', 'account_name', 'users', 'created']
|
||||||
read_only_fields = ('account_name',)
|
read_only_fields = ['account_name']
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@ This option is a dictionary, mapping field names to a dictionary of keyword argu
|
||||||
class CreateUserSerializer(serializers.ModelSerializer):
|
class CreateUserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('email', 'username', 'password')
|
fields = ['email', 'username', 'password']
|
||||||
extra_kwargs = {'password': {'write_only': True}}
|
extra_kwargs = {'password': {'write_only': True}}
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
@ -673,7 +673,7 @@ You can explicitly include the primary key by adding it to the `fields` option,
|
||||||
class AccountSerializer(serializers.HyperlinkedModelSerializer):
|
class AccountSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('url', 'id', 'account_name', 'users', 'created')
|
fields = ['url', 'id', 'account_name', 'users', 'created']
|
||||||
|
|
||||||
## Absolute and relative URLs
|
## Absolute and relative URLs
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@ You can override a URL field view name and lookup field by using either, or both
|
||||||
class AccountSerializer(serializers.HyperlinkedModelSerializer):
|
class AccountSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('account_url', 'account_name', 'users', 'created')
|
fields = ['account_url', 'account_name', 'users', 'created']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'url': {'view_name': 'accounts', 'lookup_field': 'account_name'},
|
'url': {'view_name': 'accounts', 'lookup_field': 'account_name'},
|
||||||
'users': {'lookup_field': 'username'}
|
'users': {'lookup_field': 'username'}
|
||||||
|
@ -727,7 +727,7 @@ Alternatively you can set the fields on the serializer explicitly. For example:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields = ('url', 'account_name', 'users', 'created')
|
fields = ['url', 'account_name', 'users', 'created']
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1099,7 +1099,7 @@ This would then allow you to do the following:
|
||||||
>>> class UserSerializer(DynamicFieldsModelSerializer):
|
>>> class UserSerializer(DynamicFieldsModelSerializer):
|
||||||
>>> class Meta:
|
>>> class Meta:
|
||||||
>>> model = User
|
>>> model = User
|
||||||
>>> fields = ('id', 'username', 'email')
|
>>> fields = ['id', 'username', 'email']
|
||||||
>>>
|
>>>
|
||||||
>>> print(UserSerializer(user))
|
>>> print(UserSerializer(user))
|
||||||
{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}
|
{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}
|
||||||
|
|
|
@ -14,12 +14,12 @@ Configuration for REST framework is all namespaced inside a single Django settin
|
||||||
For example your project's `settings.py` file might include something like this:
|
For example your project's `settings.py` file might include something like this:
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_RENDERER_CLASSES': (
|
'DEFAULT_RENDERER_CLASSES': [
|
||||||
'rest_framework.renderers.JSONRenderer',
|
'rest_framework.renderers.JSONRenderer',
|
||||||
),
|
],
|
||||||
'DEFAULT_PARSER_CLASSES': (
|
'DEFAULT_PARSER_CLASSES': [
|
||||||
'rest_framework.parsers.JSONParser',
|
'rest_framework.parsers.JSONParser',
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
## Accessing settings
|
## Accessing settings
|
||||||
|
|
|
@ -402,11 +402,11 @@ For example, to add support for using `format='html'` in test requests, you migh
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
...
|
...
|
||||||
'TEST_REQUEST_RENDERER_CLASSES': (
|
'TEST_REQUEST_RENDERER_CLASSES': [
|
||||||
'rest_framework.renderers.MultiPartRenderer',
|
'rest_framework.renderers.MultiPartRenderer',
|
||||||
'rest_framework.renderers.JSONRenderer',
|
'rest_framework.renderers.JSONRenderer',
|
||||||
'rest_framework.renderers.TemplateHTMLRenderer'
|
'rest_framework.renderers.TemplateHTMLRenderer'
|
||||||
)
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
[cite]: https://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper
|
[cite]: https://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper
|
||||||
|
|
|
@ -31,10 +31,10 @@ If any throttle check fails an `exceptions.Throttled` exception will be raised,
|
||||||
The default throttling policy may be set globally, using the `DEFAULT_THROTTLE_CLASSES` and `DEFAULT_THROTTLE_RATES` settings. For example.
|
The default throttling policy may be set globally, using the `DEFAULT_THROTTLE_CLASSES` and `DEFAULT_THROTTLE_RATES` settings. For example.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_THROTTLE_CLASSES': (
|
'DEFAULT_THROTTLE_CLASSES': [
|
||||||
'rest_framework.throttling.AnonRateThrottle',
|
'rest_framework.throttling.AnonRateThrottle',
|
||||||
'rest_framework.throttling.UserRateThrottle'
|
'rest_framework.throttling.UserRateThrottle'
|
||||||
),
|
],
|
||||||
'DEFAULT_THROTTLE_RATES': {
|
'DEFAULT_THROTTLE_RATES': {
|
||||||
'anon': '100/day',
|
'anon': '100/day',
|
||||||
'user': '1000/day'
|
'user': '1000/day'
|
||||||
|
@ -51,7 +51,7 @@ using the `APIView` class-based views.
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
class ExampleView(APIView):
|
class ExampleView(APIView):
|
||||||
throttle_classes = (UserRateThrottle,)
|
throttle_classes = [UserRateThrottle]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
content = {
|
content = {
|
||||||
|
@ -129,10 +129,10 @@ For example, multiple user throttle rates could be implemented by using the foll
|
||||||
...and the following settings.
|
...and the following settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_THROTTLE_CLASSES': (
|
'DEFAULT_THROTTLE_CLASSES': [
|
||||||
'example.throttles.BurstRateThrottle',
|
'example.throttles.BurstRateThrottle',
|
||||||
'example.throttles.SustainedRateThrottle'
|
'example.throttles.SustainedRateThrottle'
|
||||||
),
|
],
|
||||||
'DEFAULT_THROTTLE_RATES': {
|
'DEFAULT_THROTTLE_RATES': {
|
||||||
'burst': '60/min',
|
'burst': '60/min',
|
||||||
'sustained': '1000/day'
|
'sustained': '1000/day'
|
||||||
|
@ -164,9 +164,9 @@ For example, given the following views...
|
||||||
...and the following settings.
|
...and the following settings.
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_THROTTLE_CLASSES': (
|
'DEFAULT_THROTTLE_CLASSES': [
|
||||||
'rest_framework.throttling.ScopedRateThrottle',
|
'rest_framework.throttling.ScopedRateThrottle',
|
||||||
),
|
],
|
||||||
'DEFAULT_THROTTLE_RATES': {
|
'DEFAULT_THROTTLE_RATES': {
|
||||||
'contacts': '1000/day',
|
'contacts': '1000/day',
|
||||||
'uploads': '20/day'
|
'uploads': '20/day'
|
||||||
|
|
|
@ -97,7 +97,7 @@ The validator should be applied to *serializer classes*, like so:
|
||||||
validators = [
|
validators = [
|
||||||
UniqueTogetherValidator(
|
UniqueTogetherValidator(
|
||||||
queryset=ToDoItem.objects.all(),
|
queryset=ToDoItem.objects.all(),
|
||||||
fields=('list', 'position')
|
fields=['list', 'position']
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ For example:
|
||||||
# Apply custom validation either here, or in the view.
|
# Apply custom validation either here, or in the view.
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('client', 'date', 'amount')
|
fields = ['client', 'date', 'amount']
|
||||||
extra_kwargs = {'client': {'required': False}}
|
extra_kwargs = {'client': {'required': False}}
|
||||||
validators = [] # Remove a default "unique together" constraint.
|
validators = [] # Remove a default "unique together" constraint.
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ For example:
|
||||||
* Requires token authentication.
|
* Requires token authentication.
|
||||||
* Only admin users are able to access this view.
|
* Only admin users are able to access this view.
|
||||||
"""
|
"""
|
||||||
authentication_classes = (authentication.TokenAuthentication,)
|
authentication_classes = [authentication.TokenAuthentication]
|
||||||
permission_classes = (permissions.IsAdminUser,)
|
permission_classes = [permissions.IsAdminUser]
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -258,13 +258,13 @@ If you try to use a writable nested serializer without writing a custom `create(
|
||||||
>>> class ProfileSerializer(serializers.ModelSerializer):
|
>>> class ProfileSerializer(serializers.ModelSerializer):
|
||||||
>>> class Meta:
|
>>> class Meta:
|
||||||
>>> model = Profile
|
>>> model = Profile
|
||||||
>>> fields = ('address', 'phone')
|
>>> fields = ['address', 'phone']
|
||||||
>>>
|
>>>
|
||||||
>>> class UserSerializer(serializers.ModelSerializer):
|
>>> class UserSerializer(serializers.ModelSerializer):
|
||||||
>>> profile = ProfileSerializer()
|
>>> profile = ProfileSerializer()
|
||||||
>>> class Meta:
|
>>> class Meta:
|
||||||
>>> model = User
|
>>> model = User
|
||||||
>>> fields = ('username', 'email', 'profile')
|
>>> fields = ['username', 'email', 'profile']
|
||||||
>>>
|
>>>
|
||||||
>>> data = {
|
>>> data = {
|
||||||
>>> 'username': 'lizzy',
|
>>> 'username': 'lizzy',
|
||||||
|
@ -283,7 +283,7 @@ To use writable nested serialization you'll want to declare a nested field on th
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('username', 'email', 'profile')
|
fields = ['username', 'email', 'profile']
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
profile_data = validated_data.pop('profile')
|
profile_data = validated_data.pop('profile')
|
||||||
|
@ -327,7 +327,7 @@ The `write_only_fields` option on `ModelSerializer` has been moved to `PendingDe
|
||||||
class MySerializer(serializer.ModelSerializer):
|
class MySerializer(serializer.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MyModel
|
model = MyModel
|
||||||
fields = ('id', 'email', 'notes', 'is_admin')
|
fields = ['id', 'email', 'notes', 'is_admin']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'is_admin': {'write_only': True}
|
'is_admin': {'write_only': True}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ Alternatively, specify the field explicitly on the serializer class:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MyModel
|
model = MyModel
|
||||||
fields = ('id', 'email', 'notes', 'is_admin')
|
fields = ['id', 'email', 'notes', 'is_admin']
|
||||||
|
|
||||||
The `read_only_fields` option remains as a convenient shortcut for the more common case.
|
The `read_only_fields` option remains as a convenient shortcut for the more common case.
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ The `view_name` and `lookup_field` options have been moved to `PendingDeprecatio
|
||||||
class MySerializer(serializer.HyperlinkedModelSerializer):
|
class MySerializer(serializer.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MyModel
|
model = MyModel
|
||||||
fields = ('url', 'email', 'notes', 'is_admin')
|
fields = ['url', 'email', 'notes', 'is_admin']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'url': {'lookup_field': 'uuid'}
|
'url': {'lookup_field': 'uuid'}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ Alternatively, specify the field explicitly on the serializer class:
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MyModel
|
model = MyModel
|
||||||
fields = ('url', 'email', 'notes', 'is_admin')
|
fields = ['url', 'email', 'notes', 'is_admin']
|
||||||
|
|
||||||
#### Fields for model methods and properties.
|
#### Fields for model methods and properties.
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ You can include `expiry_date` as a field option on a `ModelSerializer` class.
|
||||||
class InvitationSerializer(serializers.ModelSerializer):
|
class InvitationSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Invitation
|
model = Invitation
|
||||||
fields = ('to_email', 'message', 'expiry_date')
|
fields = ['to_email', 'message', 'expiry_date']
|
||||||
|
|
||||||
These fields will be mapped to `serializers.ReadOnlyField()` instances.
|
These fields will be mapped to `serializers.ReadOnlyField()` instances.
|
||||||
|
|
||||||
|
@ -738,7 +738,7 @@ The `UniqueTogetherValidator` should be applied to a serializer, and takes a `qu
|
||||||
class Meta:
|
class Meta:
|
||||||
validators = [UniqueTogetherValidator(
|
validators = [UniqueTogetherValidator(
|
||||||
queryset=RaceResult.objects.all(),
|
queryset=RaceResult.objects.all(),
|
||||||
fields=('category', 'position')
|
fields=['category', 'position']
|
||||||
)]
|
)]
|
||||||
|
|
||||||
#### The `UniqueForDateValidator` classes.
|
#### The `UniqueForDateValidator` classes.
|
||||||
|
|
|
@ -61,7 +61,7 @@ For example, when using `NamespaceVersioning`, and the following hyperlinked ser
|
||||||
class AccountsSerializer(serializer.HyperlinkedModelSerializer):
|
class AccountsSerializer(serializer.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Accounts
|
model = Accounts
|
||||||
fields = ('account_name', 'users')
|
fields = ['account_name', 'users']
|
||||||
|
|
||||||
The output representation would match the version used on the incoming request. Like so:
|
The output representation would match the version used on the incoming request. Like so:
|
||||||
|
|
||||||
|
|
|
@ -499,7 +499,7 @@ A generic view with sections in the class docstring, using single-line style.
|
||||||
"""
|
"""
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
permission_classes = (IsAdminUser,)
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
A generic viewset with sections in the class docstring, using multi-line style.
|
A generic viewset with sections in the class docstring, using multi-line style.
|
||||||
|
|
||||||
|
|
|
@ -112,10 +112,10 @@ Install using `pip`, including any optional packages you want...
|
||||||
|
|
||||||
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
|
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
)
|
]
|
||||||
|
|
||||||
If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views. Add the following to your root `urls.py` file.
|
If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views. Add the following to your root `urls.py` file.
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ Here's our project's root `urls.py` module:
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('url', 'username', 'email', 'is_staff')
|
fields = ['url', 'username', 'email', 'is_staff']
|
||||||
|
|
||||||
# ViewSets define the view behavior.
|
# ViewSets define the view behavior.
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
|
|
|
@ -15,14 +15,14 @@ Nested data structures are easy enough to work with if they're read-only - simpl
|
||||||
class ToDoItemSerializer(serializers.ModelSerializer):
|
class ToDoItemSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ToDoItem
|
model = ToDoItem
|
||||||
fields = ('text', 'is_completed')
|
fields = ['text', 'is_completed']
|
||||||
|
|
||||||
class ToDoListSerializer(serializers.ModelSerializer):
|
class ToDoListSerializer(serializers.ModelSerializer):
|
||||||
items = ToDoItemSerializer(many=True, read_only=True)
|
items = ToDoItemSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ToDoList
|
model = ToDoList
|
||||||
fields = ('title', 'items')
|
fields = ['title', 'items']
|
||||||
|
|
||||||
Some example output from our serializer.
|
Some example output from our serializer.
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,11 @@ Once that's done we can create an app that we'll use to create a simple Web API.
|
||||||
|
|
||||||
We'll need to add our new `snippets` app and the `rest_framework` app to `INSTALLED_APPS`. Let's edit the `tutorial/settings.py` file:
|
We'll need to add our new `snippets` app and the `rest_framework` app to `INSTALLED_APPS`. Let's edit the `tutorial/settings.py` file:
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'snippets.apps.SnippetsConfig',
|
'snippets.apps.SnippetsConfig',
|
||||||
)
|
]
|
||||||
|
|
||||||
Okay, we're ready to roll.
|
Okay, we're ready to roll.
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ For the purposes of this tutorial we're going to start by creating a simple `Sni
|
||||||
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
|
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('created',)
|
ordering = ['created']
|
||||||
|
|
||||||
We'll also need to create an initial migration for our snippet model, and sync the database for the first time.
|
We'll also need to create an initial migration for our snippet model, and sync the database for the first time.
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ Open the file `snippets/serializers.py` again, and replace the `SnippetSerialize
|
||||||
class SnippetSerializer(serializers.ModelSerializer):
|
class SnippetSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Snippet
|
model = Snippet
|
||||||
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
|
fields = ['id', 'title', 'code', 'linenos', 'language', 'style']
|
||||||
|
|
||||||
One nice property that serializers have is that you can inspect all the fields in a serializer instance, by printing its representation. Open the Django shell with `python manage.py shell`, then try the following:
|
One nice property that serializers have is that you can inspect all the fields in a serializer instance, by printing its representation. Open the Django shell with `python manage.py shell`, then try the following:
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ Now that we've got some users to work with, we'd better add representations of t
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('id', 'username', 'snippets')
|
fields = ['id', 'username', 'snippets']
|
||||||
|
|
||||||
Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we needed to add an explicit field for it.
|
Because `'snippets'` is a *reverse* relationship on the User model, it will not be included by default when using the `ModelSerializer` class, so we needed to add an explicit field for it.
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ First add the following import in the views module
|
||||||
|
|
||||||
Then, add the following property to **both** the `SnippetList` and `SnippetDetail` view classes.
|
Then, add the following property to **both** the `SnippetList` and `SnippetDetail` view classes.
|
||||||
|
|
||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
## Adding login to the Browsable API
|
## Adding login to the Browsable API
|
||||||
|
|
||||||
|
@ -178,8 +178,8 @@ In the snippets app, create a new file, `permissions.py`
|
||||||
|
|
||||||
Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetDetail` view class:
|
Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetDetail` view class:
|
||||||
|
|
||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
|
||||||
IsOwnerOrReadOnly,)
|
IsOwnerOrReadOnly]
|
||||||
|
|
||||||
Make sure to also import the `IsOwnerOrReadOnly` class.
|
Make sure to also import the `IsOwnerOrReadOnly` class.
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ Instead of using a concrete generic view, we'll use the base class for represent
|
||||||
|
|
||||||
class SnippetHighlight(generics.GenericAPIView):
|
class SnippetHighlight(generics.GenericAPIView):
|
||||||
queryset = Snippet.objects.all()
|
queryset = Snippet.objects.all()
|
||||||
renderer_classes = (renderers.StaticHTMLRenderer,)
|
renderer_classes = [renderers.StaticHTMLRenderer]
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
snippet = self.get_object()
|
snippet = self.get_object()
|
||||||
|
@ -80,8 +80,8 @@ We can easily re-write our existing serializers to use hyperlinking. In your `sn
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Snippet
|
model = Snippet
|
||||||
fields = ('url', 'id', 'highlight', 'owner',
|
fields = ['url', 'id', 'highlight', 'owner',
|
||||||
'title', 'code', 'linenos', 'language', 'style')
|
'title', 'code', 'linenos', 'language', 'style']
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
@ -89,7 +89,7 @@ We can easily re-write our existing serializers to use hyperlinking. In your `sn
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('url', 'id', 'username', 'snippets')
|
fields = ['url', 'id', 'username', 'snippets']
|
||||||
|
|
||||||
Notice that we've also added a new `'highlight'` field. This field is of the same type as the `url` field, except that it points to the `'snippet-highlight'` url pattern, instead of the `'snippet-detail'` url pattern.
|
Notice that we've also added a new `'highlight'` field. This field is of the same type as the `url` field, except that it points to the `'snippet-highlight'` url pattern, instead of the `'snippet-detail'` url pattern.
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighl
|
||||||
"""
|
"""
|
||||||
queryset = Snippet.objects.all()
|
queryset = Snippet.objects.all()
|
||||||
serializer_class = SnippetSerializer
|
serializer_class = SnippetSerializer
|
||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
|
||||||
IsOwnerOrReadOnly,)
|
IsOwnerOrReadOnly]
|
||||||
|
|
||||||
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
|
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
|
||||||
def highlight(self, request, *args, **kwargs):
|
def highlight(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -69,13 +69,13 @@ First up we're going to define some serializers. Let's create a new module named
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('url', 'username', 'email', 'groups')
|
fields = ['url', 'username', 'email', 'groups']
|
||||||
|
|
||||||
|
|
||||||
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Group
|
model = Group
|
||||||
fields = ('url', 'name')
|
fields = ['url', 'name']
|
||||||
|
|
||||||
Notice that we're using hyperlinked relations in this case with `HyperlinkedModelSerializer`. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.
|
Notice that we're using hyperlinked relations in this case with `HyperlinkedModelSerializer`. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.
|
||||||
|
|
||||||
|
@ -144,10 +144,10 @@ Pagination allows you to control how many objects per page are returned. To enab
|
||||||
|
|
||||||
Add `'rest_framework'` to `INSTALLED_APPS`. The settings module will be in `tutorial/settings.py`
|
Add `'rest_framework'` to `INSTALLED_APPS`. The settings module will be in `tutorial/settings.py`
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = [
|
||||||
...
|
...
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
)
|
]
|
||||||
|
|
||||||
Okay, we're done.
|
Okay, we're done.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user