django-rest-framework公式ドキュメント記録
27694 ワード
Tutorial 1:Serializationシーケンス化
インストール環境
pip install django
pip install djangorestframework
pip install pygments # We'll be using this for the code highlighting
テスト環境の作成を開始
djangoプロジェクトの作成django-admin.py startproject tutorial
プロジェクトにappを作成するpython manage.py startapp snippets
tutorial/settings.py
ファイルでの変更:app(自分で作成したappとrest_framework)を宣言します.INSTALLED_APPS = (
...
'rest_framework',
'snippets.apps.SnippetsConfig',
)
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',)
作成したModelは、対応するdbテーブルを作成し、データベースを更新します.python manage.py makemigrations snippets
python manage.py migrate
Creating a Serializer classシーケンサクラスの作成
snippets
appディレクトリの下に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
モデルオブジェクトを作成し、データベースに保存します.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"
')
snippet.save()
snippet = Snippet(code='print "hello, world"
')
snippet.save()
シーケンス化オブジェクト:modelオブジェクトをpython基本データ型に変換するmodelオブジェクトserializer = SnippetSerializer(snippet)
serializer.data
# {'title': '', 'id': 3, 'code': 'create by new
', 'style': 'friendly', 'language': 'python', 'linenos': False}
python基本データをjsonにレンダリングcontent = JSONRenderer().render(serializer.data)
content
# b'{"id":3,"title":"","code":"create by new\
","linenos":false,"language":"python","style":"friendly"}'
逆シーケンス化json-』objectfrom django.utils.six import BytesIO
stream = BytesIO(content)
data = JSONParser().parse(stream)
逆シーケンス化されたobjectをデータベースに保存します.serializer = SnippetSerializer(data=data) # data json->object object
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"
'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
#
データのセットを検索するには、次の手順に従います.serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"
'), ('linenos', False), ('langua......
Using ModelSerializersモデルを使用してシーケンス化
元のsnippets/serializers.py
ファイルの内容を次のように置き換えます.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')
これを使用する利点の1つは、serializerインスタンスのプロパティ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クラスは特別な処理をしていません.彼はSerializerクラスの簡略化にすぎません.
pip install django
pip install djangorestframework
pip install pygments # We'll be using this for the code highlighting
django-admin.py startproject tutorial
python manage.py startapp snippets
INSTALLED_APPS = (
...
'rest_framework',
'snippets.apps.SnippetsConfig',
)
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',)
python manage.py makemigrations snippets
python manage.py migrate
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
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"
')
snippet.save()
snippet = Snippet(code='print "hello, world"
')
snippet.save()
serializer = SnippetSerializer(snippet)
serializer.data
# {'title': '', 'id': 3, 'code': 'create by new
', 'style': 'friendly', 'language': 'python', 'linenos': False}
content = JSONRenderer().render(serializer.data)
content
# b'{"id":3,"title":"","code":"create by new\
","linenos":false,"language":"python","style":"friendly"}'
from django.utils.six import BytesIO
stream = BytesIO(content)
data = JSONParser().parse(stream)
serializer = SnippetSerializer(data=data) # data json->object object
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"
'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
#
serializer = SnippetSerializer(Snippet.objects.all(), many=True)
serializer.data
# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"
'), ('linenos', False), ('langua......
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')
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')...
Writing regular Django views using our Serializer我々が定義したシーケンス可能なオブジェクトを使用して通常のdjango Viewを記述
次の例ではrest-frameworkの特性を用いずdjangoの方法でviewを確立する
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を取得するか、新しい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を必要としないことを示しています.通常、rest-frameworkでは、これに対してより良い解決策があります.ここでは簡単な例にすぎません.api:retrieve,update or delete用の独立したsnippetsを取得
@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[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リクエストと返信
Request objects
rest-frameworkは、HttpRequestから継承されたRequestオブジェクトを採用し、より柔軟なリクエスト解析を提供します.
コアは属性: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は、要求codeを提供します.例えば、HTTP_400_BAD_REQUEST
デジタルコードを直接使うよりも分かりやすい
Wrapping API viewsパッケージAPIビュー
2種類の包装方式:
request.POST # Only handles form data. Only works for 'POST' method.
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
return Response(data) # Renders to content type as requested by the client.
@api_view
修飾方法ビューAPIView
パッケージクラスをビューとするapi 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)
メリット:
Adding optional format suffixes to our URLs urlに接尾辞を追加
viewの変更view:formatパラメータの追加formatパラメータの追加
def snippet_list(request, format=None):
def snippet_detail(request, pk, format=None):
修正
urls.py
urlpatterns = format_suffix_patterns(urlpatterns)
要求を開始して、異なるデータフォーマットに戻ります.
Accept:application/json # Request JSON
Accept:text/html # Request HTML
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 Viewクラスビュー
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[0-9]+)/$', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Using mixins
クラスビューを使用するメリット:
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)
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[0-9]+)/$', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
修正
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)
基本クラスが追加されました:General APIView
mixinsメソッド拡張クラス:ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
Using generic class-based views generic基本クラスの使用
mixinクラスを使用すると多くのコードを簡略化できますが、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認証と権限
目的:
Adding information to our model修正model
変更
Snippet/models.py
:2つの属性を追加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)
データの変更後にデータベースを更新する:ここで更新は古いデータベースを直接削除し、新しいデータベースを作成します.
rm -f tmp.db db.sqlite3
rm -r snippets/migrations
python manage.py makemigrations snippets
python manage.py migrate
ユーザーの作成:
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対応の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[0-9]+)/$', views.UserDetail.as_view()),
Associating Snippets with Users関連Snippetsとusers
views.py
の中のSnippetList
類を修正します:次の方法を書き直して、def perform_create(self, serializer):
serializer.save(owner=self.request.user)
Updating our serializer更新シーケンサ
上のコードはSnippetsと作成したuserを関連付け、次にシーケンス化器を変更します:fieldを追加
owner = serializers.ReadOnlyField(source='owner.username')
Adding required permissions to views viewsリクエスト権限をviewsに追加
rest-frameworkにはviewsを要求できるユーザーを制限する権限クラスがたくさんあります.次にIsAuthenticatedOrReadOnlyのみで権限を設定します.
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レベルpermissionsオブジェクトレベルの権限
次のパーミッションを設定します.Snippetsを作成したユーザーは、このSnippetsを変更できます.
作成
snippets/permissions.py
:カスタム権限クラスの追加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
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認証api
現在の場所ではauthentication classesは設定されていません.権限に関連するクラスです.そのため、現在のエンジニアリングのデフォルト認証クラスは、SessionAuthentication、BasicAuthenticationです.
要求時にBasic Authを設定できます:ユーザー名:パスワードアクセスapi
Tutorial 5:Relationships&Hyperlinked APIs関係とハイパーリンクAPIs
Creating an endpoint for the root of our APIインタフェースのエントリを作成
次のコードを追加します: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)
})
上のコード
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)
})
reverse
法を用いてurl 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[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
Hyperlinking our API apiへのハイパーリンクの作成
エンティティ・クラス間の関係を処理するには、次のような方法があります.
次はハイパーリンクで処理します.
シーケンサの変更HyperlinkedModelSerializerの継承
HyperlinkedModelSerializerとModelSerializerの違い:
修正
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にパラメータ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[0-9]+)/$',
views.SnippetDetail.as_view(),
name='snippet-detail'),
url(r'^snippets/(?P[0-9]+)/highlight/$',
views.SnippetHighlight.as_view(),
name='snippet-highlight'),
url(r'^users/$',
views.UserList.as_view(),
name='user-list'),
url(r'^users/(?P[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
}