You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+24-32Lines changed: 24 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,39 +42,10 @@ Add `'rest_framework'` to your `INSTALLED_APPS` setting.
42
42
'rest_framework',
43
43
)
44
44
45
-
If you're intending to use the browseable API you'll probably also want to add REST framework's login and logout views. Add the following to your root `urls.py` file.
Note that the URL path can be whatever you want, but you must include `'rest_framework.urls'` with the `'rest_framework'` namespace.
53
-
54
45
# Example
55
46
56
-
Let's take a look at a quick example of using REST framework to build a simple model-backed API.
57
-
58
-
We'll create a read-write API for accessing users and groups.
59
-
60
-
Any global settings for a REST framework API are kept in a single configuration dictionary named `REST_FRAMEWORK`. Start off by adding the following to your `settings.py` module:
61
-
62
-
REST_FRAMEWORK = {
63
-
# Use hyperlinked styles by default.
64
-
# Only used if the `serializer_class` attribute is not set on a view.
Copy file name to clipboardExpand all lines: docs/api-guide/generic-views.md
+5-2Lines changed: 5 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -62,6 +62,10 @@ The following attributes control the basic view behavior.
62
62
*`serializer_class` - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the `get_serializer_class()` method.
63
63
*`lookup_field` - The field that should be used to lookup individual model instances. Defaults to `'pk'`. The URL conf should include a keyword argument corresponding to this value. More complex lookup styles can be supported by overriding the `get_object()` method.
64
64
65
+
**Shortcuts**:
66
+
67
+
*`model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes, although using the explicit style is generally preferred. If used instead of `serializer_class`, then then `DEFAULT_MODEL_SERIALIZER_CLASS` setting will determine the base serializer class.
68
+
65
69
**Pagination**:
66
70
67
71
The following attibutes are used to control pagination when used with list views.
@@ -75,7 +79,6 @@ The following attibutes are used to control pagination when used with list views
75
79
76
80
*`filter_backend` - The filter backend class that should be used for filtering the queryset. Defaults to the same value as the `FILTER_BACKEND` setting.
77
81
*`allow_empty` - Determines if an empty list should successfully display zero results, or return a 404 response. Defaults to `True`, meaning empty lists will return sucessful `200 OK` responses, with zero results.
78
-
*`model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes, although using the explicit style is generally preferred. If used instead of `serializer_class`, then then `DEFAULT_MODEL_SERIALIZER_CLASS` setting will determine the base serializer class.
79
82
80
83
### Methods
81
84
@@ -160,7 +163,7 @@ The following classes are the concrete generic views. If you're using generic v
There are three arguments to the `register()` method:
22
+
There are two mandatory arguments to the `register()` method:
23
23
24
24
*`prefix` - The URL prefix to use for this set of routes.
25
25
*`viewset` - The viewset class.
26
-
*`name` - The base to use for the URL names that are created.
26
+
27
+
Optionally, you may also specify an additional argument:
28
+
29
+
*`base_name` - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the `model` or `queryset` attribute on the viewset, if it has one.
27
30
28
31
The example above would generate the following URL patterns:
29
32
@@ -101,6 +104,8 @@ The following example will only route to the `list` and `retrieve` actions, and
101
104
102
105
## Advanced custom routers
103
106
104
-
If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls()` method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the `self.registry` attribute.
107
+
If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the `self.registry` attribute.
108
+
109
+
You may also want to override the `get_default_base_name(self, viewset)` method, or else always explicitly set the `base_name` argument when registering your viewsets with the router.
Registering the viewsets with the router is similar to providing a urlpattern. We include three arguments - the URL prefix for the views, the viewset itself, and the base name that should be used for constructing the URL names, such as `snippet-list`.
118
+
Registering the viewsets with the router is similar to providing a urlpattern. We include two arguments - the URL prefix for the views, and the viewset itself.
119
119
120
120
The `DefaultRouter` class we're using also automatically creates the API root view for us, so we can now delete the `api_root` method from our `views` module.
121
121
122
122
## Trade-offs between views vs viewsets.
123
123
124
124
Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.
125
125
126
-
That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using view sets is less explicit than building your views individually.
126
+
That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.
Copy file name to clipboardExpand all lines: docs/tutorial/quickstart.md
+25-70Lines changed: 25 additions & 70 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ Create a new Django project, and start a new app called `quickstart`. Once you'
8
8
9
9
First up we're going to define some serializers in `quickstart/serializers.py` that we'll use for our data representations.
10
10
11
-
from django.contrib.auth.models import User, Group, Permission
11
+
from django.contrib.auth.models import User, Group
12
12
from rest_framework import serializers
13
13
14
14
@@ -19,109 +19,64 @@ First up we're going to define some serializers in `quickstart/serializers.py` t
19
19
20
20
21
21
class GroupSerializer(serializers.HyperlinkedModelSerializer):
22
-
permissions = serializers.ManySlugRelatedField(
23
-
slug_field='codename',
24
-
queryset=Permission.objects.all()
25
-
)
26
-
27
22
class Meta:
28
23
model = Group
29
-
fields = ('url', 'name', 'permissions')
24
+
fields = ('url', 'name')
30
25
31
26
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.
32
27
33
-
We've also overridden the `permission` field on the `GroupSerializer`. In this case we don't want to use a hyperlinked representation, but instead use the list of permission codenames associated with the group, so we've used a `ManySlugRelatedField`, using the `codename` field for the representation.
34
-
35
28
## Views
36
29
37
30
Right, we'd better write some views then. Open `quickstart/views.py` and get typing.
38
31
39
32
from django.contrib.auth.models import User, Group
40
-
from rest_framework import generics
41
-
from rest_framework.decorators import api_view
42
-
from rest_framework.reverse import reverse
43
-
from rest_framework.response import Response
33
+
from rest_framework import viewsets
44
34
from quickstart.serializers import UserSerializer, GroupSerializer
45
35
46
36
47
-
@api_view(['GET'])
48
-
def api_root(request, format=None):
49
-
"""
50
-
The entry endpoint of our API.
51
-
"""
52
-
return Response({
53
-
'users': reverse('user-list', request=request),
54
-
'groups': reverse('group-list', request=request),
55
-
})
56
-
57
-
58
-
class UserList(generics.ListCreateAPIView):
59
-
"""
60
-
API endpoint that represents a list of users.
61
-
"""
62
-
model = User
63
-
serializer_class = UserSerializer
64
-
65
-
66
-
class UserDetail(generics.RetrieveUpdateDestroyAPIView):
37
+
class UserViewSet(viewsets.ModelViewSet):
67
38
"""
68
-
API endpoint that represents a single user.
39
+
API endpoint that allows users to be viewed or edited.
69
40
"""
70
-
model = User
41
+
queryset = User.objects.all()
71
42
serializer_class = UserSerializer
72
43
73
44
74
-
class GroupList(generics.ListCreateAPIView):
45
+
class GroupViewSet(viewsets.ModelViewSet):
75
46
"""
76
-
API endpoint that represents a list of groups.
47
+
API endpoint that allows groups to be viewed or edited.
77
48
"""
78
-
model = Group
79
-
serializer_class = GroupSerializer
80
-
81
-
82
-
class GroupDetail(generics.RetrieveUpdateDestroyAPIView):
83
-
"""
84
-
API endpoint that represents a single group.
85
-
"""
86
-
model = Group
49
+
queryset = Group.objects.all()
87
50
serializer_class = GroupSerializer
88
51
89
-
Let's take a moment to look at what we've done here before we move on. We have one function-based view representing the root of the API, and four class-based views which map to our database models, and specify which serializers should be used for representing that data. Pretty simple stuff.
52
+
Rather that write multiple views we're grouping together all the common behavior into classes called `ViewSets`.
53
+
54
+
We can easily break these down into individual views if we need to, but using viewsets keeps the view logic nicely organized as well as being very concise.
90
55
91
56
## URLs
92
57
93
-
Okay, let's wire this baby up. On to `quickstart/urls.py`...
58
+
Okay, now let's wire up the API URLs. On to `quickstart/urls.py`...
94
59
95
60
from django.conf.urls import patterns, url, include
96
-
from rest_framework.urlpatterns import format_suffix_patterns
97
-
from quickstart.views import UserList, UserDetail, GroupList, GroupDetail
Firstly the names `user-detail` and `group-detail` are important. We're using the default hyperlinked relationships without explicitly specifying the view names, so we need to use names of the style `{modelname}-detail` to represent the model instance views.
75
+
Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.
121
76
122
-
Secondly, we're modifying the urlpatterns using `format_suffix_patterns`, to append optional `.json` style suffixes to our URLs.
77
+
Again, if we need more control over the API URLs we can simply drop down to using regular class based views, and writing the URL conf explicitly.
123
78
124
-
Finally, we're including default login and logout views for use with the browsable API. That's optional, but useful if your API requires authentication and you want to use the browseable API.
79
+
Note that we're also including default login and logout views for use with the browsable API. That's optional, but useful if your API requires authentication and you want to use the browseable API.
0 commit comments