API ์๋ฒ์ ๋์ ์๋ฆฌ
- Create
- Read
- Update
- Delete
API ์๋ฒ์ ์ด์ ์๋ฆฌ
- Authentication
- ์๋น์ค๋ฅผ ์ด์ฉํ ๋ ์ฌ์ฉ์๊ฐ ์ด๋ ์ ๋์ ๊ถํ์ด ์์์ ์์ฒญํ๋ ๊ณผ์
- Permission
- ์๋น์ค๋ฅผ ์ด๋ ์ ๋๋ก ์ด์ฉํ ์ ์๋์ง์ ๋ํ ๊ถํ
- ์๋น์ค๋ฅผ ์ด๋ ์ ๋๋ก ์ด์ฉํ ์ ์๋์ง์ ๋ํ ๊ถํ
๋๋ถ๋ถ์ ์น ์๋น์ค์์ ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ๋์ผํ ๊ถํ์ ์ฃผ์ง ์๋๋ค.
์ธ์ฆ ์์ฒญ์ด ์์ ๋ ์ธ์ฆ์ด ์ฑ๊ณต์ ํ ๊ฒฝ์ฐ์ ์คํจํ ๊ฒฝ์ฐ ๋ชจ๋
request.user
์ request.auth
๋ ๊ฐ์ ๋ณ์๊ฐ ์์ฑ๋๋ค.
์ธ์ฆ์ด ์ฑ๊ณตํ ๊ฒฝ์ฐ ์ ์ ์ ๋ํ๊ฐ์ธ ์์ด๋๊ฐ request.user
์ ์ ์ฅ๋๊ณ
์ธ์ฆ์ ์ฑ๊ณตํ ์ ์ ์ ๊ถํ์ด request.auth
์ ์ ์ฅ๋๋ค.
์ธ์ฆ์ด ์คํจํ ๊ฒฝ์ฐ AnonymousUser
๊ฐ request.user
์ ์ ์ฅ๋๊ณ
request.auth
๋ None
๊ฐ์ ๊ฐ์ง๊ณ ์๊ฒ ๋๋ค.
์ธ์ฆ์ ์คํจํ์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์ค์ ๊ณผ ๋ค๋ฅด๊ฒ ๋ค๋ฅธ ๊ฐ์ ์ ๋ฌํ๊ณ ์ถ๋ค๋ฉด
settings.py
์์ UNAUTHENTICATED_USER
์ UNAUTHENTICATED_TOKEN
๊ฐ์ ์์ ํ๋ฉด ๋๋ค.
settings.py
์ REST_FRAMEWORK
๋์
๋๋ฆฌ๋ฅผ ์์ฑํ๊ณ ์๋์ ๊ฐ์ด
๊ธฐ๋ณธ ๊ฐ์ผ๋ก ์ฌ์ฉํ๊ธธ ์ํ๋ ์ธ์ฆ ๋ฐฉ์์ ์์ฑํ๋ฉด ๋๋ค.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
rest_framework
์ authentication
์์ ์ฌ์ฉํ ์ธ์ฆ ๋ฐฉ์์ import
ํด์ฃผ๊ณ
authentication_classes
๋ฆฌ์คํธ์ ์ถ๊ฐํ ์ธ์ฆ ๋ฐฉ์์ ์์ฑํ๋ฉด ๋๋ค.
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
content = {
'user': unicode(request.user),
'auth': unicode(request.auth),
}
return Response(content)
๋ฐ์ฝ๋ ์ดํฐ(@
)๋ฅผ ์ฌ์ฉํด ๊ตฌํํ๋ฉฐ ์๋์ ๊ฐ์ด @authentication_classes
์
์์ CBV
์์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋ง์ฐฌ ๊ฐ์ง๋ก ์ฌ์ฉํ ์ธ์ฆ ๋ฐฉ์์ ์์ฑํ๋ฉด ๋๋ค.
@api_view(['GET'])
@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
content = {
'user': unicode(request.user),
'auth': unicode(request.auth),
}
return Response(content)
HTTP 401 Unauthorized
HTTP 403 Permission Denied
BasicAuthentication
TokenAuthentication
SessionAuthentication
RemoteUserAuthentication
Custom authentication
HTTP Protocol
์์ฒด ๊ธฐ๋ณธ ์ธ์ฆ์ ๊ธฐ๋ฐํ ์ธ์ฆ ๋ฐฉ์
HTTP
์ ์ด ํค๋๋ก ๋๊ธด ID
, PW
๋ฅผ base64๋ก ์ธ์ฝ๋ฉํ๋ค.
BasicAuthentication
์ ๋ณด์ํ ๋ฐฉ์
์ฌ์ฉ์๊ฐ ์ธ์ฆ์ ์์ฒญํ๋ฉด ํด๋น ์ฌ์ฉ์์๊ฒ ์ ์ผํ Key ๊ฐ์ ๋ฐ๊ธํ๋ค.
Token ํค๋์์ ์ธ์ฆ์ ์ํํ๋ค.
๋ก๊ทธ์ธ์ด ๋ ๋๋ง๋ค ์ ์ฅ๋๋ Session
์ ๋ณด๋ฅผ ์ฐธ์กฐํ์ฌ ์ธ์ฆํ๋ค.
์ฌ์ฉ์ ์ ๋ณด๊ฐ ๋ค๋ฅธ ์๋น์ค์์ ๊ด๋ฆฌ๋ ๋ ์ฐ์ด๋ ์ธ์ฆ ๋ฐฉ์์ด๋ค.
REMOTE_USER ํค๋์์ ์ธ์ฆ์ ์ํํ๋ค.
์ด์ ๊ฐ์์์ ์งํํ๋ UserPost
๋ชจ๋ธ์ ์ฌ์ฉํ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ํ๋ก์ ํธ ์์ฑ ๋ฐ ์ฑ ์์ฑ
settings.py
์์ฑmodels.py
์์ฑ ๋ฐadmin.py
์ฐ๊ฒฐmigrate
๋ช ๋ น์ด ์คํserializer.py
์์ฑviews.py
์์ฑ- ์ฑ์
urls.py
์์ฑ ๋ฐ ํ๋ก์ ํธ์urls.py
์ ์ฐ๊ฒฐ
serializer.py
๋ฅผ ์๋์ ๊ฐ์ด ์์ ํ๋ค.
class UserPostSerializer(serializers.ModelSerializer):
author_name = serializers.ReadOnlyField(
source='author.username'
)
class Meta:
model = UserPost
fields = ['pk','author_name', 'title', 'body']
์๋์ ๊ฐ์ด ์ค์ ํ ํ๋๊ฐ ์ ๋ณด์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ author
๋ฅผ ReadOnly๋ก ๋ณ๊ฒฝํด ์ ํํ๋ Form
์ด ์ฌ๋ผ์ก๋ค.
views.py
์์ perform_create
๋ผ๋ ํจ์๋ฅผ ์ด์ฉํด ๊ตฌํํ๋ค.
serializer
์ save
ํจ์๋ฅผ ์ด์ฉํด author
ํ๋๋ฅผ self.request.user
๋ก ์ ์ฅํ๋ค.
class UserPostViewSet(viewsets.ModelViewSet):
queryset = UserPost.objects.all()
serializer_class = UserPostSerializer
filter_backends = [SearchFilter]
search_fields = ('title', 'body')
def get_queryset(self):
qs = super().get_queryset()
if self.request.user.is_authenticated:
qs = qs.filter(author=self.request.user)
else:
qs = qs.none()
return qs
def perform_create(self, serializer):
serializer.save(author=self.request.user)
์๋์ ๊ฐ์ด settings.py
๋ฅผ ์์ ํด์ค๋ค.
DEBUG = False
ALLOWED_HOSTS = ['*']
์์์ ์ค๋ช
ํ ๊ฒ๊ณผ ๊ฐ์ด ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋ฑ๋ก์ด ๊ฐ๋ฅํ๋ค.
- ์ ์ญ์ผ๋ก ์ธ์ฆ ๋ฐฉ์ ๋ฑ๋กํ๊ธฐ
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
views.py
์์ ์ธ์ฆ ๋ฐฉ์ ๋ฑ๋กํ๊ธฐ
...
from rest_framework.authentication \
import BasicAuthentication, SessionAuthentication
class UserPostViewSet(viewsets.ModelViewSet):
authentication_classes = [BasicAuthentication, SessionAuthentication]
queryset = UserPost.objects.all()
serializer_class = UserPostSerializer
...
- ์ด์ ๊ณผ ๊ฐ์ด
POST
์์ฒญ ๋ณด๋ด๊ธฐ
์ด์ ๊ณผ ๊ฐ์ด POST
์์ฒญ์ ๋ณด๋ผ๊ฒฝ์ฐ HTTP 500 Server Error
๊ฐ ๋ฐ์ํ๋ค.
์๋ํ๋ฉด ์์ฒญ์ ๋ณด๋ธ ์ฌ์ฉ์๊ฐ ๋๊ตฌ์ธ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.
- ์ธ์ฆ ์ ๋ณด์ ํจ๊ป
POST
์์ฒญ ๋ณด๋ด๊ธฐ
http --auth <username>:<password> --form POST http://127.0.0.1:8000/userpost/ title="" body=""
์์ ๊ฐ์ด POST
์์ฒญ์ด ์ ์ฒ๋ฆฌ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.