Update docs to use lists instead of tuples (#6797)

This commit is contained in:
Luke Plant 2019-07-13 04:15:36 +03:00 committed by Ryan P Kilby
parent 5c922fb39d
commit f0dbf0a264
26 changed files with 161 additions and 161 deletions

View File

@ -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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = {

View File

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

View File

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

View File

@ -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'}

View File

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

View File

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

View File

@ -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'

View File

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

View File

@ -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):
""" """

View File

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

View File

@ -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:

View File

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

View File

@ -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):

View File

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

View File

@ -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:

View File

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

View File

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

View File

@ -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):

View File

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