Tutorial 5: Relationships & Hyperlinked APIs

转载自:http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/

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.

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. In your snippets/views.py add:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse

@api_view([‘GET‘])
def api_root(request, format=None):
    return Response({
        ‘users‘: reverse(‘user-list‘, request=request, format=format),
        ‘snippets‘: reverse(‘snippet-list‘, request=request, format=format)
    })

Two things should be noticed here. First, we‘re using REST framework‘s reverse function in order to return fully-qualified URLs; second, URL patterns are identified by convenience names that we will declare later on in our snippets/urls.py.

Creating an endpoint for the highlighted snippets

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.py add:

from rest_framework import renderers
from rest_framework.response import Response

class SnippetHighlight(generics.GenericAPIView):
    queryset = Snippet.objects.all()
    renderer_classes = (renderers.StaticHTMLRenderer,)

    def get(self, request, *args, **kwargs):
        snippet = self.get_object()
        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 in snippets/urls.py:

url(r‘^$‘, views.api_root),

And then add a url pattern for the snippet highlights:

url(r‘^snippets/(?P<pk>[0-9]+)/highlight/$‘, views.SnippetHighlight.as_view()),

Hyperlinking our API

Dealing with relationships between entities is one of the more challenging aspects of Web API design. There are a number of different ways that we might choose to represent a relationship:

  • Using primary keys.
  • Using hyperlinking between entities.
  • Using a unique identifying slug field on the related entity.
  • Using the default string representation of the related entity.
  • Nesting the related entity inside the parent representation.
  • Some other custom representation.

REST framework supports all of these styles, and can apply them across forward or reverse relationships, or apply them across custom managers such as generic foreign keys.

In this case we‘d like to use a hyperlinked style between entities. In order to do so, we‘ll modify our serializers to extend HyperlinkedModelSerializer instead of the existing ModelSerializer.

The HyperlinkedModelSerializer has the following differences from ModelSerializer:

  • It does not include the id field by default.
  • It includes a url field, using HyperlinkedIdentityField.
  • Relationships use HyperlinkedRelatedField, instead of PrimaryKeyRelatedField.

We can easily re-write our existing serializers to use hyperlinking. In your snippets/serializers.py add:

class SnippetSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source=‘owner.username‘)
    highlight = serializers.HyperlinkedIdentityField(view_name=‘snippet-highlight‘, format=‘html‘)

    class Meta:
        model = Snippet
        fields = (‘url‘, ‘id‘, ‘highlight‘, ‘owner‘,
                  ‘title‘, ‘code‘, ‘linenos‘, ‘language‘, ‘style‘)

class UserSerializer(serializers.HyperlinkedModelSerializer):
    snippets = serializers.HyperlinkedRelatedField(many=True, view_name=‘snippet-detail‘, read_only=True)

    class Meta:
        model = User
        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.

Because we‘ve included format suffixed URLs such as ‘.json‘, we also need to indicate on the highlight field that any format suffixed hyperlinks it returns should use the ‘.html‘ suffix.

Making sure our URL patterns are named

If we‘re going to have a hyperlinked API, we need to make sure we name our URL patterns. Let‘s take a look at which URL patterns we need to name.

  • The root of our API refers to ‘user-list‘ and ‘snippet-list‘.
  • Our snippet serializer includes a field that refers to ‘snippet-highlight‘.
  • 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 snippets/urls.py file should look like this:

from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

# API endpoints
urlpatterns = format_suffix_patterns([
    url(r‘^$‘, views.api_root),
    url(r‘^snippets/$‘,
        views.SnippetList.as_view(),
        name=‘snippet-list‘),
    url(r‘^snippets/(?P<pk>[0-9]+)/$‘,
        views.SnippetDetail.as_view(),
        name=‘snippet-detail‘),
    url(r‘^snippets/(?P<pk>[0-9]+)/highlight/$‘,
        views.SnippetHighlight.as_view(),
        name=‘snippet-highlight‘),
    url(r‘^users/$‘,
        views.UserList.as_view(),
        name=‘user-list‘),
    url(r‘^users/(?P<pk>[0-9]+)/$‘,
        views.UserDetail.as_view(),
        name=‘user-detail‘)
])

# Login and logout views for the browsable API
urlpatterns += [
    url(r‘^api-auth/‘, include(‘rest_framework.urls‘,
                               namespace=‘rest_framework‘)),
]

