티스토리 뷰
Adding information to our model
from django.db import models
from pygments.lexers import get_all_lexers, get_lexer_by_name
from pygments.styles import get_all_styles
from pygments.formatters.html import HtmlFormatter
from pygments import highlight
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):
owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
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)
highlighted = models.TextField()
class Meta:
ordering = ['created']
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 = 'table' if self.linenos else False
options = {'title': self.title} if self.title else {}
formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True, **options)
self.highlighted = highlight(self.code, lexer, formatter)
super(Snippet, self).save(*args, **kwargs)
Adding endpoints for our User models
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']
snippets 필드는 reverse relationship이기 때문에, ModelSerializer를 사용할 때 기본적으로 포함되지 않으므로, 명시적으로 정의.
# views.py
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# urls.py
from django.urls import path
from snippets import views
urlpatterns = [
path('users/', views.UserList.as_view()),
path('users/<int:pk>/', views.UserDetail.as_view()),
]
Associating Snippets with Users
새로운 Snippet을 생성할 때 생성한 user를 같이 저장.
.perform_create() 메서드를 사용.
class SnippetList(generics.ListCreateAPIView):
"""
List all code snippets, or create a new snippet
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
create() 메서드가 owner 필드를 request 데이터에 추가하여 전송.
위의 내용을 반영하기 위해 SnippetSerializer 수정.
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
fields = ['id', 'owner', 'title', 'code', 'linenos', 'language', 'style']
source argument는 Django의 template language가 사용되어지는 것과 비슷한 방식으로 사용되어짐.
ReadOnlyField는 deserialized 될 때 모델 인스턴스를 업데이트하기 위해 사용되지 않음. CharField(read_only=True)로도 표현 가능.
Adding required permissions to views
class SnippetList(generics.ListCreateAPIView):
"""
List all code snippets, or create a new snippet
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
"""
Retrieve, update or delete a code snippet.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
Adding login to the Browsable API
# root urls.py
urlpatterns += [
path('api-auth/', include('rest_framework.urls')),
]
'api-auth' 주소는 원하는 주소로 수정 가능
Object level permissions
# 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
class SnippetList(generics.ListCreateAPIView):
"""
List all code snippets, or create a new snippet
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOny]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
"""
Retrieve, update or delete a code snippet.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOny]
Authenticating with the API
기본적으로 SessionAuthentication과 BasicAuthentication이 적용됨
아래와 같이 settings.py에 명시적으로 설정도 가능
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
}
Welcome! — Pygments
Welcome! This is the home of Pygments. It is a generic syntax highlighter suitable for use in code hosting, forums, wikis or other applications that need to prettify source code. Highlights are: a wide range of over 300 languages and other text formats is
pygments.org
https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/
4 - Authentication and permissions - Django REST framework
Currently our API doesn't have any restrictions on who can edit or delete code snippets. We'd like to have some more advanced behavior in order to make sure that: Code snippets are always associated with a creator. Only authenticated users may create snipp
www.django-rest-framework.org
https://www.django-rest-framework.org/api-guide/authentication/
Authentication - Django REST framework
www.django-rest-framework.org
'Django' 카테고리의 다른 글
ViewSets & Routers (0) | 2019.08.29 |
---|---|
Relationships & Hyperlinked APIs (0) | 2019.08.29 |
Rest Framework Views (0) | 2019.08.29 |
Serializer (0) | 2019.08.29 |
클래스 필터링, 검색, 정렬의 이해 (0) | 2019.08.28 |