django-rest-framework 官方文檔記錄

Tutorial 1: Serialization 序列化

安裝基本環(huán)境

pip install django
pip install djangorestframework
pip install pygments  # We'll be using this for the code highlighting

開始 創(chuàng)建測(cè)試環(huán)境

創(chuàng)建一個(gè) django 工程

django-admin.py startproject tutorial

在工程中創(chuàng)建一個(gè) app

python manage.py startapp snippets

tutorial/settings.py 文件中修改:聲明 app (自己創(chuàng)建的 app 和 rest_framework)

INSTALLED_APPS = (
    ...
    'rest_framework',
    'snippets.apps.SnippetsConfig',
)

創(chuàng)建 Model 模塊

修改 snippets/models.py 文件:

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())


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.BooleanField(default=False)
    language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
    style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)

    class Meta:
        ordering = ('created',)

將創(chuàng)建的 Model 建立相應(yīng)的 db 表,更新數(shù)據(jù)庫:

python manage.py makemigrations snippets
python manage.py migrate

Creating a Serializer class 創(chuàng)建序列化器類

snippets app 目錄下創(chuàng)建 serializers.py:

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES


class SnippetSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    code = serializers.CharField(style={'base_template': 'textarea.html'})
    linenos = serializers.BooleanField(required=False)
    language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
    style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Snippet.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

Working with Serializers 使用 序列化器類

開啟 shell
python manage.py shell

創(chuàng)建 model 對(duì)象,保存到數(shù)據(jù)庫中:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

snippet = Snippet(code='foo = "bar"\n')
snippet.save()

snippet = Snippet(code='print "hello, world"\n')
snippet.save()

序列化對(duì)象:將 model 對(duì)象轉(zhuǎn)化為 python 基本數(shù)據(jù)類型

serializer = SnippetSerializer(snippet)
serializer.data
# {'title': '', 'id': 3, 'code': 'create by new\n', 'style': 'friendly', 'language': 'python', 'linenos': False}

將 python 基本數(shù)據(jù),渲染成 json

content = JSONRenderer().render(serializer.data)
content
# b'{"id":3,"title":"","code":"create by new\\n","linenos":false,"language":"python","style":"friendly"}'

反序列化 json-》object

from django.utils.six import BytesIO

stream = BytesIO(content)
data = JSONParser().parse(stream)

將一個(gè)反序列化出來的 object 存到數(shù)據(jù)庫中:

serializer = SnippetSerializer(data=data) # data 是 json->object 轉(zhuǎn)化出來的 object
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
# <Snippet: Snippet object>

查詢一組數(shù)據(jù):

serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('langua......

Using ModelSerializers 使用 模型序列化

將原來的 snippets/serializers.py 文件內(nèi)容替換為:

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES

class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

使用這個(gè)的一個(gè)好處是,可以直接看到 serializer 實(shí)例的 屬性 by printing its representation:

python manage.py shell


from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))
# SnippetSerializer():
#    id = IntegerField(label='ID', read_only=True)
#    title = CharField(allow_blank=True, max_length=100, required=False)
#    code = CharField(style={'base_template': 'textarea.html'})
#    linenos = BooleanField(required=False)
#    language = ChoiceField(choices=[('Clipper', 'FoxPro'), ('Cucumber', 'Gherkin'), ('RobotFramework', 'RobotFramework'), ('abap', 'ABAP'), ('ada', 'Ada')...
#    style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...

需要注意的是 ModelSerializer 類沒有做什么特殊的處理,他只是一個(gè) Serializer 類的簡(jiǎn)化:

  1. An automatically determined set of fields.
  2. Simple default implementations for the create() and update() methods.

Writing regular Django views using our Serializer 使用我們定義的 可序列化對(duì)象編寫正常的 django View

下面的例子不使用 rest-framework 的特性,按照 django 的方法來建立 view

創(chuàng)建一個(gè) HttpResponse 的子類,用來將 data-》 json

snippets/views.py:

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer

class JSONResponse(HttpResponse):
    """
    An HttpResponse that renders its content into JSON.
    """
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

api: 獲取已存在的 snippets ,或者創(chuàng)建新的 snippets

@csrf_exempt
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return JSONResponse(serializer.data)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data, status=201)
        return JSONResponse(serializer.errors, status=400)

csrf_exempt 表示 POST 不需要 CSRF token,通常我們不會(huì)這樣做,rest-framework 中對(duì)于這個(gè)有更好的解決方案,這里只是一個(gè)簡(jiǎn)單的例子。