Adding pagination

The list views for users and code snippets could end up returning quite a lot of instances, so really we‘d like to make sure we paginate the results, and allow the API client to step through each of the individual pages.

We can change the default list style to use pagination, by modifying our tutorial/settings.py file slightly. Add the following setting:

REST_FRAMEWORK = {
    ‘PAGE_SIZE‘: 10
}

Note that settings in REST framework are all namespaced into a single dictionary setting, named ‘REST_FRAMEWORK‘, which helps keep them well separated from your other project settings.

We could also customize the pagination style if we needed too, but in this case we‘ll just stick with the default.

Browsing the API

If we open a browser and navigate to the browsable API, you‘ll find that you can now work your way around the API simply by following links.

You‘ll also be able to see the ‘highlight‘ links on the snippet instances, that will take you to the highlighted code HTML representations.

In part 6 of the tutorial we‘ll look at how we can use ViewSets and Routers to reduce the amount of code we need to build our API.

时间: 2024-08-01 12:11:51

Tutorial 5: Relationships & Hyperlinked APIs的相关文章

API(五)之Relationships &amp; Hyperlinked APIs

目前,我们的API中的关系用主键表示.在本教程的这一部分中,我们将改进API的内聚力和可发现性,而不是使用关联的超链接. 为我们的API的根创建一个端点 现在我们有'snippets'和'users'的端点,但是我们的API没有一个入口点.为了创建一个入口点,我们将使用一个常规的基于函数的视图和我们之前介绍的装饰器@api_view.在你的snippets/views.py添加: from rest_framework.decorators import api_view from rest_f

05_Tutorial 5: Relationships &amp; Hyperlinked APIs

1.关系和超链接 0.文档 https://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/ https://q1mi.github.io/Django-REST-framework-documentation/tutorial/5-relationships-and-hyperlinked-apis_zh/ 1.效果 2.name用法,配合reverse 第一,我们使用REST框架的reve

Django REST framework 第五章 Relationships &amp; Hyperlinked APIs

到目前为止,API内部的关系是使用主键来代表的.在这篇教程中,我们将提高API的凝聚力和可发现性,通过在相互关系上使用超链接. Creating an endpoint for the root of our API 现在,我们已经有了snippets和users的终端,但是没有一个单独的终端指向我们的API.使用之前常规的FBV方式和@api_view装饰器创建一个.在你的app的views文件内 from rest_framework.decorators import api_view f

django-rest-framework学习之Relationships &amp; Hyperlinked APIs--2017年4月17日至18日

Relationships & Hyperlinked APIs 参考链接: http://www.weiguda.com/blog/23/ http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/ 目前我们API中的关系用primary keys展示,这部分我们会通过hyperlinking提高我们API的内聚性和扩展性 [1]给API的根节点传建一个端点 在views.py中添加:

django restframework 简单总结

官方文档:http://www.django-rest-framework.org/ model.py class Snippet(models.Model): created = models.DateTimeField(auto_now_add=True) title = models.CharField(max_length=100, blank=True, default='') code = models.TextField() linenos = models.BooleanFiel

python进阶资源

本文为不同阶段的Python学习者从不同角度量身定制了49个学习资源. 初学者 Welcome to Python.org https://www.python.org/ 官方Python站点提供了一个开始使用Python生态系统和学习Python的好方法,包括官方文档. Learning Python The Hard Way https://learnpythonthehardway.org/book/ 一本在线书籍,有付费版与免费版的 Basic Data Types in Python

R TUTORIAL: VISUALIZING MULTIVARIATE RELATIONSHIPS IN LARGE DATASETS

In two previous blog posts I discussed some techniques for visualizing relationships involving two or three variables and a large number of cases. In this tutorial I will extend that discussion to show some techniques that can be used on large datase

MyBatis Tutorial – CRUD Operations and Mapping Relationships – Part 1---- reference

http://www.javacodegeeks.com/2012/11/mybatis-tutorial-crud-operations-and-mapping-relationships-part-1.html CRUD OperationsMyBatis is an SQL Mapper tool which greatly simplifies the database programing when compared to using JDBC directly. Step1: Cre

SSL Programming Tutorial

SSL Programming Tutorial ? Table of Contents [ ? Index       This section demonstrates the implementation of a simple SSL client and server program using OpenSSL APIs. Although SSL client and server programs might differ in their setup and configurat