마음만은 한량 햄버거 메뉴
반응형

REST Framework Tutorial - 4 

 

 
 

 

우리가 만든 API는 데이터를 편집하거나,

삭제하는데 있어 아무 제한이 없다. 

 

다음과 같은 사항을 확실히 하기 위해

더 나은 기능들을 추가해보자.

 

 

  • 데이터는 항상 생성자와 연관되어 있다.
  • 인증받은 사용자만이 데이터를 생성할 수 있다.
  • 작성자만이 수정하거나 삭제할 수 있다.
  • 인증받지 않은 사용자는 읽기 전용만 가능하다.
 
 

Adding information to our model

  • Snippet 모델을 수정하자. 두 개의 필드를 추가한다.

  • 이 필드 중 하나(owner)는 데이터를 만든 사용자를
    나타내는데 사용된다.

  • 다른 필드는 HTML의 하이라이트 부분을 저장하는데
    사용한다.

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

 

  • 모델 저장 시, 하이라이트 부분의 코드를 pygments
    라이브러리를 이용해 하이라이트 필드에 저장되도록
    해야한다.

  • 다음 라이브러리들을 Import하자.

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

 

  • 이제는 모델 클래스에 save메서드를 추가할 수 있다.

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)

 

  • 위의 작업이 완료되면, 데이터베이스를 업데이트 하자.

 

  • 일반적으로 업데이트 시, migration을 이용하지만,
    이번 튜토리얼에서는 데이터베이스를 삭제하고 다시
    시작해보자.

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

 

  • API 테스트를 위해 몇 명의 사용자를 생성할 수 있다.

 

  • 가장 빠른 방법은 createsuperuser를 이용하는 것이다.

 

>>> python manage.py createsuperuser

 

Adding endpoints for our User
models

  • 이제 사용자를 추가했으니 사용자를 보여주는
    API를 추가하는 것이 좋다.

 

  • 새로운 serializer.py에 serializer를 추가하자.

 

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는 User 모델과 역방항 관계이기 때문에,
    Modelserializer 클래스를 이용할 때
    기본적으로
    포함되어 있지 않다.

 

  • 그래서 명시적으로 필드를 지정했다.

 

  • 우리는 사용자와 관련된 읽기 전용 view만 사용하면
    되므로, 제네릭 클래스 기반 뷰 중 ListAPIView 및
    RetrieveAPIView를 사용한다.

 

from django.contrib.auth.models import User from snippets.serializer import UserSerializer  class UserList(generics.ListAPIView):     queryset = User.objects.all()     serializer_class = UserSerializer   class UserDetail(generics.RetrieveAPIView):     queryset = User.objects.all()     serializer_class = UserSerializer

 

  • 마지막으로 이러한 view들을 URL conf에서 참조해
    API에 추가해야한다.

 

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

 

Associating Snippets with Users

  • 지금까지 데이터를 생성했지만, 데이터를 생성한
    생성자와 연결할 방법이 없었고, 
    이를 해결하기 위해 
    perform_create 메서드를 오버라이딩한다.

 

  • 이 메서드는 인스턴스 저장 방법을 관리하고, 들어오는
    요청이나 요청된
     URL에서 들어온 정보를 처리한다.

 

  • views.py의 SnippetList 클래스에 다음 내용을 추가한다.

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

 

  • 이제 serializer의 create메서드는 데이터와 함께
    owner 필드가 함께 전달된다.

 

Updating our serializer

  • 이제 데이터와 이를 만든 사용자가 연결되어 있으므로
    SnippetsSerializer를 업데이트해보자.

 

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

 

  • ReadOnlyField는 source 인자를 이용해 특정
    필드를 지정할 수 있다.
  • 마침표 표기 방식을 이용해 속성을 탐색할 수 있다.
    마치 Django의 템플릿 언어와 비슷하다.
  • 이 필드는 타입이 CharField, BooleanField와 달리
    타입이 없으며, 항상 읽기 전용이므로 모델의
    인스턴스를 업데이트 할 때는 사용 할 수 없다.

 

  • CharField(read_only=True)도 동일한 기능을 수행한다.
 
 

Adding required permissions to
views

 

  • 이제 사용자와 데이터가 연결 되었으므로, 인증받은
    사용자만이 데이터를 생성/ 업데이트/ 삭제할 수 있다.

 

  • REST 프레임워크에는 주어진 view에 접근할 수 있는 
    사용자를 제한하는데 사용할 수 있는 많은 클래스를
    제공한다.

 

  • IsAuthenticatedOrReadOnly는 인증 된 요청에
    읽기 - 쓰기 권한이 부여되고 인증되지 않은
    요청에는 읽기 전용 권한이 부여됩니다.

 

  • views.py에 다음 내용을 추가한다.

 

from rest_framework import permissions

 

  • 그리고 SnippetList 클래스와 SnippetDetail 클래스에
    다음 속성을 추가한다.

 

permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

 

Adding login to the Browsable API

  • 이 시점에 브라우저에서 API에 접속해본다면 데이터가
    생성되지 않는 것을 알 수 있다.

 

  • 문제를 해결하기 위해 사용자 로그인 기능이 필요하다.

  • 프로젝트 레벨의 urls.py를 수정해 API 로그인 view를 추가해보자. 

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

 

  • 위의 '^api-auth/'은 우리가 사용하고자 하는 URL이다.

 

  • 이제 브라우저로 다시 API에 접근해보면 오른쪽 상단에
    Login 링크가 보일 것이다. 앞에서 만든 사용자로
    로그인하면
    데이터를 생성할 수 있을 것이다.

 

  • 몇 가지 데이터를 생성하고, '/users/'로 이동해보면
    해당 사용자가 만든 데이터들이 snippets 필드에
    포함된 것을 볼 수 있다.

 

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

 

  • 이제 SnippetDetail view를 편집해 해당 사용자 지정
    권한을 추가한다.

 

permission_classes = (permissions.IsAuthenticatedOrReadOnly,                       IsOwnerOrReadOnly,)

 

  • IsOwnerOrReadOnly 클래스도 Import 한다.
from snippets.permissions import IsOwnerOrReadOnly
  • 이제 브라우저를 열면, 데이터를 만든 사용자에게만
    'DELETE', '
    PUT' 기능이 나타나는 것을 알 수 있다.
 

 

Authenticating with the API

  • API에 대한 권한 설정을 했으므로, 데이터를
    편집하려면 인증 절차가 필요하다.

 

  • 우리는 어떤 인증 클래스도 만들지 않았기때문에,

    기본값 SessionAuthentication과 BasicAuthentication이 적용된다.

 

  • 웹 브라우저로 API를 사용할 때, 로그인할 수 있으며,
    브라우저 세션은 인증 정보를 제공한다.

 

  • 프로그램 상에서 API를 사용할 때,
    인증 정보를 명시적으로 제공해야 한다.

 

  • 인증 없이 데이터를 생성하려고 하면, 다음과 같은
    에러를 보인다.

 

http POST http://127.0.0.1:8000/snippets/ code="print 123"  {     "detail": "Authentication credentials were not provided." }

 

  • 사용자 계정과 비밀번호를 포함해 요청하면 성공한다.

 

http -a admin:password123 POST http://127.0.0.1:8000/snippets/ code="print 789"  {     "id": 1,     "owner": "admin",     "title": "foo",     "code": "print 789",     "linenos": false,     "language": "python",     "style": "friendly" }
반응형
블로그카우, 티스토리 애드센스 강의

웹 개발자가 알려주는 수익형 블로그 고속 성장 A to Z

댓글
위쪽 화살표
로딩바