Tutorial 5: Relationships & Hyperlinked APIs
-At the moment relationships within our API are represented by using primary keys. In this part of the tutorial we'll improve the cohesion and discoverability of our API, by instead using hyperlinking for relationships.
+At the moment relationships within our API are represented by using primary keys. In this part of the tutorial we'll improve the cohesion and discoverability of our API, by instead using hyperlinking for relationships.
Creating an endpoint for the root of our API
-Right now we have endpoints for 'snippets' and 'users', but we don't have a single entry point to our API. To create one, we'll use a regular function-based view and the @api_view
decorator we introduced earlier.
Right now we have endpoints for 'snippets' and 'users', but we don't have a single entry point to our API. To create one, we'll use a regular function-based view and the @api_view
decorator we introduced earlier. In your snippets/views.py
add:
from rest_framework import renderers
from rest_framework.decorators import api_view
from rest_framework.response import Response
@@ -223,7 +223,7 @@ def api_root(request, format=None):
The other obvious thing that's still missing from our pastebin API is the code highlighting endpoints.
Unlike all our other API endpoints, we don't want to use JSON, but instead just present an HTML representation. There are two styles of HTML renderer provided by REST framework, one for dealing with HTML rendered using templates, the other for dealing with pre-rendered HTML. The second renderer is the one we'd like to use for this endpoint.
The other thing we need to consider when creating the code highlight view is that there's no existing concrete generic view that we can use. We're not returning an object instance, but instead a property of an object instance.
-Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own .get()
method. In your snippets.views
add:
+Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own .get()
method. In your snippets/views.py
add:
from rest_framework import renderers
from rest_framework.response import Response
@@ -236,7 +236,7 @@ class SnippetHighlight(generics.GenericAPIView):
return Response(snippet.highlighted)
As usual we need to add the new views that we've created in to our URLconf.
-We'll add a url pattern for our new API root:
+We'll add a url pattern for our new API root in snippets/urls.py
:
url(r'^$', 'api_root'),
And then add a url pattern for the snippet highlights:
@@ -261,7 +261,7 @@ We'll add a url pattern for our new API root:
Relationships use HyperlinkedRelatedField
,
instead of PrimaryKeyRelatedField
.
-We can easily re-write our existing serializers to use hyperlinking.
+We can easily re-write our existing serializers to use hyperlinking. In your snippets/serializers.py
add:
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
@@ -289,7 +289,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
Our user serializer includes a field that refers to 'snippet-detail'
.
Our snippet and user serializers include 'url'
fields that by default will refer to '{model_name}-detail'
, which in this case will be 'snippet-detail'
and 'user-detail'
.
-After adding all those names into our URLconf, our final 'urls.py'
file should look something like this:
+After adding all those names into our URLconf, our final snippets/urls.py
file should look something like this:
# API endpoints
urlpatterns = format_suffix_patterns(patterns('snippets.views',
url(r'^$', 'api_root'),
@@ -311,7 +311,7 @@ urlpatterns = format_suffix_patterns(patterns('snippets.views',
))
# Login and logout views for the browsable API
-urlpatterns += patterns('',
+urlpatterns += patterns('',
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
)
diff --git a/tutorial/quickstart.html b/tutorial/quickstart.html
index 5949e4ed8..171e7255a 100644
--- a/tutorial/quickstart.html
+++ b/tutorial/quickstart.html
@@ -319,22 +319,22 @@ REST_FRAMEWORK = {
python ./manage.py runserver
We can now access our API, both from the command-line, using tools like curl
...
-bash: curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
+bash: curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
{
- "count": 2,
- "next": null,
- "previous": null,
+ "count": 2,
+ "next": null,
+ "previous": null,
"results": [
{
- "email": "admin@example.com",
- "groups": [],
- "url": "http://127.0.0.1:8000/users/1/",
+ "email": "admin@example.com",
+ "groups": [],
+ "url": "http://127.0.0.1:8000/users/1/",
"username": "admin"
- },
+ },
{
- "email": "tom@example.com",
- "groups": [ ],
- "url": "http://127.0.0.1:8000/users/2/",
+ "email": "tom@example.com",
+ "groups": [ ],
+ "url": "http://127.0.0.1:8000/users/2/",
"username": "tom"
}
]