api:獲取一個(gè)獨(dú)立的 snippets,用于 retrieve, update or delete

@csrf_exempt
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return JSONResponse(serializer.data)

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(snippet, data=data)
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data)
        return JSONResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        snippet.delete()
        return HttpResponse(status=204)

聲明上面的 view snippets/urls.py: ( wire these views up)

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

聲明 url (wire up the root urlconf) tutorial/urls.py:

from django.conf.urls import url, include

urlpatterns = [
    url(r'^', include('snippets.urls')),
]

Tutorial 2: Requests and Responses 請(qǐng)求和回復(fù)

Request objects

rest-framework 采用 Request 對(duì)象,它繼承自 HttpRequest,提供了更加靈活的請(qǐng)求解析

其核心是屬性: request.data

request.POST  # Only handles form data.  Only works for 'POST' method.
request.data # Handles arbitrary data.  Works for 'POST', 'PUT' and 'PATCH' methods.

Response objects

return Response(data)  # Renders to content type as requested by the client.

Status codes

status module 提供了請(qǐng)求code, 比如:HTTP_400_BAD_REQUEST

這樣比直接使用 數(shù)字code 要更加易懂

Wrapping API views 包裝 API 視圖

兩種包裝方式:

  1. @api_view 修飾方法視圖
  2. APIView 包裝以類為視圖的api

包裝提供了一些新的特性,比如

  1. 確認(rèn)視圖接收了 Request 實(shí)例, 修改 Response 。
  2. 返回 405 Method Not Allowed
  3. 捕獲 ParseError

Pulling it all together 使用上面介紹的 rest-framework 的特性編寫程序

修改 snippets/views.py: 1. 去除 JSONResponse 2. 修改 view

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    List all snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a snippet instance.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

優(yōu)點(diǎn):

  1. 代碼更加簡(jiǎn)潔
  2. 使用 HTTP_400_BAD_REQUEST 而不是 400

Adding optional format suffixes to our URLs 給 url 添加后綴

修改 view:添加 format 參數(shù)

def snippet_list(request, format=None):
def snippet_detail(request, pk, format=None):

修改 urls.py

urlpatterns = format_suffix_patterns(urlpatterns)

發(fā)起請(qǐng)求回去不同的數(shù)據(jù)格式:

  1. 設(shè)置請(qǐng)求頭

     Accept:application/json  # Request JSON
     Accept:text/html         # Request HTML
    
  2. 使用 url 后綴

     http http://127.0.0.1:8000/snippets.json  # JSON suffix
     http http://127.0.0.1:8000/snippets.api   # Browsable API suffix
    

Tutorial 3: Class-based Views 類視圖

Rewriting our API using class-based views 重寫 view

views.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class SnippetList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class SnippetDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

修改 urls.py :

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

urlpatterns = [
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

Using mixins

使用類視圖好處:

  1. 可復(fù)用
  2. create/retrieve/update/delete 操作在 rest-framework 中都有相應(yīng)的封裝類

修改 views.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

添加了基本類:GenericAPIView

mixins 方法擴(kuò)展類: ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin

Using generic class-based views 使用 generic 基本類

使用 mixin 類能夠簡(jiǎn)化很多代碼,但是可以做到更加簡(jiǎn)潔,使用包含了 mixin 功能的 generic 類

修改 views.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

Tutorial 4: Authentication & Permissions 認(rèn)證和權(quán)限

目的:

  1. Code snippets are always associated with a creator.
  2. Only authenticated users may create snippets.
  3. Only the creator of a snippet may update or delete it.
  4. Unauthenticated requests should have full read-only access.

Adding information to our model 修改 model

修改 Snippet/models.py: 添加兩個(gè)屬性

owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
highlighted = models.TextField()

添加 保存方法:

from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight

def save(self, *args, **kwargs):
    """
    Use the `pygments` library to create a highlighted HTML
    representation of the code snippet.
    """
    lexer = get_lexer_by_name(self.language)
    linenos = self.linenos and 'table' or False
    options = self.title and {'title': self.title} or {}
    formatter = HtmlFormatter(style=self.style, linenos=linenos,
                              full=True, **options)
    self.highlighted = highlight(self.code, lexer, formatter)
    super(Snippet, self).save(*args, **kwargs)

修改完數(shù)據(jù)后更新數(shù)據(jù)庫:這里更新是直接刪除舊的數(shù)據(jù)庫,創(chuàng)建新的數(shù)據(jù)庫

rm -f tmp.db db.sqlite3
rm -r snippets/migrations
python manage.py makemigrations snippets
python manage.py migrate

創(chuàng)建用戶:

python manage.py createsuperuser

Adding endpoints for our User models 添加用戶控制入口

serializers.py: 添加 User 序列化器

from django.contrib.auth.models import User

class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

    class Meta:
        model = User
        fields = ('id', 'username', 'snippets')

添加 User 對(duì)應(yīng)的 View,修改 views.py:

from django.contrib.auth.models import User
from snippets.serializers import UserSerializer


class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

添加 url urls.py

url(r'^users/$', views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

Associating Snippets with Users 關(guān)聯(lián) Snippets 和 users

修改 views.py 中的 SnippetList 類:重寫下面的方法,讓

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)

Updating our serializer 更新 序列化器

上面的代碼將 Snippets 和創(chuàng)建它的 user 關(guān)聯(lián)在一起,下面修改 序列化器:添加 field

owner = serializers.ReadOnlyField(source='owner.username')

Adding required permissions to views 添加請(qǐng)求權(quán)限到 views

rest-framework 中有很多權(quán)限類用于限制哪些用戶可以請(qǐng)求views,下面我們只用 IsAuthenticatedOrReadOnly 來設(shè)置權(quán)限

views.py 中添加 SnippetList ,SnippetDetail 類屬性

from rest_framework import permissions

permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

Adding login to the Browsable API 添加游覽器登入api

修改 urls.py 添加 登入視圖url:

urlpatterns += [
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
]

Object level permissions 對(duì)象級(jí)別的權(quán)限

下面設(shè)置權(quán)限: 創(chuàng)建 Snippets 的用戶才能修改這個(gè) Snippets

創(chuàng)建 snippets/permissions.py: 添加自定義的權(quán)限類

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Write permissions are only allowed to the owner of the snippet.
        return obj.owner == request.user

將權(quán)限添加到 SnippetDetail 中 views.py:

from snippets.permissions import IsOwnerOrReadOnly

permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                      IsOwnerOrReadOnly,)

Now, if you open a browser again, you find that the 'DELETE' and 'PUT' actions only appear on a snippet instance endpoint if you're logged in as the same user that created the code snippet.

Authenticating with the API 認(rèn)證api

目前位置我們還沒有設(shè)置任何 authentication classes ,和權(quán)限有關(guān)的類,所以目前這個(gè)工程的默認(rèn)認(rèn)證類是:SessionAuthentication,BasicAuthentication

可以在請(qǐng)求時(shí)設(shè)置 Basic Auth: 用戶名:密碼 訪問api

Tutorial 5: Relationships & Hyperlinked APIs 關(guān)系和超鏈接 APIs

Creating an endpoint for the root of our API 為接口創(chuàng)建一個(gè)入口

添加下面代碼:snippets/views.py

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)
    })

上面代碼

  1. 使用了 rest-framework 提供的 reverse 方法來轉(zhuǎn)化url
  2. 其對(duì)應(yīng)的 URL 模版,我們會(huì)在后面的代碼中看到 snippets/urls.py

Creating an endpoint for the highlighted snippets

添加 snippets/views.py:

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)

添加 snippets/urls.py:

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

Hyperlinking our API 為 api 創(chuàng)建超級(jí)鏈接

處理 實(shí)體類 之間的關(guān)系有很多種方式:

  1. 使用主鍵
  2. Using hyperlinking between entities. 使用超級(jí)鏈接
  3. Using a unique identifying slug field on the related entity.
  4. Using the default string representation of the related entity.
  5. Nesting the related entity inside the parent representation.
  6. Some other custom representation.

下面使用超級(jí)鏈接的方式來處理。

修改 序列化器(serializers) 繼承 HyperlinkedModelSerializer

HyperlinkedModelSerializer 和 ModelSerializer 的區(qū)別:

  1. It does not include the id field by default. 默認(rèn)不包含 id
  2. It includes a url field, using HyperlinkedIdentityField。 包含了 url 屬性
  3. Relationships use HyperlinkedRelatedField, instead of PrimaryKeyRelatedField。 關(guān)系維護(hù)使用 HyperlinkedRelatedField

修改 snippets/serializers.py:

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

Making sure our URL patterns are named 確保 url 中定義了參數(shù) name

snippets/urls.py:

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 添加分頁

tutorial/settings.py :

REST_FRAMEWORK = {
    'PAGE_SIZE': 10
}

Tutorial 6: ViewSets & Routers

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容