Translated the API Guide document into Korean.

This commit is contained in:
Kim Do Ky 2018-08-27 13:02:52 +09:00
parent c4b068cfd3
commit 0d3c1ee514
42 changed files with 8084 additions and 0 deletions

View File

@ -0,0 +1,348 @@
# Django REST Framework - Authentication
---
_"Auth needs to be pluggable."_
_"인증은 플러그가 가능해야 합니다."_
_— Jacob Kaplan-Moss, "REST worst practices"_
---
## Authentication(입증)
Authentication은 수신 요청을 요청한 사용자 또는 서명 된 토큰과 같은 식별 자격 증명 세트를 연결하는 메커니즘입니다. 그런 다음 [권한](http://www.django-rest-framework.org/api-guide/permissions/)과 [정책](http://www.django-rest-framework.org/api-guide/throttling/)은 이러한 자격 증명을 사용하여 요청을 허용해야 하는지 결정할 수 있습니다.
REST 프레임워크는 여러가지 인증 스키마를 즉시 제공하며 custom 스키마를 구현할 수도 있습니다.
Authentication은 항상 View의 맨 처음, 권한 및 제한 검사가 수행되기 전에 그리고 다른 코드가 진행되기 전에 실행됩니다.
`request.user`속성은 일반적으로 `contrib.auth`패키지의 `User`클래스 인스턴스로 설정됩니다.
`request.auth` 등록정보는 추가인증 정보에 사용됩니다. 예를 들어, request가 서명 된 인증 토큰을 나타내는데 사용될 수 있습니다.
---
**Note**: 들어오는 request를 허용하거나 거부하지 않는 인증은 request가 수행된 자격 증명을 식별하기만하면 된다는 것을 잊지 마십시오.
API에 대한 사용권한정책을 설정하는 방법에 대한 자세한 내용은 [permissions documentation](http://www.django-rest-framework.org/api-guide/permissions/)를 참조하세요.
---
### How authentication is determined
인증 체계는 항상 클래스 list으로 정의됩니다. REST 프레임워크는 list의 각 클래스에 대해 인증을 시도하고 성공적으로 인증한 첫 번째 클래스의 반환 값을 사용하여 `request.user``request.auth`를 설정합니다.
클래스가 인증되지 않으면 `request.user``django.contrib.auth.AnonymousUser`의 인스턴스로 설정되고 `request.auth``None`으로 설정됩니다.
인증되지 않은 요청에 대한 `request.user`, `request.auth`의 값은 `UNAUTHENTICATED_USER`, `UNAUTHENTICATED_TOKEN` 설정을 사용하여 수정할 수 있습니다.
### Setting the authentication scheme
`DEFAULT_AUTHENTICATION_CLASSES` 설정을 사용하여 기본 인증 구성표를 전역으로 설정할 수 있습니다. 예를 들면.
```python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
```
또한 `APIVIew` CBV를 사용하여 view 단위 또는 view단위로 인증 체계를 구성할 수 있습니다.
```python
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), # `django.contrib.auth.User` instance.
'auth': unicode(request.auth), # None
}
return Response(content)
```
또는 FBV와 함께 `@api_view`데코레이터를 사용하는 경우
```pyhon
@api_view(['GET'])
@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated,))
def example_view(request, format=None):
content = {
'user': unicode(request.user), # `django.contrib.auth.User` instance.
'auth': unicode(request.auth), # None
}
return Response(content)
```
### Unauthorized and Forbidden responses(무단 및 금지된 응답)
인증되지 않은 요청에 권한이 거부되면 적절한 두 가지 오류 코드가 있습니다.
- [HTTP 401 Unauthorized](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2)
- [HTTP 403 Permission Denied](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4)
HTTP 401 응답에는 항상 클라이언트에 인증 방법을 지시하는 `WWW-Authenticate` 헤더가 포함되어야합니다. HTTP 403 응답에는 `WWW-Authenticate` 헤더가 포함되지 않습니다.
사용되는 response의 종류는 인증 체계에 따라 다릅니다. 여러 인증 스키마가 사용 중일 수 있지만, response의 타입을 결정하는데 하나의 스키마만 사용할 수 있습니다. **view에 설정된 첫번째 authentication 클래스는 response 타입을 결정 할 때 사용됩니다.**
request가 성공적으로 인증 될 수 있지만, 여전히 request를 수행할 권한이 거부 된 경우, 인증 스키마에 관계없이 `403 Permission Denied`응답이 항상 사용됩니다.
### Apache mod_wsgi specific configuration
mod_wsgi를 사용하여 Apache에 배포한다면, 권한 부여 헤더는 기본적으로 응용프로그램 수준이 아닌 Apache에서 인증을 처리한다고 가정하므로, 기본적으로 WSGI 응용프로그램에 전달되지 않습니다.
Apache에 배포하고 비 세션 기반 인증을 사용하는 경우 `mod_wsgi`를 명시적으로 구성하여 필요한 헤더를 응용프로그램에 전달해야 합니다. 이는 적절한 컨텍스트에서 `WSGIPassAuthorization`지시문을 지정하고 `On`으로 설정하여 수행할 수 있습니다.
```
# 이것은 서버 설정, 가상 호스트, 디렉토리 또는 .htaccess 중 하나에 들어갈 수 있습니다.
WSGIPassAuthorization On
```
---
## API Reference
### BasicAuthentication
이 인증 체계는 사용자의 사용자 이름과 암호에 대해 서명 된 [HTTP basic Authentication](https://tools.ietf.org/html/rfc2617)을 사용합니다. 기본 인증은 일반적으로 테스트에만 적합합니다.
성공적으로 인증되면 `BasicAuthencation`은 다음 자격 증명을 제공합니다.
- `request.user`는 Django `User`인스턴스가 될 것입니다.
- `request.auth``None`입니다.
권한이 거부 된 인증되지 않은 응답은 적절한 WWW-Authenticate 헤더와 함께 `HTTP 401 Unauthorized` 웅답이 됩니다.
```
WWW-Authenticate: Basic realm="api"
```
**Note**: 프로덕션 환경에서 `BasicAuthentication`을 사용하는 경우 `https`를 통해서만 API를 사용할 수 있어야 합니다. 또한 API 클라이언트가 로그인 할때 항상 사용자 이름과 비밀번호를 다시 요청하고 해당 세부정보를 영구 저장소에 저장하지 않도록 해야합니다.
### TokenAuthentication
이 인증체계는 간단한 토큰 기반 HTTP인증체계를 사용합니다. 토큰 인증은 네이티브 데스크톱 및 모바일 클라이언트와 같은 클라이언트 - 서버 설정에 적합합니다.
`TokenAuthentication` 스키마를 사용하려면 `TokenAuthentication`을 포함하도록 [authentication클래스를 구성](http://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme)하고 `INSTALLED_APPS`설정에 `rest_framework.authtoken`를 추가해야 합니다.
```
INSTALLED_APPS = (
...
'rest_framework.authtoken'
)
```
---
**Note**: 설정을 변경한 후에 `manage.py migrate`를 실행해야합니다. `rest_framework.authtoken`앱은 Django 데이터베이스 마이그레이션을 제공합니다.
---
또한 사용자를 위한 토큰을 만들어야 합니다.
```python
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
```
클라이언트가 인증하려면 토큰 키가 `Authorization` HTTP 헤더에 포함되어야합니다. 키에는 두 문자열을 공백으로 구분하여 문자열 리터럴 "Token"을 prefix로 사용해야합니다. 예:
```
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
```
**Note**: `Bearer`와 같은 헤더에 다른 키워드를 사용하려면 단순히 `TokenAuthentication`을 서브 클래스화하고 `keyword` 클래스 변수를 설정하십시오.
성공적으로 인증되면 `TokenAuthentication`은 다음 자격 증명을 제공합니다.
- `request.user`는 Django `User` 인스턴스가 될 것입니다.
- `request.auth``rest_framework.authtoken.models.Token` 인스턴스가 됩니다.
권한이 거부 된 인증되지 않은 응답은 적절한 WWW-Authenticate 헤더와 함께 `HTTP 401 Unauthorized` 응답이 됩니다. 예:
```
WWW-Authenticate: Token
```
`curl` command line tool은 토큰으로 인증된 API를 테스트 하는데 유용할 수 있습니다. 예:
```
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
```
---
**Note**: 프로덕션 환경에서 `TokenAuthentication`을 사용하는 경우 `https`를 통해서만 API를 사용할 수 있어야 합니다.
---
#### Generating Tokens
##### By using signals
모든 사용자가 자동으로 생선 된 토큰을 갖기를 원하면 사용자의 `post_save`신호를 간단히 잡을 수 있습니다.
```python
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
```
이 코드는 snippet이 설치된 `models.py` 모듈이나 시작시 Django가 가져올 다른 위치에 배치해야 합니다.
이미 일부 사용자를 만든 경우 다음과 같이 모든 기존 사용자에 대한 토큰을 생성 할 수 있습니다.
```python
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
for user in User.objects.all():
Token.objects.get_or_create(user=user)
```
##### By exposing an api endpoint(api 엔드포인트를 노출시킴)
`TokenAuthentication`을 사용할 때 클라이언트가 사용자 이름과 암호가 있는 토큰을 얻을 수 있는 메커니즘을 제공 할 수 있습니다. REST 프레임워크는 이 동작을 제공하는 built-in 뷰를 제공합니다. 그것을 사용하려면 URLconf에 `obtain_auth_token` 뷰를 추가하세요.
```python
from rest_framework.authtoken import views
urlpatterns += [
url(r'^api-token-auth/', views.obtain_auth_token)
]
```
패턴의 URL 부분은 원하는대로 사용할 수 있습니다.
`obtain_auth_token` 뷰는 유효한 `사용자 이름``암호` 필드가 양식 데이터 또는 JSON을 사용하여 뷰에 POST되면 JSON 응답을 리턴합니다.
```
{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }
```
기본 `obtain_auth_token` 뷰는 설정에서 기본 renderer 및 parser 클래스를 사용하는 대신 JSON 요청 및 응답을 명시적으로 사용합니다.
`obtain_auth_token`view의 custom 된 버전이 필요하면 `ObtainAuthToken`view 클래스를 대체하고 URL conf에 대신 사용하세요.
기본적으로 `obtain_auth_token` view에 적용된 사용 권한이나 제한이 없습니다. 제한을 적용하려면 view클래스를 재정의하고 `throttle_classes`속성을 사용하여 view클래스를 포함해야 합니다.
##### With Django admin
관리자 인터페이스를 통해 수동으로 토큰을 생성 할 수도 있습니다. 대규모 사용자 기반을 사용하는 경우, `user` 필드를 `raw_field`로 선언하여 `TokenAdmin` 클래스를 monkey 패치하여 필요에 맞게 custom하는 것이 좋습니다.
`your_app/admin.py`:
```python
from rest_framework.authtoken.admin import TokenAdmin
TokenAdmin.raw_id_fields = ('user',)
```
### SessionAuthentication
이 인증방식은 Django의 기본 세션 백엔드를 인증에 사용합니다. 세션 인증은 웹 사이트롸 동일한 세션 컨텍스트에서 실행되는 AJAX 클라이언트에 적합합니다.
성공적으로 인증되면 `SessionAuthentication`은 다음 자격 증명을 제공합니다.
- `request.use`r는 Django `User` 인스턴스가 될 것입니다.
- `request.auth``None`입니다.
권한이 거부 된 인증되지 않은 응답은 `HTTP 403 Forbidden`응답이 됩니다.
SessionAuthentication과 함께 AJAX 스타일 API를 사용하는 경우 `PUT`, `PATCH`, `POST` 또는 `DELETE` 요청과 같은 **"안전하지 않은"**HTTP 메소드 호출에 유효한 CSRF 토큰을 포함시켜야합니다. 자세한 내용은 [Django CSRF documentation](https://docs.djangoproject.com/en/1.10/ref/csrf/#ajax) 참조
**Warning**: 로그인 페이지를 만들 때 항상 Django의 표준 로그인 view를 사용하세요. 이렇게 하면 로그인view가 올바르게 보호됩니다.
REST 프레임워크의 CSRF 유효성 검사는 동일한 view에 대해 session 및 non-session 기반 인증을 모두 지원해야하므로 표준 Django와 약간 다르게 작동합니다. 즉, 인증 된 요청만 CSRF 토큰이 필요로 하며 익명 요청은 CSRF 토큰 없이 전송될 수 있습니다. 이 동작은 항상 CSRF 유효성 검사가 적용된 로그인 View에는 적합하지 않습니다.
## Custom authentication
사용자 정의 인증 체계를 구현하려면 `BaseAuthentication`을 서브 클래스화하고 `.authenticate(self, request)` 메소드를 대체하십시오. 이 메소드는 인증에 성공하면 2-tuple(user, auth)을 반환하고, 그렇지 않으면 `None`을 반환햐야 합니다.
`None`을 반환하는 대신 상황에 따라 `.authenticate()` 메서드에서 `AuthenticationFailed` 예외를 발생 시킬 수 있습니다.
일반적으로 취해야 할 접근 방식은 다음과 같습니다.
- 인증을 시도하지 않으면 `None`을 반환합니다. 사용중인 다른 인증 체계도 계속 검사됩니다.
- 인증을 시도했지만 실패한 경우 `AuthenticationFailed` 예외를 발생시킵니다. 권한 확인과 관계없이 다른 인증 스키마를 확인하지 않고 즉시 오류 응답이 반환됩니다.
또한 `.authenticate_header(self, request)` 메소드를 대체 할 수 있습니다. 구현 된 경우 `HTTP 401 Unauthorized` 응답에서 `WWW-Authenticate` 헤더의 값으로 사용 될 문자열을 반환해야합니다.
`.authenticate_header()` 메소드가 대체되지 않으면, 인증 스키마는 인증되지 않은 요청이 액세스를 거부 할 때 `HTTP 403 Forbidden` 응답을 리턴합니다.
### Example
다음 예제는 들어오는 요청을 'X_USERNAME'이라는 사용자 지정 request 헤더에서 사용자 이름으로 지정된 사용자로 인증합니다.
```python
from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions
class ExampleAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
username = request.META.get('X_USERNAME')
if not username:
return None
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise exceptions.AuthenticationFailed('No such user')
return (user, None)
```
## Third party packages
다음의 타사 패키지도 제공됩니다.
### Django OAuth Toolkit
[Django OAuth Toolkit](https://github.com/evonove/django-oauth-toolkit) 패키지는 OAuth 2.0 지원을 제공하며 Python 2.7 및 Python 3.3 이상에서 작동합니다. 이 패키지는 [Evonove](https://github.com/evonove/)에서 유지 관리하며 우수한 [OAuthLib](https://github.com/idan/oauthlib)을 사용합니다. 이 패키지는 잘 문서화되어 잘 지원되며 현재 **OAuth 2.0 지원을위한 권장 패키지**입니다.
#### 설치와 구성
pip를 사용하여 설치합니다.
```
pip install django-oauth-toolkit
```
패키지를 `INSTALLED_APPS`에 추가하고 REST 프레임워크 설정을 수정하십시오.
```
INSTALLED_APPS = (
...
'oauth2_provider',
)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
)
}
```
자세한 내용은 [Django REST framework - Getting started](https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html)를 참조하세요.
### Django REST framework OAuth
Django [REST 프레임워크 OAuth](http://jpadilla.github.io/django-rest-framework-oauth/) 패키지는 REST 프레임워크에 대한 OAuth1 및 OAuth2 지원을 제공합니다. 이 패키지는 이전에 REST 프레임 워크에 직접 포함되었지만 이제는 타사 패키지로 지원 및 유지 관리됩니다.
#### 설치와 구성
pip를 사용하여 패키지를 설치합니다.
```
pip install djangorestframework-oauth
```
설정과 사용에 대한 자세한 내용은 Django REST 프레임워크 OAuth문서에서 [인증](http://jpadilla.github.io/django-rest-framework-oauth/authentication/)과 [권한](http://jpadilla.github.io/django-rest-framework-oauth/permissions/)을 참조하세요.
### Digest Authentication
HTTP 다이제스트 인증은 HTTP 기본 인증을 대체하기 위한 것으로 널리 구현 된 구성이며 간단한 암호화 된 인증 메커니즘을 제공합니다. [Juan Riaza](https://github.com/juanriaza)는 REST 프레임워크에 HTTP 다이제스트 인증 지원을 제공하는 [djangorestframework-digestauth](https://github.com/juanriaza/django-rest-framework-digestauth) 패키지를 유지 관리합니다.
### Django OAuth2 Consumer
[Rediker Software](https://github.com/Rediker-Software)의 [Django OAuth2 Consumer](https://github.com/Rediker-Software/doac) 라이브러리는 [REST 프레임 워크에 대한 OAuth 2.0 지원](https://github.com/Rediker-Software/doac/blob/master/docs/integrations.md#)을 제공하는 또 다른 패키지입니다. 이 패키지에는 토큰에 대한 토큰 범위 지정 권한이 포함되어있어 API에 대한 세밀한 액세스가 가능합니다.
### JSON Web Token
JSON Web Token은 토큰 기반 인증에 사용할 수있는 상당히 새로운 표준입니다. 내장 된 TokenAuthentication 체계와 달리 JWT 인증은 데이터베이스를 사용하여 토큰의 유효성을 검사 할 필요가 없습니다. [Blimp](https://github.com/GetBlimp)는 JWT 인증 클래스를 제공하는 [djangorestframework-jwt](https://github.com/GetBlimp/django-rest-framework-jwt) 패키지와 클라이언트가 사용자 이름과 비밀번호가 있는 JWT를 얻을 수 있는 메커니즘을 유지합니다.
### Hawk HTTP Authentication
[HawkREST](https://hawkrest.readthedocs.io/en/latest/) 라이브러리는 [Mohawk](https://mohawk.readthedocs.io/en/latest/) 라이브러리를 기반으로 [Hawk](https://github.com/hueniverse/hawk)에서 서명 한 요청 및 응답을 API에서 사용할 수 있도록합니다. [Hawk](https://github.com/hueniverse/hawk)은 공유 키로 서명 된 메시지를 사용하여 두 당사자가 서로 안전하게 통신 할 수있게합니다. [HTTP MAC 액세스 인증](https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) ([OAuth 1.0](https://oauth.net/core/1.0a/)의 일부를 기반으로 함)을 기반으로합니다.
### HTTP Signature
HTTP 서명 (현재 [IETF 초안](https://datatracker.ietf.org/doc/draft-cavage-http-signatures/))은 HTTP 메시지에 대한 원본 인증 및 메시지 무결성을 달성하는 방법을 제공합니다. 많은 서비스에서 사용되는 [Amazon의 HTTP 서명 체계](http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)와 유사하게 상태 비 저장 요청 별 인증을 허용합니다. [Elvio Toccalino](https://github.com/etoccalino/)는 사용하기 쉬운 HTTP 서명 인증 메커니즘을 제공하는 [djangorestframework-httpsignature](https://github.com/etoccalino/django-rest-framework-httpsignature) 패키지를 유지 관리합니다.
### Djoser
[Djoser](https://github.com/sunscrapers/djoser) 라이브러리는 등록, 로그인, 로그 아웃, 비밀번호 재설정 및 계정 활성화와 같은 기본 작업을 처리하기 위한 일련의 보기를 제공합니다. 패키지는 custom 사용자 모델과 작동하며 토큰 기반 인증을 사용합니다. 이것은 Django 인증 시스템의 REST 구현을 사용할 준비가되었습니다.
### django-rest-auth
[Django-rest-auth](https://github.com/Tivix/django-rest-auth) 라이브러리는 등록, 인증 (소셜 미디어 인증 포함), 비밀번호 재설정, 사용자 세부 정보 검색 및 업데이트 등을 위한 일련의 REST API 엔드포인트를 제공합니다. 이러한 API 엔드포인트를 사용하면 AngularJS, iOS, Android 및 기타 사용자는 사용자 관리를 위해 REST API를 통해 독립적으로 Django 백엔드 사이트와 통신 할 수 있습니다.
### django-rest-framework-social-oauth2
[Django-rest-framework-social-oauth2](https://github.com/PhilipGarnero/django-rest-framework-social-oauth2) 라이브러리는 소셜 플러그인 (facebook, twitter, google 등)을 인증 시스템에 쉽게 통합하고 쉬운 oauth2 설정을 제공합니다. 이 라이브러리를 사용하면 외부 토큰 (예 : 페이스 북 액세스 토큰)을 기반으로 사용자를 인증하고 이러한 토큰을 "in-house" oauth2 토큰으로 변환하고 oauth2 토큰을 사용 및 생성하여 사용자를 인증 할 수 있습니다.
### django-rest-knox
[Django-rest-knox](https://github.com/James1345/django-rest-knox) 라이브러리는 단일 페이지 응용 프로그램 및 모바일 클라이언트를 염두에 두고 기본 TokenAuthentication 체계보다 안전하고 확장 가능한 방식으로 토큰 기반 인증을 처리 할 수 있는 모델과 뷰를 제공합니다. 클라이언트 별 토큰 및 일부 다른 인증 (일반적으로 기본 인증)이 제공된 경우 생성하는 View, 토큰을 삭제 (서버 강제 로그 아웃 제공) 및 모든 토큰 삭제(사용자가 로그인 한 모든 클라이언트 로그 아웃) view를 제공합니다.).
---
## 추가 내용 (Token 등록 및 삭제)
**`member_myuser`**
![](./images/token1.png)
**`authtoken_token`**
![](./images/token2.png)
**`postman`에서 토큰 생성**
![](./images/token3.png)
`token``user_id` 값은 `member_myuser``id` 값으로 등록됩니다.
postman에서 생성한 test5(username)의 `myuser`테이블에서의 id 값은 8이고, 해당 토큰값으로 `token`테이블을 비교해보면 `user_id`가 같은 것을 확인할 수 있습니다.
`token` 삭제는 해당 토큰값의 계정으로 로그인해야 삭제가 가능합니다.
![](./images/token_delete.png)
> `request.user`를 프린트해보면 `username`값이 조회됩니다.

View File

@ -0,0 +1,100 @@
# Django REST Framework - Content negotiation
---
_"HTTP has provisions for several mechanisms for "content negotiation" - the proce반s of selecting the best representation for a given response when there are multiple representations available."_
_"HTTP는 "내용 협상 (content negotiation)"에 대한 몇 가지 메커니즘에 대한 규정을 제공합니다. 이는 여러 표현을 사용할 수 있는 경우 주어진 응답에 대한 최상의 표현을 선택하는 프로세스입니다."_
_— RFC 2616, Fielding et al._
---
## Content negotiation
content negotiation은 클라이언트 또는 서버 환경 설정에 따라 클라이언트로 리턴할 수 있는 여러 표현 중 하나를 선택하는 프로세스입니다.
### Determining the accepted renderer
REST 프레임워크는 간단한 스타일의 content negotiation을 사용하여 사용 가능한 renderer. 각 렌더러의 우선 순위 및 클라이언트의 `Accept:` 헤더를 기반으로 클라이언트에 반환해야하는 미디어 유형을 결정합니다. 사용되는 스타일은 부분적으로 클라이언트 / 서버 중심적입니다.
1. 더 구체적인 미디어 유형은 덜 구체적인 미디어 유형보다 우선합니다.
2. 복수의 미디어 타입이 같은 특이성을 가지는 경우, 지정된 뷰에 대해서 설정된 렌더러의 순서에 따라 우선권이 주어집니다.
예를 들어, 다음 `Accept` 헤더가 제공됩니다.
```
application/json; indent=4, application/json, application/yaml, text/html, */*
```
각 미디어 유형의 우선 순위는 다음과 같습니다.
- `application/json; indent=4`
- `application/json`, `application/yaml` and `text/html`
- `*/*`
요청 된 뷰가 `YAML``HTML`용 렌더러로만 구성된 경우 REST 프레임워크는 `renderer_classes` list 또는 ` DEFAULT_RENDERER_CLASSES` 설정에서 먼저 나열된 렌더러를 선택합니다.
HTTP Accept 헤더에 대한 자세한 내용은 [`RFC 2616`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)을 참조하십시오.
---
**Note** : 환경 설정에서 REST 프레임워크가 `"q"`값을 고려하지 않습니다. `"q"`값의 사용은 캐싱에 부정적인 영향을 주며 저자의 의견으로는 content negotiation에 불필요하고 복잡해지는 접근방식입니다.
이는 HTTP 사양이 의도적으로 서버가 클라이언트 기반 환경설정에 대해 서버 기잔 환경설정에 가중치를 부여하는 방법을 명시하지 않기 때문에 유효한 접근 방식입니다.
---
## Custom content negotiation
REST 프레임워크에 대해 custom content negotiation scheme를 제공하는 것은 거의 불가능하지만 필요한 경우 그렇게 할 수 있습니다. custom content negotiation scheme를 구현하려면 `BaseContentNegotiation`을 오버라이드합니다.
REST 프레임워크의 content negotiation 클래스는 요청에 대한 적절한 파서 및 응답에 적합한 렌더러 모두를 처리하므로 `.select_parser(request, parser)``.select_renderer(request, renderers, format_suffix)` 메서드를 모두 구현해야합니다.
`select_parser()`메서드는 파서 인스턴스 중 하나를 사용 가능한 파서 목록에서 반환하거나 파서가 들어오는 요청을 처리 할 수 없는 경우 `None`을 반환해야합니다.
`select_renderer()`메서드는 (renderer instance, media type)의 두 tuple을 반환하거나 `NotAcceptable` 예외를 발생시킵니다.
### Example
다음은 적절한 파서 또는 렌더러를 선택할 때 클라이언트 요청을 무시하는 custom content negotiation 클래스입니다.
```python
from rest_framework.negotiation import BaseContentNegotiation
class IgnoreClientContentNegotiation(BaseContentNegotiation):
def select_parser(self, request, parsers):
"""
Select the first parser in the `.parser_classes` list.
"""
return parsers[0]
def select_renderer(self, request, renderers, format_suffix):
"""
Select the first renderer in the `.renderer_classes` list.
"""
return (renderers[0], renderers[0].media_type)
```
### Setting the content negotiation
기본 content negotiation 클래스는 `DEFAULT_CONTENT_NEGOTIATION_CLASS`설정을 사용하여 전역으로 설정 할 수 있습니다. 예를 들어, 다음 설정은 예제 `IgnoreClientContentNegotitaion`클래스를 사용합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.IgnoreClientContentNegotiation',
}
```
`APIView` CBV를 사용하여 개별 view 또는 viewset에 사용 된 content negotiation을 설정할 수도 있습니다.
```python
from myapp.negotiation import IgnoreClientContentNegotiation
from rest_framework.response import Response
from rest_framework.views import APIView
class NoNegotiationView(APIView):
"""
An example view that does not perform content negotiation.
"""
content_negotiation_class = IgnoreClientContentNegotiation
def get(self, request, format=None):
return Response({
'accepted media type': request.accepted_renderer.media_type
})
```

View File

@ -0,0 +1,206 @@
# Django REST Framework - Exceptions
---
_"Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure."_
_"예외... 프로그램 구조 내의 중앙 또는 상위 위치에서 오류 처리를 명확하게 구성 할 수 있습니다."_
_— Doug Hellmann, Python Exception Handling Techniques_
---
## Exceptions
### Exception handling in REST framework views
REST 프레임워크의 뷰는 다양한 예외를 처리하고 적절한 오류 응답을 반환합니다.
처리되는 예외는 다음과 같습니다.
- REST 프레임워크 내에서 발생하는 `APIException`의 서브클래스입니다.
- Django의 `Http404` exception.
- Django의 `PermissionDenied` exception.
각각의 경우에 REST 프레임워크는 적절한 상태 코드 및 내용 유형이 포함된 응답을 반환합니다. response 본문에는 오류의 성격에 관한 추가 세부 정보가 포함됩니다.
대부분의 오류 응답에는 response 본문의 `detail`정보가 포함됩니다.
예를 들어, 다음 요청은:
```
DELETE http://api.example.com/foo/bar HTTP/1.1
Accept: application/json
```
해당 리소스에서 `DELETE` 메서드가 허용되지 않는다는 오류 응답을 받을 수 있습니다.
```python
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 42
{"detail": "Method 'DELETE' not allowed."}
```
유효성 검사 오류는 약간 다르게 처리되며 필드 이름을 응답의 키로 포함합니다. 유효성 검사 오류가 특정 필드에만 해당되지 않으면 `"non_field_errors"`키를 사용하거나 `NON_FIELD_ERRORS_KEY` 설정에 대해 설정된 문자열 값을 사용합니다.
모든 유효성 검증 오류는 다음과 같습니다.
```python
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 94
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
```
### Custom exception handling
API view에서 발생한 예외를 response 객체로 변환하는 handler 함수를 만들어 custom exception를 구현할 수 있습니다. 이를 통해 API에서 사용되는 오류 응답 스타일을 제어할 수 있습니다.
함수는 한쌍의 인수를 취해야하며, 첫번째는 처리할 예외이고, 두번째는 현재 처리중인 뷰와 같은 추가 context를 포함하는 dict입니다. exception handler 함수는 `Response` 객체를 반환하거나 예외를 처리 할 수 없는 경우 `None`을 반환해야합니다. handler가 `None`을 반환하면 예외가 다시 발생하고 Django는 표준 HTTP 500 'server error'응답을 반환합니다.
예를 들어, 모든 오류 응답에 다음과 같이 HTTP 본문 코드에 HTTP 상태 코드가 포함되도록 할 수 있습니다.
```python
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 62
{"status_code": 405, "detail": "Method 'DELETE' not allowed."}
```
response 스타일을 변경하기 위해 다음과 같은 custom exception handler를 작성 할 수 있습니다.
```python
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# Now add the HTTP status code to the response.
if response is not None:
response.data['status_code'] = response.status_code
return response
```
context 인수는 기본 handler에서 사용되지 않지만 exception handler가 `context['view']`로 액서스 할 수 있는 현재 처리중인 뷰와 같은 추가 정보를 필요로 할 때 유용할 수 있습니다.
`EXCEPTION_HANDLER`설정 키를 사용하여 설정에서 exception handler를 구성해야합니다. 예:
```python
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
```
지정하지 않으면 `EXCEPTION_HANDLER` 설정의 기본값은 REST 프레임워크에서 제공하는 표준 exception handler로 설정됩니다.
```python
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}
```
exception handler는 발생하는 예외에 의해 생성 된 응답에 대해서만 호출됩니다. serializer 유효성 검사가 실패 할 때 generic view에서 반환되는 `HTTP_400_BAD_REQUEST`응답과 같이 뷰에서 직접 반환 된 응답에는 사용되지 않습니다.
---
## API Reference
### APIException
**Signature**: `APIException()`
`APIView`클래스 또는 `@api_view`내부에서 발생한 모든 예외에 대한 기본 클래스입니다.
custom exception을 제공하려면, `APIException`을 서브클래스화하고 클래스의 `.status_code`, `.default_detail``default_code`속성을 설정하세요.
예를 들어, API가 가끔 도달 할 수 없는 제3자 서비스에 의존하는 경우, "503 Service Unavailable" HTTP response 코드에 대한 예외를 구현할 수 있습니다. 우리는 이렇게 할 수 있습니다.
```python
from rest_framework.exceptions import APIException
class ServiceUnavailable(APIException):
status_code = 503
default_detail = 'Service temporarily unavailable, try again later.'
default_code = 'service_unavailable'
```
#### Inspecting API exceptions
API exception을 검사하는데 사용할 수 있는 여러 속성이 있습니다. 이를 사용하여 프로젝트에 대한 custom exception를 빌드 할 수 있습니다.
사용 가능한 속성 및 메서드는 다음과 같습니다.
- `.detail` : 오류의 텍스트 설명을 리턴합니다.
- `.get_codes()` : 오류의 코드 식별자를 반환합니다.
- `.get_full_details()` : 텍스트 설명과 코드 식별자를 반환합니다.
대부분의 경우 오류 세부 사항은 간단한 항목입니다.
```python
>>> print(exc.detail)
You do not have permission to perform this action.
>>> print(exc.get_codes())
permission_denied
>>> print(exc.get_full_details())
{'message':'You do not have permission to perform this action.','code':'permission_denied'}
```
유효성 검사 오류의 경우 오류 세부 정보는 list나 dict입니다.
```python
>>> print(exc.detail)
{"name":"This field is required.","age":"A valid integer is required."}
>>> print(exc.get_codes())
{"name":"required","age":"invalid"}
>>> print(exc.get_full_details())
{"name":{"message":"This field is required.","code":"required"},"age":{"message":"A valid integer is required.","code":"invalid"}}
```
### ParseError
**Signature**: `ParseError(detail=None, code=None)`
`request.data`에 엑서스 할 때 request에 잘못된 데이터가 포함 된 경우 발생합니다.
기본적으로 이 예외는 HTTP status code "400 Bad Request"로 응답합니다.
### AuthenticationFailed
**Signature**: `AuthenticationFailed(detail=None, code=None)`
들어오는 request에 잘못된 인증이 포함될 떄 발생합니다.
기본적으로 이 예외로 인해 HTTP status code "401 Unauthenticated"가 반환되지만, 사용중인 인증 방식에 따라 "403 Forbidden" 응답이 발생할 수도 있습니다. 자세한 내용은 [인증 문서](http://www.django-rest-framework.org/api-guide/authentication/)를 참조하세요.
### NotAuthenticated
**Signature**: `NotAuthenticated(detail=None, code=None)`
인증되지 않은 요청이 권한 검사에 실패하면 발생합니다.
기본적으로 이 예외로 인해 HTTP status code "401 Unauthenticated"가 반환되지만 사용중인 인증 방식에 따라 "403 Forbidden"응답이 발생 할 수도 있습니다. 자세한 내용은 [인증 문서](http://www.django-rest-framework.org/api-guide/authentication/)를 참조하세요.
### PermissionDenied
**Signature**: `PermissionDenied(detail=None, code=None)`
인증 된 요청이 권한 검사에 실패하면 발생합니다.
기본적으로 이 예외는 HTTP status code "403 Forbidden"으로 응답하니다.
### NotFound
**Signature**: `NotFound(detail=None, code=None)`
주어진 URL에 resource가 없을 때 발생합니다. 이 예외는 표준 `Http404` Django exception과 동일합니다.
기본적으로 이 예외는 HTTP status code "404 Not Found"으로 응답합니다.
### MethodNotAllowed
**Signature**: `MethodNotAllowed(method, detail=None, code=None)`
뷰의 handler 메서드에 매핑되지 않는 들어오는 request가 발생했을 떄 발생합니다.
기본적으로 이 예외는 HTTP status code "405 Method Not Allowed"로 응답합니다.
### NotAcceptable
**Signature**: `NotAcceptable(detail=None, code=None)`
사용 가능한 randerer에서 만족 할 수 없는 `Accept`헤더로 들어오는 request가 발생할때 발생합니다.
기본적으로 이 예외는 HTTP status code "406 Not Acceptable"으로 응답합니다.
### UnsupportedMediaType
**Signature**: `UnsupportedMediaType(media_type, detail=None, code=None)`
`request.data`에 엑서스 할 때 request 데이터의 내용 유형을 처리 할 수 있는 parser가 없는 경우 발생합니다.
기본적으로 이 예외는 HTTP status code "415 Unsupported Media Type"으로 응답합니다.
### Throttled
**Signature**: `Throttled(wait=None, detail=None, code=None)`
들어오는 request가 throttle 검사에 실패하면 발생합니다.
기본적으로 이 예외는 HTTP status code "429 Too Many Requests"으로 응답합니다.
### ValidationError
**Signature**: `ValidationError(detail, code=None)`
`ValidationError` 예외는 다른 `APIException`클래스와 약간 다릅니다.
- `detail` 인수는 필수입니다. 선택사항이 아닙니다.
- `detail`인수는 오류 세부 사항 list 또는 dict 일 수 있으며, 중첩된 데이터 구조 일 수도 있습니다.
- 규약에 따라 serializer 모듈을 가져와 정규화 된 `ValidationError` 스타일을 사용하여 Django의 기본 유효성 검사 오류와 구별해야합니다. 예: `raise serializers.ValidationError('이 필드는 정수(Integer)값이어야 합니다.')`
`ValidationError` 클래스는 serializer 및 필드 유효성 검사 및 유효성 검사기 클래스에 사용해야합니다. 또한 `raise_exception` 키워드 인수로 `serializer.is_valid`를 호출 할 때 발생합니다.
```
serializer.is_valid(raise_exception=True)
```
generic view는 `raise_exception=True`플래그를 사용합니다. 즉, API에서 유효성 검증 오류 응답의 스타일을 대체할 수 있습니다. 이렇게 하려면 위에서 설명한대로 custom exception handler를 사용하세요.
기본적으로 이 예외는 HTTP status code "400 Bad Request"으로 응답합니다.

View File

@ -0,0 +1,455 @@
# Django REST Framework - Filtering
---
_"The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects."_
_"Manager가 제공하는 루트 QuerySet은 데이터베이스 테이블의 모든 객체를 설명합니다. 그러나 일반적으로 개체의 전체 집합 중 일부만 선택해야합니다."_
_— Django documentation_
---
## Filtering
REST 프레임워크의 `generic list view`의 기본 동작 모델 manager에 대한 전체 QuerySet을 반환하는 것입니다. 때때로 당신 API가 QuerySet에 의해 반환 되된 항목을 제한하기를 원할 것입니다.
`GenericAPIView`를 하위 클래스로 하는 view의 QuerySet를 필터링하는 가장 간단한 방법은 `.get_queryset()`메서드를 오버라이드하는 것입니다.
이 메소드응 대체라면 다양한 방식으로 view에서 리턴 된 queryset을 custom 할 수 있습니다.
### Filtering against the current user (현재 사용자에 대한 필터링)
쿼리를 필터링하여 요청을 한 현재 인증 된 사용자와 관련된 결과만 반환되도록 할 수 있습니다.
`request.user`의 값에 따라 필터링을 수행 할 수 있습니다.
예를 들어:
```python
from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
user = self.request.user
return Purchase.objects.filter(purchaser=user)
```
### Filtering against the URL
필터링의 또 다른 스타일은 URL 일부를 기반으로 queryset을 제한하는 것입니다.
예를 들어 URLconfig에 다음과 같은 항목이 포함 된 경우:
```python
url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
```
그런 다음 URL의 사용자 이름 부분으로 필터링 된 purchases queryset을 반환하는 view를 작성 할 수 있습니다.
```python
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
username = self.kwargs['username']
return Purchase.objects.filter(purchaser__username=username)
```
### Filtering against query parameters
초기 쿼리셋을 필터링하는 마지막 예는 URL의 쿼리 parameter를 기반으로 초기 쿼리겍을 결정하는 것입니다.
`http://example.com/api/purchases?username=denvercoder9`과 같은 URL을 처리하려면 `.get.queryset()`을 재정의하고 `username` 매개변수가 URL에 포함되어있는 경우에만 쿼리셋을 필터링하세요.
```python
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
Optionally restricts the returned purchases to a given user,
by filtering against a `username` query parameter in the URL.
"""
queryset = Purchase.objects.all()
username = self.request.query_params.get('username', None)
if username is not None:
queryset = queryset.filter(purchaser__username=username)
return queryset
```
---
### Generic Filtering
기본 쿼리셋을 재정의 할 수 있을뿐만 아니라 REST 프레임워크는 복잡한 검색 및 필터를 쉽게 구성할 수 있는 일반 필터링 백엔드를 지원합니다.
Generic filter는 browsable API 및 admin API에서 HTML 컨트롤로 나타낼 수도 있습니다.
![](./images/genericfiltering.png)
### Setting filter backends
기본 필터 백엔드는 `DEFAULT_FILTER_BACKENDS` 설정을 사용하여 전체적으로 설정할 수 있습니다. 예를 들면,
```python
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
```
`GenericAPIView` CBV를 사용하여 view 당 또는 viewset 단위로 필터 백엔드를 설정할 수도 있습니다.
```python
import django_filters.rest_framework
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
```
### Filtering and object lookups
필터 백엔드는 view에 대해 구성되고 list view를 필터링하는데 사용되는 경우, 하나의 객체를 반환하는데 가용되는 queryset을 필터링하는데에도 사용됩니다.
예를 들어, 앞의 예제와 id가 4675인 제품의 경우 다음 URL은 해당 제품 인스턴스에서 필터링 조건이 충족되었는지 여부에 따라 해당 객체를 반환하거나 404 응답을 반환합니다.
```
http://example.com/api/products/4675/?category=clothing&max_price=10.00
```
### Overriding the initial queryset
오버라이드 된 `.get_queryset()`과 generic filtering을 함께 사용하면 모든 것이 예상대로 작동합니다. 예를 들어, `Product``User`라는 구매자와 `many-to-many`관계를 갖고 있다면 다음과 같은 view를 작성하는 것이 좋습니다.
```python
class PurchasedProductsList(generics.ListAPIView):
"""
Return a list of all the products that the authenticated
user has ever purchased, with optional filtering.
"""
model = Product
serializer_class = ProductSerializer
filter_class = ProductFilter
def get_queryset(self):
user = self.request.user
return user.purchase_set.all()
```
---
## API Guide
### DjangoFilterBackend
`django-filter` 라이브러리에는 REST 프레임워크에 대해 고도의 custom이 가능한 필드 필터링을 지원하는 `DjangoFilterBackend`클래스가 포함되어 있습니다.
`DjangoFilterBackend`를 사용하려면 먼저 `django-filter`를 설치하세요.
```
pip install django-filter
```
이제 필터 백엔드를 설정에 추가해야 합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
```
또는 필터 백엔드를 개별 view 또는 viewset에 추가하세요.
```python
from django_filters.rest_framework import DjangoFilterBackend
class UserListView(generics.ListAPIView):
...
filter_backends = (DjangoFilterBackend,)
```
browsable API나 admin API를 사용하는 경우, `django-crispy-forms`를 설치하여 HTML View에서 필터 양식의 표시를 향상시키고 부트스트랩3 HTML을 랜더링할 수 있습니다.
```
pip install django-crispy-forms
```
crispy-forms 를 설치하고 Django의 `INSTALLED_APPS`에 추가하면 browsable API는 다음과 같이 `DjangoFilterBackend`에 대한 필터링 컨트롤을 제공합니다.
![](./images/fieldfilter.png)
#### Specifying filter fields
필요한 것은 간단한 equality-based 필터링 뿐입니다. 필터링 할 필드 집합을 나열하는 view 또는 viewset에 `filter_fields` 속성을 설정할 수 있습니다.
```python
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('category', 'in_stock')
```
이렇게 하면 주어진 필드에 대한 `FilterSet`클래스가 자동으로 생성되며 다음과 같은 요청을 할 수 있습니다.
```
http://example.com/api/products?category=clothing&in_stock=True
```
#### Specifying a FilterSet (FilterSet 지정하기)
고급 필터링 요구 사항의 경우 view에서 사용해야하는 `FilterSet`클래스를 지정할 수 있습니다. 예:
```python
import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
class ProductFilter(django_filters.rest_framework.FilterSet):
min_price = django_filters.NumberFilter(name="price", lookup_expr='gte')
max_price = django_filters.NumberFilter(name="price", lookup_expr='lte')
class Meta:
model = Product
fields = ['category', 'in_stock', 'min_price', 'max_price']
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
filter_class = ProductFilter
```
그러면 다음과 같은 요청을 할 수 있습니다.
```
http://example.com/api/products?category=clothing&max_price=10.00
```
`django-filter`를 사용하여 관계를 확장할 수도 있습니다. 각 제품에는 제조업체 모델에 대한 외래 키가 있다고 가정하여 제조업체 이름을 사용하여 필터링 하는 필터를 만듭니다. 예:
```python
import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
class ProductFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = Product
fields = ['category', 'in_stock', 'manufacturer__name']
```
이렇게 하면 다음과 같은 쿼리를 작성할 수 있습니다.
```
http://example.com/api/products?manufacturer__name=foo
```
이것은 좋은 일이지만 Django의 double-underscore 규칙을 API의 일부로 나타냅니다. 대신 명식적으로 필터 인수의 이름을 지정하려면 `FilterSet`클래스에 필터 인수를 명시적으로 포함시킬 수 있습니다.
```python
import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
class ProductFilter(django_filters.rest_framework.FilterSet):
manufacturer = django_filters.CharFilter(name="manufacturer__name")
class Meta:
model = Product
fields = ['category', 'in_stock', 'manufacturer']
```
이제 다음을 실행 할 수 있습니다.
```
http://example.com/api/products?manufacturer=foo
```
필터 셋 사용데 대한 자세한 내용은 [django-filter documentation](https://django-filter.readthedocs.io/en/latest/index.html)를 참조하세요.
---
**Hints & Tips**
- 기본적으로 필터링은 사용할 수 없습니다. `DjangoFilterBackend`를 사용하려면 `DEFAULT_FILTER_BACKENDS`설정을 사용하여 설치되었는지 확인하세요.
- Boolean 필드를 사용할 때는 `0`, `1`, `true``false`가 아닌 URL 쿼리 매개변수에 `True``False` 값을 사용해야 합니다. (허용된 boolean 값은 현재 Django의 [NullBooleanSelect implementation](https://github.com/django/django/blob/master/django/forms/widgets.py)에서 고정되어 있습니다.)
- `django-filter`는 Django의 double-underscore 문법을 통해 관계가 맺어진 필터링을 지원합니다.
---
### SearchFilter
`SearchFilter`클래스는 간단한 단일 쿼리 parameter 기반 검색을 지원하며 [django 관리자의 검색 기능](https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields)을 기반으로 합니다.
사용 중에는 browsable API에 `SearchFilter` 컨트롤이 포함됩니다.
![](./images/searchfilter.png)
`SearchFilter`클래스는 뷰에 `search_fields`속성이 설정된 경우에만 적용됩니다. `search_fields`속성은 `CharField`또는 `TextField`와 같이 모델의 텍스트 유형 필드의 이름의 list이어야 합니다.
```python
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('username', 'email')
```
이렇게 하면 클라이언트가 다음과 같은 쿼리를 작성하여 list의 items를 필터링 할 수 있습니다.
```
http://example.com/api/users?search=russell
```
검색 API double-underscore 표기법을 사용하여 `ForeignKey` 또는 `ManyToManyField`에서 관련 조회를 수행할 수도 있습니다.
```python
search_fields = ('username', 'email', 'profile__profession')
```
기본적으로 검색은 대소 문자를 구분하지 않는 부분 일치를 사용합니다. 검색 parameter에는 공백 또는 `/`또는 쉼표로 구분 된 여러 검색어가 포함 될 수 있습니다. 여러 검색어가 사용되면 제공된 모든 용어가 일치하는 경우에만 list에서 객체가 반환됩니다.
검색 동작은 다양한 문자를 `search_fields`앞에 붙이면 제한 될 수 있습니다.
- `'^'`: 검색을 시작합니다.
- `'='`: 정확히 일치
- `'@'`: 전체 텍스트 검색 (현재 django의 MySQL 백엔드만 지원됩니다.
- `'$'`: 정규식 검색
예를 들면 :
```python
search_fields = ('=username', '=email')
```
기본적으로 검색 parameter의 이름은 `'search'`이지만 `SEARCH_PARAM` 설정으로 오버라이드 될 수 있습니다.
자세한 내용은 [장고 문서](https://docs.djangoproject.com/en/1.10/ref/contrib/admin/parameter#django.contrib.admin.ModelAdmin.search_fields)를 참조하세요.
---
### OrderingFilter
`OrderingFilter`클래스는 쿼리 parameter로 제어되는 간단한 결과 순서를 지원합니다.
![](./images/orderingfilter.png)
기본적으로 쿼레 parameter의 이름은 `'ordering'`이지만, `ORDERING_PARAM`설정으로 오버라이드 할 수 있습니다.
예를 들어 사용자 이름별로 사용자를 정렬 하려면 다음과 같이 입력하세요.
```
http://example.com/api/users?ordering=username
```
클라이언트는 필드 이름의 접두사를 `'-'`로 지정함으로써 역순으로 지정할 수도 있습니다.
```
http://example.com/api/users?ordering=-username
```
여러 개의 순서도 지정 할 수 있습니다.
```
http://example.com/api/users?ordering=account,username
```
#### Specifying which fields may be ordered against
API가 정렬 필터에서 허용해야하는 필드를 명시적으로 지정하는 것이 좋습니다. 다음과 같이 view에서 `ordering_fields`속성을 설정하여 이를 수행 할 수 있습니다.
```python
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
```
이렇게 하면 사용자가 암호 해시 필드나 기타 중요한 데이터에 대해 정렬할 수 있게 하는 등 예기치 않은 데이터 유출을 방지할 수 있습니다.
view에서 `ordering_fields`속성을 지정하지 않으면 필터 클래스는 기본적으로 `serializer_class`속성을 지정된 serializer의 읽을 수 있는 필드를 필터링 할 수 있게 합니다.
> `ordering_fields`에 한개의 조건(ex. start_date)만 넣으면, `pagination` 사용시 중복되는 조건에 대하여 어떤 것을 앞에 두어야하는지에 대한 이슈가 일어나서 페이지가 넘어갈때 중복된 값이 출력될 수 있습니다. 두개 이상의 조건을 제시하면 pagination 시 중복된 값의 출력을 방지할 수 있습니다.
뷰에 사용 된 쿼리셋은 중요한 데이터가 포함되어 있지 않은 것으로 확신하는 경우, 특수 값 `'__all__'`을 사용하여 view가 모든 모델 필드 또는 쿼리셋 합계에서 정렬을 허용하도록 명시적으로 지정할 수 있습니다.
```python
class BookingsListView(generics.ListAPIView):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = '__all__'
```
#### Specifying a default ordering
`ordering` 속성이 view에 설정되어 있는 경우, 이것은 기본 순서로 사용됩니다.
일반적으로 초기 쿼리셋에서 `order_by`를 설정하여 이 작업을 제어할 수 있지만 view의 `ordering` parameter를 사용하면 렌더링 된 템플릿에 컨텍스트로 자동 전달 할 수 있는 방식으로 순서를 지정할 수 있습니다. 이렇게 하면 결과를 정렬하는데 사용하는 경우, column headers를 자동으로 다르게 렌더링 할 수 있습니다.
```python
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
ordering = ('username',)
```
`ordering` 속성은 문자열이거나 문자열의 list/tuple 일 수 있습니다.
---
### DjangoObjectPermissionsFilter
`DjangoObjectPermissionsFilter``django-guardian`패키지와 함께 사용되며 custom `'view'` 권한이 추가되었습니다. 필터는 쿼리셋이 사용자에게 적절한 view 권한이 있는 객체만 반환하도록 합니다.
`DjangoObjectPermissionsFilter`를 사용하고 있다면 적절한 객체 권한 클래스를 추가하여 적절한 객체 권한이 있는 사용자만 인스턴스에서 작업 할 수 있도록 할 수 있습니다. 가장 쉬운 방법은 `DjangoObjectPermissions`를 서브 클래스화하고 `perms_map`속성에 `'view'`권한을 추가하는 것입니다.
`DjangoObjectPermissionsFilter``DjangoObjectPermissions`를 사용하는 완전한 예는 다음과 같습니다.
**permission.py**:
``` python
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
```
**views.py**:
```python
class EventViewSet(viewsets.ModelViewSet):
"""
Viewset that only lists events if user has 'view' permissions, and only
allows operations on individual events if user has appropriate 'view', 'add',
'change' or 'delete' permissions.
"""
queryset = Event.objects.all()
serializer_class = EventSerializer
filter_backends = (filters.DjangoObjectPermissionsFilter,)
permission_classes = (myapp.permissions.CustomObjectPermissions,)
```
모델에 대한 `'view'`권한을 추가하는 방법에 대한 자세한 내용은 [`django-guardian`의 relevant section ](https://django-guardian.readthedocs.io/en/latest/userguide/assign.html)과 이 [블로그 게시물](http://blog.nyaruka.com/adding-a-view-permission-to-django-models)을 참조하세요.
---
## Custom generic filtering
나만의 generic 필터링 백엔드를 제공하거나, 다른 개발자가 사용할 수 있는 설치 가능한 앱을 작성 할 수도 있습니다.
이렇게하려면 `BaseFilterBackend`를 무시하고 `.filter_queryset(self, request, queryset, view)`메서드를 오버라이드 하세요. 메서드는 필터링 된 새 쿼리셋을 반환해야합니다.
클라이언트가 검색 및 필터링을 수행할 수 있을뿐만 아니라 generic filter 백엔드는 특정 요청이나 사용자에게 표시되어야 하는 객체를 제한하는데 유용 할 수 있습니다.
### Example
예를 들어, 사용자가 만든 개체만 볼 수 있도록 사용자를 제한해야 할 수 있습니다.
```python
class IsOwnerFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see their own objects.
"""
def filter_queryset(self, request, queryset, view):
return queryset.filter(owner=request.user)
```
view에서 `get_queryset()`을 오버라이드하여 동일한 동작을 얻을 수 있지만 filter 백엔드를 사용하면 이 제한을 여러 view에 더 쉽게 추가하거나 전체 API에 적용할 수 있습니다.
### Customizing the interface
generic filter는 browsable API에도 친터페이스를 제공 할 수 있습니다. 이렇게 하려면 filter의 렌더링 된 HTML 표현을 반환하는 `to_html()`메서드를 구현해야합니다. 이 메서드의 서명은 다음과 같습니다.
`to_html(self, request, queryset, view)`
메서드는 렌더링 된 HTML 문자열을 반환해야 합니다.
### Pagination & schemas
REST 프레임워크가 제공하는 스키마 자동 생성에서 filter 컨트롤을 사용할 수 있도록 하려면, `get_schema_fields()`메서드를 구현하면 됩니다. 이 메서드는 `coreapi.Filed`인스턴스의 list를 반환해야 합니다.
## Third party packages
다음의 타사 패키지는 추가 필터 구현을 제공합니다.
### Django REST framework
[`django-rest-framework-filters`](https://github.com/philipn/django-rest-framework-filters) 패키지는 `DjangoFilterBackend` 클래스와 함께 작동하며 관계에 대한 필터를 쉽게 만들거나 주어진 필드에 대해 여러 개의 필터 조회 유형을 만들 수 있습니다.
### Django REST framework full word search filter
[`djangorestframework-word-filter`](https://github.com/trollknurr/django-rest-framework-word-search-filter)는 `filters.SearchFilter`의 대안으로 개발되었으며 텍스트 또는 완전 일치에서 전체 단어를 검색합니다.
### Django URL Filter
[`django-url-filter`](https://github.com/miki725/django-url-filter)는 친인간적인 URL을 통해 데이터를 필터링하는 안전한 방법을 제공합니다. 이는 DRF serializer 및 필드와 매우 유사하게 작동합니다. 즉, filtersets 및 필터라고 하는 것을 제외하고는 중첩 될 수 있습니다. 이를 통해 관련 데이터를 쉽게 필터링 할 수 있습니다. 또한 이 라이브러리는 일반적인 목적이므로 Django `QuerySet`뿐만 아니라 다른 소스의 데이터를 필터링하는데 사용할 수 있습니다.
### drf-url-filters
[`drf-url-filter`](https://github.com/manjitkumar/drf-url-filters)는 Drf `ModelViewSet``Queryset`에 필터를 간단하고 구성 가능한 방식으로 적용하는 간단한 Django 응용 프로그램입니다. 또한 들어오는 쿼리 parameter 및 해당 값에 대한 유효성 검사를 지원합니다. 아름다운 python 패키지 `Voluptuous`는 들어오는 쿼리 parameter의 유효성 검사에 사용됩니다. 가장 관대한 부분은 쿼리 parameter 요구 사항에 따라 자체 유효성 검사를 정의할 수 있다는 것입니다.

View File

@ -0,0 +1,88 @@
# Django REST Framework - Format suffixes
---
_"Section 6.2.1 does not say that content negotiation should be used all the time."_
_"섹션 6.2.1은 content negotiation이 항상 사용되어야한다고 말하지 않는다. "_
_— Roy Fielding, REST discuss mailing list_
---
## Format suffixes
웹 API의 일반적인 패턴은 URL에서 파일 이름 확장자를 사용하여 특정 미디어 유형에 대한 엔드포인트를 제공하는 것입니다. 예를 들어, 'http://example.com/api/users.json'은 JSON 표현을 제공합니다.
API의 URLconf에 있는 각 개별 항목에 형식 접미사 패턴을 추가하는 것은 오류가 발생하기 쉽고 DRY가 아니므로 REST 프레임워크는 이러한 패턴을 URLconf에 추가하는 방법을 제공합니다.
### format_suffix_patterns
**Signature**: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None)
제공된 각 URL 패턴에 추가 된 형식 접미사 패턴을 포함하는 URL 패턴 list를 반환합니다.
Arguments:
- `urlpatterns` : **필수**. URL 패턴 목록.
- `suffix_required` : 선택사항. URL의 접미사를 옵션으로 하는지, 필수로 하는지를 나타내는 boolean입니다. 디폴트는 `False`입니다. 접미사는 기본적으로 선택사항입니다.
- `allowed` : 선택사항. 유효한 형식 접미사의 list 또는 tuple입니다. 제공되지 않으면 와일드 카드 형식 접미사 패턴이 사용됩니다.
예:
```python
from rest_framework.urlpatterns import format_suffix_patterns
from blog import views
urlpatterns = [
url(r'^/$', views.apt_root),
url(r'^comments/$', views.comment_list),
url(r'^comments/(?P<pk>[0-9]+)/$', views.comment_detail)
]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
```
`format_suffix_patterns`를 사용하는 경우 `'format'`키워드 인수를 해당 부에 추가해야합니다. 예:
```python
@api_view(('GET', 'POST'))
def comment_list(request, format=None):
# do stuff...
```
또는 class-bassed-views:
```python
class CommentList(APIView):
def get(self, request, format=None):
# do stuff...
def post(self, request, format=None):
# do stuff...
```
사용 된 kwarg의 이름은 `FORMAT_SUFFIX_KWARG`설정을 사용하여 수정할 수 있습니다.
또한 `format_suffix_patterns``include`URL 패턴으로 내림차순을 지원하지 않습니다.
#### Using with `i18n_patterns`
Django에서 제공하는 `i18n_patterns`함수와 `format_suffix_patterns`를 사용하는 경우 `i18n_patterns` 함수가 최종 함수 또는 가장 바깥쪽 함수로 적용되는지 확인해야합니다. 예:
```python
url patterns = [
]
urlpatterns = i18n_patterns(
format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
)
```
---
### Query parameter formats
format suffixe의 대신 요청 된 쿼리 parameter에 포함시키는 것입니다. REST 프레임워크는 기본적으로 옵션을 제공하며, browsable API에서 사용 가능한 다양한 표현을 전환하는데 사용됩니다.
짧은 형식을 사용하여 표현을 선택하려면 `format` 쿼리 parameter를 사용하십시오. 예 : `http://example.com/organizations/?format=csv`
이 쿼리 parameter의 이름은 `URL_FORMAT_OVERRIDE`설정을 사용하여 수정할 수 있습니다. 이 동작을 사용하지 않으려면 값을 `None`으로 설정하세요.
### Accept headers vs. format suffixes
파일 이름 확장자는 RESTfull 패턴이 아니면 HTTP Accept 헤더가 항상 대신 사용되어야 한다는 웹 커뮤니티의 견해가 있는 것 같습니다.
그것은 실제론 오해입니다. 예를 들어 Roy Fileding은 쿼리 parameter 미디어 타입 표시기와 파일 확장 미디어 타입 표시기의 상대적 장점에 대해 다음과 같이 설명합니다.
_"그래서 나는 항상 확장 프로그램을 선호합니다. 어느 선택도 REST와는 아무런 관련이 없습니다. "- Roy Fielding, REST 토론 메일 링리스트_
인용문에는 Accept Headers가 언급되어 있지 않지만 format suffix는 허용되는 패턴으로 간주되어야 한다는 점을 분명히 합니다.

View File

@ -0,0 +1,316 @@
# Django REST Framework - Generic views
---
_"Djangos generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself."_
_"Django의 generic views... 일반적인 사용 패턴을 위한 지름길로 개발되었습니다... 그들은 view 개발에서 발견되는 특정 공통 관용구와 패턴을 취해서 반복함으로써 반복하지 않고도 공통된 데이터 view를 빠르게 작성할 수 있습니다."_
_— Django Documentation_
---
## Generic views
CBV의 주요 이점 중 하나는 재사용이 가능한 동작을 구성하는 것입니다. REST 프레임워크는 일반적으로 사용되는 패턴을 제공하는 다수의 dict에 빌드 된 view를 제공함으로써 이를 활용합니다.
REST 프레임워크에서 제공하는 generic view를 사용하면 데이터베이스 모델과 밀접하게 매핑되는 API 뷰를 빠르게 빌드 할 수 있습니다.
`generic views` 가 API의 요구 사항에 맞지 않으면 정규 `APIView`클래스를 사용하여 drop down 하거나 `generic views`에서 사용하는 `mixin`과 기본 클래스를 재사용하여, 자신만 재사용이 가능한 `generic views` set를 작성할 수 있습니다.
### Examples
일반적으로 `generic views`를 사용하는 경우 view를 무시하고 여러 클래스 속성을 설정합니다.
```python
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
```
보다 복잡한 경우에는 view 클래스의 다양한 메서드를 재정의 할 수도 있습니다. 예를 들면:
```python
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
def list(self, request):
# Note the use of `get_queryset()` instead of `self.queryset`
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
```
매우 간단한 경우에는 `.as_view()`메서드를 사용하여 클래스 속성을 전달할 수 있습니다. 예를 들어, `URLconf`에 다음 항목이 포함 될 수 있습니다.
```python
url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
```
---
## API Reference
### GenericAPIView
이 클래스는 REST 프레임워크의 `APIView` 클래스를 확장하여 기존 list view와 detail views에 일반적으로 필요한 동작을 추가합니다.
제공된 각각의 `generic views``GenericAPIView`를 하나 이상의 `minxin`클래스와 결합하여 빌드됩니다.
#### Attributes
##### Basic settings:
다음 속성은 기본 뷰 동작을 제어합니다.
- `queryset` : 이 뷰에서 객체를 반환하는 데 사용해야 하는 쿼리셋입니다. 일반적으로 이 속성을 설정하거나 `get_queryset()`메서드를 대체해야합니다. 뷰 메서드를 오버라이드하는 경우, 이 속성에 직접 액서스하는 대신 `get_queryset()`을 호출하는 것이 중요합니다. 쿼리셋은 한번 평가되고 그 결과는 모든 후속 request에 대해 캐시됩니다.
- `serializer_class` : 입력의 검증과 serializer 복원 및 출력 serializer에 사용하는 `serializer` 클래스입니다. 일반적으로 이 속성을 설정하거나 `get_serializer_class()`메소드를 대체해야 합니다.
- `lookup_field` : 개별 모델 인스턴스의 object 조회를 수행 할 때 사용해야하는 모델 필드입니다. 기본값은 `'pk'`입니다. 하이퍼링크 된 API에 custom 값을 사용해야 하는 경우 API views와 serializer 클래스가 `lookup`필드를 설정해야 합니다.
- `lookup_url_kwarg` : 객체 검색에 사용해야하는 URL 키워드 인수입니다. `URL conf`에는 이 값에 해당하는 키워드 인수가 포함되어야 합니다. 설정을 해제하면 `lookup_field`와 동일한 값을 사용합니다.
##### Pagination:
다음 속성은 list views와 함께 사용될 때 `pagination`을 제어하는데 사용됩니다.
- `pagination_class` : 결과 목록을 지정할 때 사용해야하는 `pagination`클래스입니다. 기본값은 `'rest_framework.pagination.PageNumberPagination'``DEFAULT_PAGINATION_CLASS`설정과 동일한 값입니다. `pagination_class=None`으로 설정하면 이 view에서 pagination을 사용할 수 없습니다.
##### Filtering:
- `filter_backends` : 쿼리셋을 필터링하는데 사용해야하는 `filter backend`클래스의 list입니다. 기본값은 `DEFAULT_FILTER_BACKENDS`설정과 동일합니다.
#### Method
##### Base methods:
```
get_queryset(self)
```
**`list view`**에서 사용되는 쿼리셋을 돌려줍니다. `detail view` 안의 `lookup`의 베이스로 사용됩니다. `queryset`속성에 의해 지정된 쿼리셋을 리턴하는 것이 기본값입니다.
이 메서드는 `self.queryset`에 직접 액서스하는 대신 항상 사용되어야하며, `self.queryset`은 한번만 평가되고 그 결과는 모든 후속 요청에 캐시됩니다.
request를 작성하는 사용자에게 특정되는 쿼리셋 반환과 같은 동적 동작을 제공하도록 재정의 될 수 있습니다.
예제:
```python
def get_queryset(self):
user = self.request.user
return user.accounts.all()
```
```
get_object(self)
```
**`detail views`**에 사용해야 하는 객체 인스턴스를 반환합니다. 기본적으로 `lookup_field` parameter를 사용하여 기본 쿼리셋을 필터링합니다.
둘 이상의 `URL kwarg`를 기반으로 하는 `object lookups`와 같이 복잡한 동작을 제공하기 위해 무시될 수 있습니다.
예를 들어:
```python
def get_object(self):
queryset = self.get_queryset()
filter = {}
for field in self.multiple_lookup_fields:
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter)
self.check_object_permissions(self.request, obj)
return obj
```
API에 객체 수준 권한이 없으면 선택적으로 `self.check_object_permissions`를 제외하고 단순히 `get_object_or_404` lookup에서 객체를 반환 할 수 있습니다.
```
filter_queryset(self, queryset)
```
**`serializer`**에 사용해야하는 클래스를 반환합니다. 기본값은 `serializer_class`속성을 반환하는 것입니다.
읽기와 쓰기 작업에 다른 serializer를 사용하거나 다른 유형의 사용자에게 다른 serializer를 제공하는 등의 동적 동작을 제공하기 위해 재정의 될 수 있습니다.
예:
```python
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
```
##### Save and deletion hooks:
다음과 같은 메서드가 `mixin`클래스에서 제공되며 object 저장이나 삭제 동작을 쉽게 대체 할 수 있습니다.
- `perform_create(self, serializer)` : 새 object 인스턴스를 저장할 때 `CreateModelMixin`에 의해 호출됩니다.
- `perform_update(self, serializer)` : 기존 object 인스턴스를 저장할 때 `UpdateModelMixin`에 의해 호출됩니다.
- `perform_destroy(self, instance)` : object 인스턴스를 삭제할 때 `DestroyModelMixin`에 의해 호출됩니다.
이러한 `hooks`는 request에 내포되어 있지만, 요청 데이터의 일부가 아닌 속성을 설정하는데 특히 유용합니다. 예를 들어, request 사용자를 기준으로 또는 URL 키워드 인수를 기반으로 object의 속성을 설정할 수 있습니다.
```python
def perform_create(self, serializer):
serializer.save(user=self.request.user)
```
또한 이러한 오버라이드 포인트는 확인 이메일을 보내거나 업데이트를 로깅하는 것과 같이 object 저장 전후에 발생하는 동작을 추가 할 때 특히 유용합니다.
> 로깅 : 시스템을 작동할 때 시스템의 작동 상태의 기록,보존,시스템동작 분석들을 기록하는 것
```python
def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
```
`ValidationError()`를 발생시켜 추가 유효성 검사를 제공하기 위해 이러한 `hooks`을 사용할 수도 있습니다. 데이터베이스 저장 시점에 적용 할 유효성 검증 로직이 필요한 경우 유용 할 수 있습니다.
```python
def perform_create(self, serializer):
queryset = SignupRequest.objects.filter(user=self.request.user)
if queryset.exists():
raise ValidationError('You have already signed up')
serializer.save(user=self.request.user)
```
**Note**: 이 메서드는 이전 버전(2.x)의 `pre_save`, `post_save`, `pre_delete``post_delete`메서드를 대체하며 더 이상 사용할 수 없습니다.
##### Other methods:
`GenericAPIView`를 사용하여 custom views를 작성하는 경우, 호출할 수도 있지만 일반적으로 다음의 메서드를 대체하야 할 필요는 없습니다.
- `get_serializer_context(self)` : serializer에 제공되어야 하는 추가 컨텐스트가 포함된 dict를 반환합니다. 기본값엔 `request`, `view`, `format` 키가 포합됩니다.
- `get_serializer(self, instance=None, data=None, many=False, partial=False)` : serializer 인스턴스를 반환합니다.
- `get_paginated_response(self, data)` : pagination 스타일의 response object를 반환합니다.
- `paginate_queryset(self, queryset)` : 필요하면, `paginate_queryset`에 page object를 반환하거나, 이 view에 pagination이 구성되지 않은 경우 None을 반환합니다.
- `filter_queryset(self, queryset)` : 주어진 쿼리셋을 사용중인 필터 백엔드를 사용하여 새로운 쿼리셋을 반환합니다.
---
## Mixins
`mixin`클래스는 기본 view 동작을 제공하는데 사용되는 작업을 제공합니다. `mixin`클래스는 `.get()``.post()`와 같은 핸들러 메서드를 직접 정의하는 것이 아니라 작업 메서드를 제공합니다. 이것은 보다 유연한 작동 구성을 가능하게 합니다.
`mixin`클래스는 `rest_framework.mixins`에서 가져 올 수 있습니다.
### ListModelMixin
쿼리셋 list를 구현하는 `.list(request, *args, **kwargs)`메서드를 제공합니다.
쿼리셋이 채워지면 response의 본문으로 쿼리셋의 serializer 된 표현과 함께 `200 OK`응답을 반환합니다. response 데이터는 선택적으로 페이징 될 수 있습니다.
### CreateModelMixin
새 모델 인스턴스 만들기 및 저장을 구현하는 `.create(request, *args, **kwargs)`메서드를 제공합니다.
객체가 생성되면 객체의 serializer 된 표현을 response의 본문으로 사용하여 `201 Created`응답을 반환합니다. 표현에 `url`이라는 키가 포함되어 있으면 response의 `Location` 헤더가 해당 값으로 채워집니다.
객체 생성을 위해 제공된 request 데이터가 유효하지 않은 경우 `400 Bad Request`응답이 반환되며, 오류 내역은 response 본문으로 반환됩니다.
### RetrieveModelMixin
response에서 기존 모델 인스턴스를 반환하도록 구현하는 `.retrieve(request, *args, **kwargs)`메서드를 반환합니다.
객체를 검색 할 수 있는 경우 `200 OK`응답을 반환하며, 객체를 response 본문으로 serializer하여 반환합니다.
### UpdateModelMixin
기존 모델 인스턴스를 업데이트하고 저장하는 `.update(request, *args, **kwargs)`메서드를 제공합니다.
또한 `update`메소드와 유사한 `.partial_update(request, *args, **kwargs)`메소드도 제공합니다. 단, 업데이트의 모든 필드는 선택사항입니다. 이렇게 하면 HTTP`PATCH`request를 지원할 수 있습니다.
객체가 업데이트되면 객체의 serializer 된 표현이 응답 본문과 함께 `200 OK`응답을 반환합니다.
객체를 업데이트하기 위해 제공된 request 데이터가 유효하지 않은 경우 `400 Bad Request`응답이 반환되고 오류 세부 정보가 response 본문으로 사용됩니다.
### DestroyModelMixin
기존 모델 인스턴스의 삭제를 구현하는 `.destroy(request, *args, **kwargs)`메서드를 제공합니다.
객체가 삭제되면 `204 No Content`응답을 반환하고, 그렇지 않으면 `404 Not Found`을 반환합니다.
---
## Concrete View Classes
다음의 클래스는 구체적인 `generic views`입니다. `generic views`를 사용하는 경우 일반적을 커스터마이징 된 동작이 필요하지 않으면 할만한 수준입니다.
뷰 클래스는 `rest_framework.generics`에서 가져올 수 있습니다.
### CreateAPIView
**읽기 전용** 엔드포인트에 사용됩니다.
`post` 메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [CreateModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#createmodelmixin)
### ListAPIView
**읽기 전용** 엔드포인트가 **모델 인스턴스의 콜렉션**을 나타내는데 사용됩니다.
`get` 메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [ListModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#listmodelmixin)
### RetrieveAPIView
**읽기 전용** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`get`메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [RetrieveModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#retrievemodelmixin)
### DestroyAPIView
**삭제 전용** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`delete`메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [DestroyModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#destroymodelmixin)
### UpdateAPIView
**업데이트 전용** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`put``patch`메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [UpdateModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#updatemodelmixin)
### ListCreateAPIView
**읽기-쓰기** 엔드포인트가 **모델 인스턴스의 컬렉션**를 나타내는데 사용됩니다.
`get``post` 메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [ListModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#listmodelmixin), [CreateModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#createmodelmixin)
### RetrieveUpdateAPIView
**읽거나 업데이트** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`get`, `put`, `patch` 메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [RetrieveModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#retrievemodelmixin), [UpdateModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#updatemodelmixin)
### RetrieveDestroyAPIView
**읽거나 삭제** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`get``delete`메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [RetrieveModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#retrievemodelmixin), [DestroyModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#destroymodelmixin)
### RetrieveUpdateDestroyAPIView
**읽기-쓰기-삭제** 엔드포인트가 **단일 모델 인스턴스**를 나타내는데 사용됩니다.
`get`, `put`, `patch`, `delete`메서드 핸들러를 제공합니다.
Extends: [GenericAPIView](http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview), [RetrieveModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#retrievemodelmixin), [UpdateModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#updatemodelmixin), [DestroyModelMixin](http://www.django-rest-framework.org/api-guide/generic-views/#destroymodelmixin)
---
## Customizing the generic views
종종 기본 generic views를 사용하고 약간 custom 된 동작을 사용하려고 합니다. 여러 위치에서 custom 된 동작을 재사용하는 경우, 동작을 공통 클래스로 리팩토링하여 필요할 때 모든 view나 viewset에 적용할 수 있습니다.
### Creating custom mixins
예를 들어, URL conf 내의 복수의 필드에 근거해 오브젝트를 검색 할 필요가 있는 경우, 다음과 같이 `mixin` 클래스를 작성할 수 있습니다.
```python
class MultipleFieldLookupMixin(object):
"""
Apply this mixin to any view or viewset to get multiple field filtering
based on a `lookup_fields` attribute, instead of the default single field filtering.
"""
def get_object(self):
queryset = self.get_queryset() # 기본 쿼리셋 가져오기
queryset = self.filter_queryset(queryset) # backends에서 필터 적용
filter = {}
for field in self.lookup_fields:
if self.kwargs[field]: # 빈 필드는 무시
filter[field] = self.kwargs[field]
return get_object_or_404(queryset, **filter) # 객체를 찾는다
```
그런 다음 custom 동작을 적용해야 할때 mixin을 view나 viewset에 간단하게 적용할 수 있습니다.
```python
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ('account', 'username')
```
사용해야 하는 custom 동작이 있는 경우, custom mixin을 사용하는 것이 좋습니다.
### Creating custom base classes
여러 views에서 mixin을 사용하는 경우, 이 단계를 더 진행하고 프로젝트 전체에서 사용할 수 있는 고유한 기본 views set을 만들 수 있습니다. 예를 들어:
```python
class BaseRetrieveView(MultipleFieldLookupMixin,
generics.RetrieveAPIView):
pass
class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
generics.RetrieveUpdateDestroyAPIView):
pass
```
프로젝트 전반에 걸쳐 많은 수의 views에서 일관되게 반복해야 하는 custom 동작이 있는 경우, custom 기본 클래스를 사용하는 것이 좋습니다.
---
## PUT as create
버전 3.0 이전에는 객체가 이미 존재하는지 여부에 따라 REST 프레임워크 mixins가 `PUT`을 업데이트나 작성 작업으로 처리했습니다.
생성 작업으로 `PUT`을 허용하는 것은 객체의 존재나 부재에 대한 정보를 반드시 노출시키기 때문에 문제가 됩니다. 또한 이전에 삭제 된 인스턴스를 투명하게 다시 만들수 있다는 것이 단순히 `404`응답을 반환하는 것보다 더 나은 기본 동작이라고 할 수만은 없습니다.
"`PUT` as 404"와 "`PUT` as create"는 서로 다른 상황에서 유효 할 수 있지만, 버전 3.0부터는 더 간단하고 명확한 404 동작을 기본값으로 사용합니다.
일반적인 `PUT-as-create`동작이 필요한 경우 `AllowPUTAsCreateMixin`클래스를 views에 mixin으로 포함할 수 있습니다.
---
## Third party packages
다음의 타사 패키지는 추가 generic view 구현을 제공합니다.
### Django REST Framework bulk
[django-rest-framework-bulk](https://github.com/miki725/django-rest-framework-bulk)패키지는 API request을 통해 대량 작업을 적용할 수 있도록 generic views mixin 뿐만 아니라 일반적인 구체적 generic views를 구현합니다.
### Django Rest Multiple Models
[Django Rest Multiple Models](https://github.com/Axiologue/DjangoRestMultipleModels)은 단일 API request을 통해 여러 serializer된 모델 및 `/` 또는 쿼리셋을 전송하기 위한 generic views(and mixin)을 제공합니다.

View File

@ -0,0 +1,117 @@
# Django REST Framework - Metadata
---
_"[The OPTIONS] method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval."_
_"[OPTIONS] 메소드는 클라이언트가 자원 동작을 암시하거나 자원 검색을 시작하지 않고 자원 또는 서버의 기능과 관련된 옵션 및 `/` 또는 요구 사항을 결정할 수 있게 합니다."_
_— RFC7231, Section 4.3.7._
---
## Metadata
REST 프레임워크는 API가 `OPTIONS` 요청에 어떻게 응답해야 하는지를 결정하기 위한 구성 가능한 메커니즘을 포함합니다. API 스키마 또는 기타 리소스 정보를 반환 할 수 있습니다.
현재 HTTP OPTIONS 요청에 대해 어떤 스타일의 response를 반환해야하는지에 대해 널리 채택 된 규칙이 없으므로 유용한 정보를 반환하는 특별 스타일을 제공합니다.
다음은 기본적으로 반환되는 정보를 보여주는 예제 response입니다.
```python
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
{
"name": "To Do List",
"description": "List existing 'To Do' items, or create a new item.",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"note": {
"type": "string",
"required": false,
"read_only": false,
"label": "title",
"max_length": 100
}
}
}
}
```
### Setting the metadata scheme
`DEFAULT_METADATA_CLASS`설정 키를 사용하여 메타 데이터 클래스를 전역으로 설정할 수 있습니다.
```python
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'
}
```
또는 view에 대해 개별적으로 메타 데이터 클래스를 설정할 수 있습니다.
```python
class APIRoot(APIView):
metadata_class = APIRootMetadata
def get(self, request, format=None):
return Response({
...
})
```
REST 프레임워크 패키지는 `SimpleMetadata`라는 단일 메타 데이터 클래스 구현만 포함됩니다. 다른 스타일을 사용하려면 custom 메타 데이터 클래스를 구현해야합니다.
### Creating schema endpoints
일반 `GET` 요청으로 액서스되는 schema endpoint을 만들기 위한 특정 요구사항이 있는 경우 그렇게 하기 위해 메타 데이터 API를 다시 사용할 수 있습니다.
예를 들어, 다음과 같은 추가 라우트를 vViewSet에 사용하여 linkable schema endpoint에 제공할 수 있습니다.
```python
@list_route(methods=['GET'])
def schema(self, request):
meta = self.metadata_class()
data = meta.determine_metadata(request, self)
return Response(data)
```
`OPTIONS` 응답을 [캐싱할 수 없다는 것](https://www.mnot.net/blog/2012/10/29/NO_OPTIONS)을 포함하여 이 접근 방식을 선택할 수 있는 몇가지 이유가 있습니다.
---
## Custom metadata classes
custom metadata 클래스를 제공하려면 `BaseMetadata`를 대체하고 `decide_metadata(self, request, view)` 메서드를 구현해야합니다.
유용한 정보로는 schema 정보 리턴, [JSON schema](http://json-schema.org/)와 같은 형식 사용 또는 관리자에세 디버그 정보 리턴 등이 있습니다.
### Example
다음 클래스는 `OPTIONS` 요청에 반환되는 정보를 제한하는데 사용될 수 있습니다.
```python
class MinimalMetadata(BaseMetadata):
"""
Don't include field and other information for `OPTIONS` requests.
Just return the name and description.
"""
def determine_metadata(self, request, view):
return {
'name': view.get_view_name(),
'description': view.get_view_description()
}
```
그런 다음 이 custom 클래스를 사용하도록 설정을 구성하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata'
}
```
## Third party packages
다음의 타사 패키지는 추가 메나 데이터 구현을 제공합니다.
### DRF-schema-adapter
[drf-schema-adapter]()는 프론트엔드 프레임워크 및 라이브러리에 스키마 정보를 보다 쉽게 제공할 수 있게 해주는 도구 set입니다. metadata mixin 뿐만 아니라 다양한 라이브러리에 의해 읽을 수 있는 스키마 정보뿐만 아니라 [json-schema](http://json-schema.org/)를 생성하는데 적합한 2개의 metadara 클래스와 여러 어댑터를 제공합니다.
특정 프론트엔드에서 작동하도록 어댑터를 작성할 수도 있습니다. 그렇게 하고 싶다면 스키마 정보를 json 파일로 내보낼 수 있는 내보내기 기능을 제공합니다.

View File

@ -0,0 +1,316 @@
# Django REST Framework - Pagination
---
_"Django provides a few classes that help you manage paginated data that is, data thats split across several pages, with “Previous/Next” links."_
_"Django는 페이지가 매겨진 데이터, 즉 "이전 / 다음" 링크를 사용하여 여러 페이지로 나누어 진 데이터를 관리하는데 도움이 되는 몇가지 클래스를 제공합니다."_
_— Django documentation_
---
## Pagination
REST 프레임워크는 custom 가능한 pagination 스타일을 지원합니다. 이렇게 하면 큰 result sets을 개별 데이터 페이지로 분할하는 방법을 수정할 수 있습니다.
pagination API는 다음 중 하나를 지원할 수 있습니다.
- resopnse 내용의 일부로 제공되는 pagination 링크
- `Content-Range` 또는 `Link`와 같은 response header에 포함 된 pagination 링크
내장된 스타일은 현재 response 내용의 일부로 포함된 링크를 사용합니다. 이 스타일은 browsable API를 사용할 때 더 쉽게 액서스 할 수 있습니다.
pagination은 generic view 또는 viewset를 사용하는 경우에만 자동으로 수행됩니다. 일반 `APIView`를 사용하는 경우 pagination 된 response를 반환하도록 pagination API를 직접 호출해야 합니다. 예를 들어, `mixins.ListModelMixin``generics.GenericAPIView` 클래스의 소스 코드를 참조하세요.
pagination 클래스를 `None`으로 설정하면 pagination을 끌 수 있습니다.
### Setting the pagination style
기본 pagination 스타일은 `DEFAULT_PAGINATION_CLASS``PAGE_SIZE` 설정 키를 사용하여 전체적으로 설정할 수 있습니다. 예를 들어 내장 된 limit / offset pagination을 사용하려면 다음과 같이 하면 됩니다.
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
```
pagination 클래스와 사용할 페이지 크를 모두 설정해야 합니다.
`pagination_class`속성을 사용하여 개별 view에서 pagination 클래스를 설정 할 수도 있습니다. 일반적으로 API 전체에서 동일한 pagination 스타일을 사용하고 싶지만 view마다 기본 페이지 또는 최대 페이지 크기가 같은 pagination의 개별적인 측면을 바꿀 수도 있습니다.
### Modifying the pagination style
pagination 스타일의 특정 측면을 수정하려면 pagination 클래스 중 하나를 오버라이드하고 변경하려는 속성을 설정해야 합니다.
```python
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
```
그런 다음 `.pagination_class` 속성을 사용하여 뷰에 새 스타일을 적용 할 수 있습니다.
```python
class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all()
serializer_class = BillingRecordsSerializer
pagination_class = LargeResultsSetPagination
```
또는 `DEFAULT_PAGINATION_CLASS` 설정 키를 사용하여 스타일을 전역적으로 적용하세요. 예:
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
```
---
## API Reference
### PageNumberPagination
이 pagination 스타일은 request 쿼리 parameter에 단일 숫자 페이지 번호를 허용합니다.
**Request**:
```
GET https://api.example.org/accounts/?page=4
```
**Response**:
```
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [
]
}
```
#### Setup
`PageNumberPagination`스타일을 전역적으로 사용하려면 다음 구성을 사용하여 `PAGE_SIZE`를 원하는대로 수정하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
```
`GenericAPIView` 서브 클래스에서 `pagination_class`속성을 설정하여 페이지 단위로 `PageNumberPagination`을 선택할 수도 있습니다.
#### Configuration (구성)
`PageNumberPagination`클래스는 pagination 스타일을 수정하기 위해 오버라이드 될 수 있는 여러 속성을 포함합니다.
이러한 속성을 설정하려면 `PageNumberPagination`클래스를 오버라이드 한 다음 위와 같이 custom pagination 클래스를 활성화해야합니다.
- `django_paginator_class` : 사용할 Django Paginator 클래스입니다. 기본값은 `django.core.paginator.Paginator`입니다. 대부분의 사용 사례에서 괜찮습니다.
- `page_size` : 페이지 크기를 나타내는 숫자 값입니다. 설정된 경우 `PAGE_SIZE` 설정보다 우선합니다. 기본값은 `PAGE_SIZE` 설정 키와 동일한 값입니다.
- `page_query_param` : pagination 컨트롤에 사용할 쿼리 parameter의 이름을 나타내는 문자열 값입니다.
- `page_size_query_param` : 설정된 경우 클라이언트가 request 별로 페이지 크기를 설정할 수 있도록하는 쿼리 parameter의 이름을 나타내는 문자열 값입니다. 기본값은 `None`으로, 클라이언트가 요청 된 페이지 크기를 제어 할 수 없음을 나타냅니다.
- `max_page_size` : 설정되면 request 된 최대 페이지 크기를 나타내는 숫자 값입니다. 이 속성은 `page_size_query_param`도 설정되어있는 경우에만 유효합니다.
- `last_page_strings` : `page_query_param`과 함께 사용되어 최종 페이지를 요청할 수있는 값을 나타내는 문자열 값의 list 또는 tuple 입니다. 기본값은 `('last',)` 입니다.
- `template` : browsable API에서 pagination 컨트롤을 렌더링 할 때 사용할 템플릿의 이름입니다. 렌더링 스타일을 수정하기 위해 오버라이드 되거나 HTML pagination 컨트롤을 완전히 비활성화하려면 `None`으로 설정 할 수 있습니다. 기본값은 `"rest_framework / pagination / numbers.html"`입니다.
---
### LimitOffsetPagination
이 pagination 스타일은 여러 데이터베이스 레코드를 찾을 때 사용되는 구문을 반영합니다. 클라이언트에는 "limit"와 "offset" 쿼리 parameter가 모두 포함됩니다. **limit** 는 반환 할 최대 항목 수를 나타내며 다른 스타일의 `page_size`와 같습니다. **offset**은 unpaginated 된 항목의 완성된 set과 관련하여 쿼리의 시작 위치를 나타냅니다.
**Request**:
```
GET https://api.example.org/accounts/?limit=100&offset=400
```
**response**:
```python
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?limit=100&offset=500",
"previous": "https://api.example.org/accounts/?limit=100&offset=300",
"results": [
]
}
```
#### Setup
`LimitOffsetPagination` 스타일을 전역적으로 사용하려면 다음 구성을 사용하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
```
선택적으로 `PAGE_SIZE` 키를 설정 할 수도 있습니다. `PAGE_SIZE` parameter도 사용되는 경우 `limit` 쿼리 parameter는 선택사항이며 클라이언트가 생략할 수 있습니다.
`GenericAPIView` 서브 클래스에서는 `pagination_class`속성을 설정하여 각 뷰별로 `LimitOffsetPagination`을 선택할 수 있습니다.
#### Configuration
`LimitOffsetPagination` 클래스에는pagination 스타일을 수정하기 위해 오버라이드 할 수 있는 많은 속성이 포함되어 있습니다.
이러한 속성을 설정하려면 `LimitOffsetPagination`클래스를 오버라이드 한 다음 위와 같이 custom pagination 클래스를 활성화해야 합니다.
- `default_limit` : 쿼리 parameter에서 클라이언트가 제공하지 않을 경우 사용할 제한을 나타내는 숫자 값입니다. 기본값은 `PAGE_SIZE` 설정 키와 동일한 값입니다.
- `limit_query_param` : "limit" 쿼리 parameter의 이름을 나타내는 문자열 값입니다. 기본값은 `'limit'`입니다.
- `offset_query_param` : "offset" 쿼리 parameter의 이름을 나타내는 문자열 값입니다. 기본값은 `'offset'`입니다.
- `max_limit` : 설정된 경우 클라이언트가 요청할 수있는 최대 허용 한계를 나타내는 숫자 값입니다. 기본값은 `None`입니다.
- `template` : browsable API에서 페이지 매김 컨트롤을 렌더링 할 때 사용할 템플릿의 이름입니다. 렌더링 스타일을 수정하기 위해 오버라이드 되거나 HTML pagination 컨트롤을 완전히 비활성화하려면 `None`으로 설정 될 수 있습니다. 기본값은 `"rest_framework / pagination / numbers.html"`입니다.
---
### CursorPagination
cursor 기반 pagination은 클라이언트가 result set를 통해 페이지 할 때 사용할 수 있는 불투명한 "cursor" 지시자를 제공합니다. 이 pagination 스타일은 정방향 및 역방향 컨트롤만 제공하며 클라이언트가 임의의 위치로 이동할 수 없도록 합니다.
cursor를 기반으로 pagination을 수행하려면 result set에 items의 순서가 변경되지 않아야 합니다. 일반적으로 이 순서는 레코드에 대한 생성 timestamp 일 수 있습니다. 이는 pagination 순서를 일관되게 유지하기 때문입니다.
cursor 기반 pagination은 다른 스키마보다 복잡합니다. 또한 result set이 고정 된 순서를 제공해야하며 클라이언트가 임의로 result set에 색인을 작성할 수 없도록 해야합니다. 그러나 다음과 같은 이점을 제공합니다.
- 일관된 pagination 을 제공합니다. 제대로 사용하면 `CursorPagination`은 pagination 과정에서 다른 클라이언트가 새 항목을 삽입하는 경우에도 클라이언트가 레코드를 페이징 할 때 동일한 item을 두번 보지 못하게 합니다.
- 매우 큰 데이터 set 사용을 지원합니다. 극도로 큰 데이터 set의 경우 offset 기반 pagination 스타일을 사용하는 pagination이 비효율적이거나 사용할 수 없게 될 수 있습니다. 대신 cursor 기반 pagination 스키마는 고정 시간 속성을 가지며 데이터 set 크기가 커질수록 속도가 느려지지 않습니다.
#### Details and limitations
cursor 기반의 pagination을 올바르게 사용하려면 세부 사항에 약간의 주의가 필요합니다. 우리는 계획을 적용하기를 원하는 순서에 대해 생각할 필요가 있습니다. 기본값은 `"-created"`입니다. 여기에는 모델 인스턴스에 **'created' timestamp 필드가 꼭 있어야하며** 가장 최근에 추가 된 항목이 먼저 나오는 "timeline" 스타일 pagination view가 제공됩니다.
pagination 클래스의 `'ordering'`속성을 무시하거나 `OrderingFilter` 필터 클래스를 `CursorPagination`과 함께 사용하여 순서를 수정할 수 있습니다. `OrderingFilter`와 함께 사용하는 경우 사용자가 주문 할 수 있는 입력란을 제한하는 것이 좋습니다.
커서 pagination 을 올바르게 사용하려면 다음을 만족시키는 ordering 필드가 있어야 합니다.
- 생성시 timestamp, slug 또는 한번만 설정되는 다른 필드와 같은 변경되지 않은 값이어야 합니다.
- 고유하거나 거의 고유해야합니다. Millisecond 정밀도 timestamp가 좋은 예입니다. 이 cursor pagination의 구현은 똑똑한 "position plus offset"스타일을 사용하여 엄격하게 고유하지 않은 값을 순서대로 올바르게 지원할 수 있습니다.
- null이 허용하지 않는 값이어야 합니다.(문자열로 강제 변환 될 수 있습니다.)
- 필드에는 데이터베이스 색인이 있어야합니다.
이러한 제약 조건을 만족시키지 못하는 ordering field를 사용하면 일반적으로 작동하지만 cursor pagination의 이점을 일부 상실하게 됩니다.
cursor pagination에 사용되는 구현에 대한 자세한 정보는 ["Building cursors for the Disqus API"](http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api)블로그 게시물에서 기본 접근 방법에 대한 개요를 제공합니다.
#### Setup
`CursorPagination` 스타일을 전역적으로 사용하려면 다음 구성을 사용하여 `PAGE_SIZE`를 원하는대로 수정하십시오.
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 100
}
```
`GenericAPIView` 서브 클래스에서 `pagination_class` 속성을 설정하여 뷰 단위로 `CursorPagination`을 선택할 수도 있습니다.
#### Configuration
`CursorPagination` 클래스에는 pagination 스타일을 수정하기 위해 오버라이드 될 수 있는 많은 속성이 포함되어 있습니다.
이러한 속성을 설정하려면 `CursorPagination`클래스를 오버라이드 한 다음 위와 같이 custom pagination 클래스를 활성화해야 합니다.
- `page_size` : 페이지 크기를 나타내는 숫자 값입니다. 설정된 경우 `PAGE_SIZE` 설정보다 우선합니다. 기본값은 `PAGE_SIZE` 설정 키와 동일한 값입니다
- `cursor_query_param` : "cursor" 쿼리 parameter의 이름을 나타내는 문자열 값입니다. 기본값은 `'cursor'`입니다.
- `ordering` : cursor 기반의 pagiation이 적용될 필드를 나타내는 문자열 또는 문자열 list 이어야합니다. (예: `ordering = 'slug'`) 기본값은 `-created`입니다. 뷰에서 `OrderingFilter`를 사용하여 이 값을 오버라이드 할 수도 있습니다.
- `template` : browsable API에서 pagination 컨트롤을 렌더링 할 때 사용할 템플릿의 이름입니다. 렌더링 스타일을 수정하기 위해 오버라이드 되거나 HTML pagination 컨트롤을 완전히 비활성화하려면 `None`으로 설정 될 수 있습니다. 기본값은 `"rest_framework/pagination/previous_and_next.html"`입니다.
---
## Custom pagination styles
Custom pagination serializer 클래스를 생성하려면 `pagination.BasePagination`을 서브 클래스화하고 `paginate_queryset(self, queryset, request, view = None)``get_paginated_response(self, data)` 메소드를 오버라이드 해야합니다.
- `paginate_queryset` 메소드는 초기 쿼리셋을 전달 받고 요청 된 페이지의 데이터만 포함하는 반복 가능한 객체를 반환해야합니다.
- `get_paginated_response` 메소드는 serializer 된 페이지 데이터를 전달 받고 Response 인스턴스를 반환해야합니다.
`paginate_queryset` 메소드는 페이지 설정 인스턴스에 상태를 설정할 수 있으며 나중에 `get_paginated_response` 메소드에서 사용할 수 있습니다.
### Example
기본 pagination output 스타일을 중첩 된 'links' 키 아래의 다음 링크와 이전 링크를 포함하는 수정된 형식으로 바꾸려한다고 가정합니다. 다음과 같이 custom pagination 클래스를 지정할 수 있습니다.
```python
class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
},
'count': self.page.paginator.count,
'results': data
})
```
그런 다음 구성에서 custom 클래스를 설정해야합니다
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
'PAGE_SIZE': 100
}
```
browsable API의 response에서 키의 순서가 어떻게 표시되는지 신경 쓰면 pagination 된 response의 본문을 구성할 때 `OrderedDict`를 사용하도록 선택할 수 있지만 선택사항입니다.
### Header based pagination
내장 된 `PageNumberPagination` 스타일을 수정하여 response 본문에 pagination 링크를 포함하는 대신 [GitHub API와 비슷한 스타일](https://developer.github.com/guides/traversing-with-pagination/)로 `link` 헤더를 포함합니다.
```python
class LinkHeaderPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
next_url = self.get_next_link()
previous_url = self.get_previous_link()
if next_url is not None and previous_url is not None:
link = '<{next_url}>; rel="next", <{previous_url}>; rel="prev"'
elif next_url is not None:
link = '<{next_url}>; rel="next"'
elif previous_url is not None:
link = '<{previous_url}>; rel="prev"'
else:
link = ''
link = link.format(next_url=next_url, previous_url=previous_url)
headers = {'Link': link} if link else {}
return Response(data, headers=headers)
```
### Using your custom pagination class
custom pagination 클래스를 기본적으로 사용하려면 `DEFAULT_PAGINATION_CLASS` 설정을 사용하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
'PAGE_SIZE': 100
}
```
이제 endpoint에 대한 API response에는 페이지 본문 링크를 response 본문의 일부로 포함하는 대신 `link`헤더가 포함됩니다.
### Pagination & schemas
또한 `coreapi.Field` 인스턴스의 list를 반환해야하는 `get_schema_fields()` 메소드를 구현하여 REST 프레임워크가 제공하는 스키마 자동 생성에서 pagination 컨트롤을 사용할 수 있게 만들 수 있습니다.
---
![](./images/linkheader.png)
`link`헤더를 사용하는 custom pagination 스타일
---
## HTML pagination controls
기본적으로 pagination 클래스를 사용하면 browsable API에 HTML pagination 컨트롤이 표시됩니다. 두 가지 내장 디스플레이 스타일이 있습니다. `PageNumberPagination``LimitOffsetPagination` 클래스는 이전 및 다음 컨트롤이 포함 된 페이지 번호 목록을 표시합니다. `CursorPagination` 클래스는 이전 및 다음 컨트롤만 표시하는 보다 단순한 스타일을 표시합니다.
### Customizing the controls
HTML pagination 컨트롤을 렌더링하는 템플릿을 오버라이드 할 수 있습니다. 두 가지 기본 제공 스타일은 다음과 같습니다.
- rest_framework/pagination/numbers.html
- rest_framework/pagination/previous_and_next.html
전역 템플릿 디렉토리에 이러한 경로 중 하나가 있는 템플릿을 제공하면 관련 pagination 클래스의 기본 렌더링이 무시됩니다.
또는 기존 클래스를 하위 클래스로 분류하고 클래스의 속성으로 `template = None`을 설정하여 HTML pagination 컨트롤을 완전히 비활성화 할 수 있습니다. 그런 다음 custom 클래스를 기본 pagination 스타일로 사용하려면 `DEFAULT_PAGINATION_CLASS` 설정 키를 구성해야합니다.
#### Low-level API
pagination 클래스가 컨트롤을 표시할지 어떨지를 결정하기 위한 저레벨의 API는, pagination 인스턴스의 `display_page_controls` 속성으로서 공개되고 있습니다. HTML pagination 컨트롤을 표시해야하는 경우 `paginate_queryset` 메서드에서 custom pagination 클래스를 `True`로 설정해야합니다.
`.to_html()``.get_html_context()` 메소드는 컨트롤이 렌더링되는 방식을 추가로 custom하기 위해 custom pagination 클래스에서 오버라이드 될 수도 있습니다.
## Third party packages
다음의 타사 패키지도 제공됩니다.
### DRF-extensions
[`DRF-extensions` 패키지](http://chibisov.github.io/drf-extensions/docs/)에는 [`PaginateByMaxMixin` mixin 클래스](http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin)가 포함되어있어 API 클라이언트가 허용되는 최대 페이지 크기를 얻기 위해`?page_size=max`를 지정할 수 있습니다.
### drf-proxy-pagination
[`drf-proxy-pagination` 패키지](https://github.com/tuffnatty/drf-proxy-pagination)는 쿼리 parameter로 pagination 클래스를 선택할 수 있는 `ProxyPagination` 클래스를 포함합니다.

View File

@ -0,0 +1,206 @@
# Django REST Framework - Parsers
---
_"Machine interacting web services tend to use more structured formats for sending data than form-encoded, since they're sending more complex data than simple forms"_
_"웹 서비스를 상호 작용하는 기계는 단순한 형식보다 복잡한 데이터를 전송하기 때문에 양식으로 인코딩 된 것보다 데이터 전송에 더 많은 구조화 된 형식을 사용하는 경향이 있습니다."_
_— Malcom Tredinnick, Django developers group_
---
## Parsers
REST 프레임워크에는 `Parser`클래스가 내장되어 있어 다양한 미디어 타입으로 requests를 수락할 수 있습니다. 또한 `custom parser`를 정의 할 수 있어서 API에서 허용하는 미디어 타입을 유연하게 디자인 할 수 있습니다.
### How the parser is determined
뷰에 대한 유효한 parser set은 항상 클래스 목록으로 정의됩니다. `request.data`에 액서스하면 REST 프레임워크는 들어오는 request의 `Content-Type` 헤더를 검사하고 request 내용을 parse하는데 사용할 `parser`를 결정합니다.
---
**Note**: 클라이언트 응용 프로그램을 개발할 때는 항상 HTTP request로 데이터를 보낼때 `Content-Type`헤더를 설정해야 합니다.
콘텐트 타입을 설정하지 않으면 대부분의 클라이언트는 `'application/x-www-form-urlencoded'`를 기본값으로 사용합니다. 이는 원하지 않을 수 있습니다.
예를 들어, `.ajax()`메서드로 jQuery를 사용하여 `json`으로 인코딩 된 데이터를 보내는 경우, `contentType: 'application/json'`설정을 포함해야 합니다.
---
### Setting the parsers
`parser`의 기본 set은 `DEFAULT_PARSER_CLASSES` 설정을 사용하여 전역으로 설정할 수 있습니다. 예를 들어, 다음 설정은 기본 JSON 이나 formdata 대신 JSON 컨텐트가 있는 requests만 허용합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
)
}
```
`APIView`클래스의 기본 views를 사용하여 개별 view나 viewset에 사용되는 `parser`를 설정할 수도 있습니다.
```python
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
"""
A view that can accept POST requests with JSON content.
"""
parser_classes = (JSONParser,)
def post(self, request, format=None):
return Response({'received data': request.data})
```
또는 FBV와 함께 `@api_view`데코레이터를 사용하는 경우.
```python
from rest_framework.decorators import api_view
from rest_framework.decorators import parser_classes
@api_view(['POST'])
@parser_classes((JSONParser,))
def example_view(request, format=None):
"""
A view that can accept POST requests with JSON content.
"""
return Response({'received data': request.data})
```
---
## API Reference
### JSONParser
`JSON` request content를 파싱합니다.
**.media_type**: `application/json`
### FormParser
HTMl form content를 파싱합니다. `request.data`는 데이터의 `QueryDict`로 채워집니다.
일반적으로 HTML form data를 완벽하게 지원하기 위해 `FormParser``MultiPartParser`를 함께 사용하려고 합니다.
**.media_type**: `application/x-www-form-urlencoded`
### MultiPartParser
파일 업로드를 지원하는 `Multi form content`를 파싱합니다. 두 `request.data` 모두 `QueryDict`로 채워집니다.
일반적으로 HTML form data를 완벽하게 지원하기 위해 `FormParser``MultiPartParser`를 함께 사용하려고 합니다.
**.media_type**: `multipart/form-data`
### FileUploadParser
가공되지 않은 file upload content를 파싱함니다. `request.data` 속성은 업로드 된 파일을 포함하는 단일 키`'file'`이 포함된 dict입니다.
`FileUploadParser`와 함께 사용 된 view가 파일 이름 URL 키워드 인수로 호출되면 해당 인수가 filename 으로 사용됩니다.
`filename` URL 키워드 인수없이 호출되면 클라이언트는 `Content-Disposition` HTTP 헤더에 filename을 설정해야 합니다. 예를 들면, `Content-disposition: attachment; filename=upload.jpg`
**.media_type**: `*/*`
###### notes:
- `FileUploadParser`는 파일을 가공되지 않은 데이터 request으로 업로드 할 수 있는 기본 클라이언트에서 사용하기 위한 것입니다. 웹 기반 업로드 또는 멀티 파트 업로드가 지원되는 기본 클라이언트의 경우 `MultiPartParser` 파서를 대신 사용해야합니다.
- 이 파서의 `media_type`은 모든 콘텐트 타입과 일치하므로 `FileuploadParser`는 일반적으로 API view에 설정된 유일한 `parser` 이어야 합니다.
- `FileUploadParser`는 Django의 표준 `FILE_UPLOAD_HANDLERS` 설정과 `request.upload_handlers` 속성을 고려합니다. 자세한 내용은 [Django 문서](https://docs.djangoproject.com/en/1.10/topics/http/file-uploads/#upload-handlers)를 참조하세요.
###### Basic usage example:
```python
# views.py
class FileUploadView(views.APIView):
parser_classes = (FileUploadParser,)
def put(self, request, filename, format=None):
file_obj = request.data['file']
# ...
# do some stuff with uploaded file
# ...
return Response(status=204)
# urls.py
urlpatterns = [
# ...
url(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view())
]
```
---
## Custom parsers
`custom parser`를 구현하려면 `BaseParser`를 오버라이드하고 `.media_type`속성을 설정하고 `.parse(self, stream, media_type, parser_context)`메소드를 구현해야 합니다.
메서드는 `request.data`속성을 채우는데 사용할 데이터를 반환해야합니다.
`.parse()`에 전달된 인수는 다음과 같습니다.
### stream
request의 본문을 나타내는 스트림과 같은 객체입니다.
### media_type
선택사항. 제공되는 경우 들어오는 request content의 미디어 타입입니다.
request의 `Content-Type:` 헤더에 따라 렌더러의 `media_type`속성보다 더 구체적일 수 있으며, 미디어 타입 parameter가 포함 될 수 있습니다. 예: `"text/plain; charset=utf-8"`
### parser_context
선택사항. 이 인수가 제공되면 request content을 파싱하는데 필요할 수 있는 추가 context를 포함하는 dict가 됩니다.
기본적으로 `view`, `request`, `args`, `kwargs` 키들이 포함됩니다.
### Example
다음은 request content를 나타내는 문자열로 `request.data`속성을 채우는 일반 텍스트 파서의 예입니다.
```python
class PlainTextParser(BaseParser):
"""
Plain text parser.
"""
media_type = 'text/plain'
def parse(self, stream, media_type=None, parser_context=None):
"""
Simply return a string representing the body of the request.
"""
return stream.read()
```
---
## Third party packages
다음의 타사 패키지도 제공됩니다.
### YAML
[REST 프레임 워크 YAML](http://jpadilla.github.io/django-rest-framework-yaml/)은 [YAML](http://www.yaml.org/) 파싱 및 렌더링 지원을 제공합니다. 이전에 REST 프레임워크 패키지에 직접 포함되어 있었으며 이제는 타사 패키지로 대신 지원됩니다.
###### 설치 및 구성
pip를 사용하여 설치합니다.
```
$ pip install djangorestframework-yaml
```
REST 프레임워크 설정을 수정하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_yaml.parsers.YAMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_yaml.renderers.YAMLRenderer',
),
}
```
### XML
[REST 프레임워크 XML](http://jpadilla.github.io/django-rest-framework-xml/)은 간단한 비공식 XML 형식을 제공합니다. 이전에 REST 프레임 워크 패키지에 직접 포함되어 있었으며 이제는 타사 패키지로 대신 지원됩니다.
###### 설치 및 구성
pip를 사용하여 설치합니다.
```
$ pip install djangorestframework-xml
```
REST 프레임워크 설정을 수정하세요.
```python
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_xml.parsers.XMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_xml.renderers.XMLRenderer',
),
}
```
### MessagePack
[MessagePack](https://github.com/juanriaza/django-rest-framework-msgpack)은 빠르고 효율적인 바이너리 serializer 형식입니다. [Juan Riaza](https://github.com/juanriaza)는 MessagePack 렌더러와 REST 프레임 워크에 대한 파서 지원을 제공하는 [djangorestframework-msgpack 패키지](https://github.com/juanriaza/django-rest-framework-msgpack)를 유지 관리합니다.
### CamelCase JSON
[djangorestframework-camel-case](https://github.com/vbabiy/djangorestframework-camel-case)는 REST 프레임워크를 위한 `parser`와 camel-case JSON 렌더러를 제공합니다. 이를 통해 serializer는 파이썬 스타일의 underscored 필드 이름을 사용할 수 있지만, 자바 스크립트 스타일의 camel case field names으로 API에 표시됩니다. 그것은 [Vitaly Babiy](https://github.com/vbabiy)에 의해 관리됩니다.

View File

@ -0,0 +1,239 @@
# Django REST Framework - Permissions
---
_"Authentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization."_
_"정보 또는 코드에 대한 액서스 권한을 얻으려면 일반적으로 인증이나 식별만으로는 충분하지 않습니다. 이를 위해서는 액서스를 요청하는 개체에 권한이 있어야합니다."_
_— Apple Developer Documentation_
---
## Permissions
[인증](http://www.django-rest-framework.org/api-guide/authentication/) 및 [제한](http://www.django-rest-framework.org/api-guide/throttling/)과 함께 사용 권한은 request에 액서스를 허용할지 또는 거부 할지를 결정합니다.
권한 검사는 다른 코드가 진행되기 전에 view의 맨 처음에 항상 실행됩니다. 권한 검사는 일반적으로 들어오는 request를 허용해야 하는지를 결정하기 위해 `request.user``request.auth` 등록 정보의 인증 정보를 사용합니다.
권한은 다른 클래스의 사용자가 API의 다른 부분에 액서스 하는 것을 허용하거나 거부하는게 사용됩니다.
가장 간단한 사용 권한 스타일은 인증 된 사용자에게 멕서스를 허용하고 인증되지 않은 모든 사용자에 대한 엑서스를 거부하는 것입니다. 이것은 REST프레임워크의 `IsAuthenticated`클래스에 해당합니다.
약간 덜 엄격한 권한 스타일은 인증 된 사용자에게 모든 권한을 허용하지만 인증되지 않은 사용자에게는 읽기전용 권한을 허용하는 것입니다. 이것은 REST 프레임워크의 `IsAuthenticatedOrReadOnly` 클래스에 해당합니다.
### How permissions are determined
REST 프레임워크의 권한은 항상 클래스 list로 정의됩니다.
뷰의 본문을 실행하기 전에 list의 각 권한이 검사됩니다. 권한 확인에 실패하면 `exceptions.PermissionDenied` 또는 `exceptions.NotAuthenticated` 예외가 발생하고 view 본문이 실행되지 않습니다.
권한 검사가 실패하면 다음 규칙에 따라 "403 Forbidden"또는 "401 Unauthorized"응답이 반환됩니다.
- 요청이 성공적으로 인증되었지만 권한이 거부되었습니다. - HTTP 403 Forbidden 응답이 리턴됩니다.
- 요청이 성공적으로 인증되지 않았고 최상위 우선 순위 인증 클래스는 `WWW-Authenticate` 헤더를 사용하지 않습니다. - HTTP 403 Forbidden 응답이 리턴됩니다.
- 요청이 성공적으로 인증되지 않았고 최상위 우선 순위 인증 클래스는 `WWW-Authenticate` 헤더를 사용합니다. - 적절한 `WWW-Authenticate` 헤더가 있는 HTTP 401 Unauthorized 응답이 반환됩니다.
### Object level permissions
REST 프레임워크 권한은 또한 오브젝트 레벨 권한 부여를 지원합니다. 개체 수준 권한은 사용자가 특정 개체(일반적으로 모델 인스턴스)에 대한 작업을 허용해야하는지 여부를 결정하는 데 사용됩니다.
객체 레벨 권한은 `.get_object()`가 호출 될 때 REST 프레임워크의 generic view에 의해 실행됩니다. 뷰 수준 권한과 마찬가지로, 사용자가 지정된 객체를 처리할 수 없는 경우 `exceptions.PermissionDenied` 예외가 발생합니다.
자신 만의 뷰를 작성하고 오브젝트 레벨 권한을 적용하려는 경우 또는 generic 뷰에서 `get_object` 메소드를 겹쳐 쓰는 경우에는, 개체를 검색 한 시점에서 뷰에서 `.check_object_permissions(request, obj)` 메소드를 명시적으로 호출해야합니다.
`PermissionDenied` 또는 `NotAuthenticated` 예외가 발생하거나 view에 적절한 권한이 있는 경우 반환됩니다.
예:
```python
def get_object(self):
obj = get_object_or_404(self.get_queryset())
self.check_object_permissions(self.request, obj)
return obj
```
#### Limitations of object level permissions(개체 수준 사용 권한의 제한 사항)
성능 상의 이유로 generic view는 오브젝트 목록을 리턴 할 때 queryset의 각 인스턴스에 오브젝트 레벨 권한을 자동으로 적용하지 않습니다.
객체 레벨 권한을 사용하는 경우 종종 [쿼리 세트를 적절히 필터링](http://www.django-rest-framework.org/api-guide/filtering/)하여 사용자가 볼 수있는 인스턴스에 대한 가시성만 확보하도록 하는 것이 좋습니다.
### Setting the permission policy
기본 권한 정책은 `DEFAULT_PERMISSION_CLASSES` 설정을 사용하여 전역으로 설정할 수 있습니다. 예를 들면.
```python
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
```
지정하지 않으면이 설정은 기본적으로 무제한 액세스를 허용합니다.
```python
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
```
또한 `APIView` CBV를 사용하여 view 별 또는 view 별 기준별로 인증 정책을 설정할 수 있습니다.
```python
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
```
또는 FBV와 함께 @api_view` 데코레이터를 사용하는 경우.
```python
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
```
**Note**: 클래스 속성이나 데코레이터를 통해 새 권한 클래스를 설정하면 **settings.py** 파일을 통해 설정된 기본 목록을 무시하도록 뷰에 지시합니다.
---
## API Reference
### AllowAny
`AllowAny` 권한 클래스는 **요청이 인증되었거나 인증되지 않았는지 여부에 관계없이** 제한되지 않은 액세스를 허용합니다.
사용 권한 설정에 빈 목록이나 튜플을 사용하여 동일한 결과를 얻을 수 있기 때문에 이 사용 권한은 반드시 필요한 것은 아니지만 의도를 명시적으로 지정하기 때문에 이 클래스를 지정하는 것이 유용 할 수 있습니다.
### IsAuthenticated
`IsAuthenticated` 권한 클래스는 인증되지 않은 사용자에게 권한을 거부하고 그렇지 않은 경우에는 권한을 허용합니다.
이 권한은 등록 된 사용자만 API에 액세스 할 수 있게 하려는 경우 적합합니다.
### IsAdminUser
`IsAdminUser` 권한 클래스는 `user.is_staff``True` 인 경우를 제외하고 모든 사용자에 대한 사용 권한을 거부합니다.
이 권한은 신뢰할 수 있는 관리자의 하위 집합에서만 API에 액세스 할 수 있게 하려는 경우 적합합니다.
### IsAuthenticatedOrReadOnly
`IsAuthenticatedOrReadOnly`를 사용하면 인증 된 사용자가 모든 요청을 수행 할 수 있습니다.
권한이 없는 사용자에 대한 요청은 요청 방법이 **"안전한"**방법 중 하나일 경우에만 허용됩니다. `GET`, `HEAD` 또는 `OPTIONS`.
이 권한은 API에서 익명 사용자에게 읽기 권한을 허용하고 인증 된 사용자에게만 쓰기 권한을 허용하려는 경우에 적합합니다.
### DjangoModelPermissions
이 퍼미션 클래스는 Django의 표준 `django.contrib.auth` [모델 퍼미션](https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#custom-permissions)과 관련이 있습니다. 이 권한은 `.queryset` 속성이 설정된 view에만 적용해야합니다. 권한 부여는 사용자가 인증되고 관련 모델 권한이 할당 된 경우에만 부여됩니다.
- `POST` request를 사용하려면 사용자에게 모델에 대한 `add` 권한이 있어야합니다.
- `PUT``PATCH` request는 사용자가 모델에 대한 변경 권한을 요구합니다.
- `DELETE` request는 사용자에게 모델에 대한 삭제 권한이 있어야합니다.
기본 동작을 재정의하여 사용자 지정 모델 권한을 지원할 수도 있습니다. 예를 들어 `GET` 요청에 대한 view 모델 권한을 포함 할 수 있습니다.
custom 모델 권한을 `DjangoModelPermissions`을 오버라이드하고 `.perms_map` property를 설정하여 사용합니다.
#### Using with views that do not include a queryset attribute. (queryset 속성을 포함하지 않는 뷰를 사용할 때)
재정의 된 `get_queryset()` 메서드를 사용하는 뷰에서 이 권한을 사용하는 경우 뷰에 `queryset` 속성이 없을 수 있습니다. 이 경우에는 sentinel queryset으로 뷰를 표시하여 이 클래스가 필요한 권한을 결정할 수 있도록하는 것이 좋습니다. 예 :
```
queryset = User.objects.none() # Required for DjangoModelPermissions
```
### DjangoModelPermissionsOrAnonReadOnly
`DjangoModelPermissions`와 유사하지만 인증되지 않은 사용자는 API에 대한 읽기 전용 액세스만 허용합니다.
### DjangoObjectPermissions
이 퍼미션 클래스는 모델에 대한 객체 별 권한을 허용하는 Django의 표준 [객체 권한 프레임워크](https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#handling-object-permissions)와 관련이있다. 이 권한 클래스를 사용하려면 [`django-guardian`](https://github.com/django-guardian/django-guardian)과 같은 객체 수준 권한을 지원하는 권한 백엔드를 추가해야합니다.
`DjangoModelPermissions`와 마찬가지로 이 권한은 `.queryset` 속성이나 `.get_queryset()` 메소드가 있는 뷰에만 적용되어야합니다. 권한 부여는 사용자가 인증되고 관련 객체 별 권한 및 관련 모델 권한이 할당 된 경우에만 부여됩니다.
- `POST` request는 사용자에게 모델 인스턴스에 대한 추가 권한이 필요합니다.
- `PUT``PATCH` request는 사용자가 모델 인스턴스에 대한 변경 권한을 요구합니다.
- `DELETE` 요청은 사용자에게 모델 인스턴스에 대한 삭제 권한이 있어야합니다.
`DjangoObjectPermissions``django-guardian` 패키지를 **필요로 하지 않으며** 다른 객체 레벨 백엔드도 똑같이 잘 지원해야합니다.
`DjangoModelPermissions`와 마찬가지로 `DjangoObjectPermissions`를 재정의하고 `.perms_map` 속성을 설정하여 사용자 정의 모델 권한을 사용할 수 있습니다. 자세한 내용은 소스 코드를 참조하십시오.
---
**Note**: `GET`, `HEAD``OPTIONS` request에 대한 객체 수준 view 권한이 필요하면 `DjangoObjectPermissionsFilter` 클래스를 추가하여 목록 엔드포인트가 사용자에게 적절한 뷰 권한이 있는 객체를 포함하여 결과만 반환하도록 해야합니다.
---
## Custom permissions
Custom 권한을 구현하려면, `BasePermission`를 무시하고 다음 중 하나 또는 두가지 방법을 구현합니다.
- `.has_permission(self, request, view)`
- `.has_object_permission(self, request, view, obj) `
request에 액세스 권한이 부여되면 메서드는 `True`를 반환하고 그렇지 않으면 `False`를 반환해야합니다.
request가 읽기 작업인지 쓰기 작업인지 테스트해야하는 경우 `'GET'`, `'OPTIONS'``'HEAD'`가 포함 된 튜플 인 `SAFE_METHODS` 상수와 비교하여 request 메소드를 확인해야합니다. 예:
```python
if request.method in permissions.SAFE_METHODS:
# 읽기 전용 액세스 권한을 확인하려면
else:
# 쓰기 액세스 권한을 확인하려면
```
---
**Note**: 뷰 수준 `has_permission` 검사가 이미 통과 된 경우에만 인스턴스 수준의 `has_object_permission` 메소드가 호출됩니다. 또한 인스턴스 수준 검사를 실행하려면 view 코드에서 `.check_object_permissions(request, obj)`를 명시적으로 호출해야 합니다. generic view를 사용하는 경우 기본적으로 이 옵션이 처리됩니다.
---
테스트가 실패 할 경우 custom 권한은 `PermissionDenied` 예외를 발생시킵니다. 예외와 관련된 오류 메시지를 변경하려면 custom 권한에 직접 `massege` 속성을 구현하십시오. 그렇지 않으면 `PermissionDenied``default_detail` 속성이 사용됩니다.
```python
from rest_framework import permissions
class CustomerAccessPermission(permissions.BasePermission):
message = 'Adding customers not allowed.'
def has_permission(self, request, view):
...
```
### Examples
다음은 들어오는 request의 IP 주소를 블랙리스트와 대조하여 IP가 블랙리스트에 올랐으면 request를 거부하는 권한 클래스의 예입니다.
```python
from rest_framework import permissions
class BlacklistPermission(permissions.BasePermission):
"""
Global permission check for blacklisted IPs.
"""
def has_permission(self, request, view):
ip_addr = request.META['REMOTE_ADDR']
blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
return not blacklisted
```
들어오는 모든 request에 ​​대해 실행되는 전역 권한뿐 아니라 특정 개체 인스턴스에 영향을 주는 작업에 대해서만 실행되는 개체 수준 사용 권한을 만들 수도 있습니다. 예 :
```python
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
# 읽기 권한은 모든 요청에 ​​허용되며,
# 그래서 GET, HEAD, OPTIONS 요청을 허용 할 것입니다.
if request.method in permissions.SAFE_METHODS:
return True
# 인스턴스에는`owner`라는 속성이 있어야합니다.
return obj.owner == request.user
```
generic view는 적절한 개체 수준 사용 권한을 검사하지만 custom view를 작성하는 경우 개체 수준 사용 권한 검사를 직접 확인해야합니다. 객체 인스턴스가 있으면 뷰에서 `self.check_object_permissions(request, obj)`를 호출하여 그렇게 할 수 있습니다. 개체 수준의 권한 체크가 실패했을 경우,이 호출은 적절한 `APIException`을 송출하고, 그렇지 않은 경우는 단순히 반환됩니다.
또한 generic view는 단일 모델 인스턴스를 검색하는 뷰의 오브젝트 레벨의 권한만을 체크합니다.
목록 뷰의 개체 수준 필터링이 필요한 경우는 별도로 쿼리 세트를 필터링해야합니다. 자세한 내용은 [filtering documentation](http://www.django-rest-framework.org/api-guide/filtering/) 참조
## Third party packages
다음 타사 패키지도 제공됩니다.
### Composed Permissions
[Composed Permissions](https://github.com/niwinz/djangorestframework-composed-permissions) 패키지는 작고 재사용 가능한 구성 요소를 사용하여 (논리 연산자를 사용하여) 복잡한 멀티 심도 권한 객체를 쉽게 정의하는 방법을 제공합니다.
### REST Condition
[REST Condition](https://github.com/caxap/rest_condition) 패키지는 복잡한 권한을 쉽고 편리하게 구축하기 위한 또 다른 확장 기능입니다. 확장 기능을 사용하면 권한을 논리 연산자와 결합 할 수 있습니다.
### DRY Rest Permissions
[DRY Rest Permissions](https://github.com/dbkaplan/dry-rest-permissions) 패키지는 개별 기본 및 custom 액션에 대해 서로 다른 권한을 정의하는 기능을 제공합니다. 이 패키지는 응용 프로그램의 데이터 모델에 정의 된 관계에서 파생 된 권한을 가진 애플리케이션 용으로 만들어져 있습니다. 또한 API serializer를 통해 클라이언트 응용 프로그램에 반환되는 권한 검사도 지원하고 있습니다. 또한 사용자마다 취득하는 데이터를 제한하기 위해 기본 및 custom 목록 액션에 권한을 추가도 지원합니다.
### Django Rest Framework Roles
[Django Rest Framework Roles](https://github.com/computer-lab/django-rest-framework-roles) 패키지를 사용하면 여러 유형의 사용자에 대해 API를 쉽게 매개 변수화 할 수 있습니다.
### Django Rest Framework API Key
[Django Rest Framework API Key](https://github.com/manosim/django-rest-framework-api-key) 패키지를 사용하면 서버에 대한 모든 요청에 API 키 헤더가 필요함을 확인할 수 있습니다. 당신은 django 관리 인터페이스에서 생성 할 수 있습니다.

View File

@ -0,0 +1,434 @@
# Django REST Framework - Renderers
---
_"Before a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client."_
_"TemplateResponse 인스턴스가 클라이언트에 반환되기 전에 렌더링 되어야 합니다. 렌더링 프로세스는 템플릿과 컨텍스트의 중간 표현을 가져 와서 클래이언트에 제공 할 수 있는 최종 바이트 스트림으로 바꿉니다."_
_— Django documentation_
---
## Renderers
REST 프레임워크에는 다양한 미디어 타입의 response를 반환할 수 있는 여러가지 `Renderer`클래스가 포함되어 있습니다. 또한 custom renderer를 정의할 수 있으므로 자신의 미디어 타입을 유연하게 디자인 할 수 있습니다.
### How the renderer is determined
뷰에 대한 유혀한 renderer set은 항상 클래스의 list로 정의됩니다. 뷰가 입력되면 REST 프레임워크는 들어오는 request에 대한 내용 협상을 수행하고, request를 만족시키는데 가장 적합한 renderer를 결정합니다.
콘텐츠 협상의 기본 프로세스는 request의 `Accept`헤더를 조사하여 response에서 예상하는 미디어 타입을 판별하는 것입니다. 선택적으로, URL의 form suffixes를 사용하여 명시적으로 특정 표현을 요청할 수 있습니다. 예를 들어 URL `http://example.com/api/users_count.json`은 항상 JSON 데이터를 반환하는 엔드포인트 일 수 있습니다.
더 자세한 내용은 [content negotiation](http://www.django-rest-framework.org/api-guide/content-negotiation/)을 참조하세요.
### Setting the renderers
기본 renderer set은 `DEFAULT_RENDERER_CLASSES` 설정을 사용하여 전역으로 설정할 수 있습니다. 예를 들어, 다음 설정은 `JSON`을 기본 미디어 타입으로 사용하며 자체 기술 API도 포함됩니다.
```python
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
)
}
```
`APIView` CBV를 사용하여 개별 view나 viewset에 사용되는 renderer를 설정할 수도 있습니다.
```python
from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
class UserCountView(APIView):
"""
A view that returns the count of active users in JSON.
"""
renderer_classes = (JSONRenderer, )
def get(self, request, format=None):
user_count = User.objects.filter(active=True).count()
content = {'user_count': user_count}
return Response(content)
```
또는 FBV의 뷰와 함께 `@aip_view`데코레이터를 사용하는 경우
```python
@api_view(['GET'])
@renderer_classes((JSONRenderer,))
def user_count_view(request, format=None):
"""
A view that returns the count of active users in JSON.
"""
user_count = User.objects.filter(active=True).count()
content = {'user_count': user_count}
return Response(content)
```
### Ordering of renderer classes
API의 Renderer 클래스를 지정하여 각 미디어 타입에 할당 할 우선 순위를 생각할 때 중요합니다. 클라이언트가 `Accept: */*` 헤더를 보내는 것과 `Accept` 헤더를 포함하지 않는 것과 같이 받아 들일 수 있는 표현은 클라이언트가 명시하지 않으면 REST 프레임워크는 list에서 response에 사용할 첫번째 renderer를 선택합니다.
예를 들어 API가 JSON response과 HTML browsable API를 제공하는 경우, `Accept` 헤더를 지정하지 않은 클라이언트에 `JSON` 응답을 보내려면 `JSONRenderer`를 기본 renderer로 설정하는 것이 좋습니다.
API에 요청에 따라 일반 웹 페이지와 API 응답을 모두 제공 할 수있는 view가 포함되어있는 경우, [깨진 승인 헤더](http://www.newmediacampaigns.com/blog/browser-rest-http-accept-headers)를 보내는 오래된 브라우저에서 제대로 작동하려면 `TemplateHTMLRenderer`를 기본 렌더러로 설정하는 것이 좋습니다.
---
## API Reference
### JSONRenderer
utf-8 인코딩을 사용하여 request 데이터를 `JSON`으로 렌더링합니다.
기본 스타일은 유니코드 문자를 포함하고 불필요한 공백 없이 콤팩트 스타일을 사용하여 response를 렌더링하는 것입니다.
```python
{"unicode black star":"★","value":999}
```
클라이언트는 `indent`미디어 타입 parameter를 추가로 포함할 수 있습니다. 이 경우 반환 된 JSON은 들여쓰기 됩니다. 예: `Accept: application/json; indent=4`
```python
{
"unicode black star": "★",
"value": 999
}
```
기본 JSON 인코딩 스타일은 `UNICODE_JSON``COMPACT_JSON` 설정 키를 사용하여 변경할 수 있습니다.
**.media_type**: `application/json`
**.format**: `'.json'`
**charset**: `None`
### TemplateHTMLRenderer
Django의 표준 템플릿 렌더링을 사용하여 데이터를 HTML으로 렌더링합니다. 다른 renderer와 달리 `Response`에 전달 된 데이터는 serializer 할 필요가 없습니다. 또한 다른 renderer와 달리 `Response`를 만들 때 `template_name`인수를 포함 할 수 있습니다.
TemplateHTMLRenderer는 `response,data`를 컨텍스트 dict로 사용하여 `RequestContext`를 만들고 컨텍스트를 렌더링하는데 사용할 템플릿 이름을 결정합니다.
템플릿 이름은 (우선 순위에 따라) 다음과 같이 결정됩니다:
1. 명시적으로 `template_name`인수는 response에 전달됩니다.
2. 이 클래스는 명시적인 `.template_name` 속성이 설정됩니다.
3. `view.get_template_names()`를 호출 한 결과를 반환합니다.
`TemplateHTMLRenderer`를 사용하는 view의 예:
```python
class UserDetail(generics.RetrieveAPIView):
"""
A view that returns a templated HTML representation of a given user.
"""
queryset = User.objects.all()
renderer_classes = (TemplateHTMLRenderer,)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return Response({'user': self.object}, template_name='user_detail.html')
```
`TemplateHTMLRenderer`으로 REST 프레임워크를 사용하여 일반 HTML 페이지를 리턴하거나 HTML 및 API 응답을 단일 엔드포인트에서 리턴하도록 사용할 수 있습니다.
`TemplateHTMLRenderer`를 사용하는 웹 사이트를 구축하는 경우 `TemplateHTMLRenderer``renderer_classes` 목록의 첫 번째 클래스로 나열하는 것이 좋습니다. 이렇게하면 잘못 형성된 `ACCEPT:` 헤더를 보내는 브라우저에 대해서도 우선 순위가 지정됩니다.
`TemplateHTMLRenderer`사용에 대한 추가 예제는 [HTML & Forms Topic Page](http://www.django-rest-framework.org/topics/html-and-forms/)를 참조하세요.
**.media_type**: `text/html`
**.format**: `'.html'`
**.charset**: `utf-8`
참조 : `StaticHTMLRenderer`
### StaticHTMLRenderer
단순히 미리 렌더링 된 HTML을 반환하는 단순한 renderer입니다. 다른 렌더러와 달리 response 객체에 전달 된 데이터는 반환 할 내용을 나타내는 문자열이어야 합니다.
`StaticHTMLRenderer`를 사용하는 view의 예:
```python
@api_view(('GET',))
@renderer_classes((StaticHTMLRenderer,))
def simple_html_view(request):
data = '<html><body><h1>Hello, world</h1></body></html>'
return Response(data)
```
`StaticHTMLRenderer`는 REST 프레임워크를 사용하여 일반 HTML페이지를 리턴하거나 HTML및 API 응답을 단일 엔드포인트에서 리턴하도록 사용할 수 있습니다.
**.media_type**: `text/html`
**.format**: `'.html'`
**.charset**: `utf-8`
참조 : `TemplateHTMLRenderer`
### BrowsableAPIRenderer
Browsable API를 위해 데이터를 HTML으로 렌더링합니다.
![](./images/BrowsableAPIRenderer.png)
이 renderer는 가장 우선순위가 높은 다른 renderer를 셜정하고 이를 사용하여 HTML 페이지 내에 API 스타일 response를 표시합니다.
**.media_type**: `text/html`
**.format**: `'.api'`
**.charset**: `utf-8`
**.template**: `'rest_framework/api.html'`
#### Customizing BrowsableAPIRenderer
기본적으로 response content는 `BrowsableAPIRenderer`와 별도로 우선 순위가 가장 높은 renderer로 렌더링 됩니다. 이 동작을 custom 해야하는 경우 (ex: HTML을 기본 리턴 형식으로 사용하고 browsable API에서 JSON을 사용하는 경우) `get_default_renderer()` 메서드를 대체하서 이를 수행 할 수 있습니다. 예:
```python
class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
def get_default_renderer(self, view):
return JSONRenderer()
```
### AdminRenderer
관리자와 같은 디스플레이를 위해 데이터를 HTML으로 렌더링합니다.
![](./images/AdminRenderer.png)
이 renderer는 데이터 관리를 위한 사용자에게 친숙한 인터페이스를 제공해야하는 CRUD 스타일 웹 API에 적합합니다.
>CRUD : Create(생성), Read(읽기), Update(갱신), Delete(삭제)
HTML 폼이 제대로 지원하지 못하기 때문에 중첩 된 뷰 또는 입력을 위해 serializer를 나열한 뷰는 `AdminREnderer`와 잘 작동하지 않습니다.
**Note**: `AdminRenderer`는 올바르게 구성된 `URL_FIELD_NAME`(기본적으로 url)속성이 데이터에 있는 경우에만 detail 페이지에 대한 링크를 포함할 수 있습니다. `HyperlinkedModelSerializer`의 경우지만, `ModelSerializer` 또는 일반 Serializer 클래스의 경우 필드를 명시적으로 포함해야합니다. 예를 들어 여기서는 `get_absolute_url` 모델을 사용합니다.
```python
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = Account
```
**.media_type**: `text/html`
**.format**: `'.admin'`
**.charset**: `utf-8`
**.template**: `'rest_framework/admin.html'`
### HTMLFormRenderer
serializer에서 반환된 데이터를 HTML from으로 렌더링합니다. 이 renderer의 출력에는 포함된 `<form>`태크, 숨겨진 `CSRF`입력이나 `submit`버튼이 포함되지 않습니다.
이 renderer는 직접 사용하기 위한 것이 아니며, serializer 인스턴스를 `renderer_form` 템플릿 태그에 전달하여 템플릿에서 대신 사용할 수 있습니다.
```python
{% load rest_framework %}
<form action="/submit-report/" method="post">
{% csrf_token %}
{% render_form serializer %}
<input type="submit" value="Save" />
</form>
```
더 자세한 내용은 [HTML & Forms](http://www.django-rest-framework.org/topics/html-and-forms/)를 참조하세요.
**.media_type**: `text/html`
**.format**: `'.form'`
**.charset**: `utf-8`
**.template**: `'rest_framework/horizontal/form.html'`
### MultiPartRenderer
이 renderer는 HTML 다중 파트 form 데이터를 렌더링하는데 사용됩니다. response renderer로는 적합하지 않지만 대신 REST 프레임워크의 [테스트 클라이언트 및 테스트 request 팩토리](http://www.django-rest-framework.org/api-guide/testing/)를 사용하여 테스트 request를 만드는데 사용됩니다.
**.media_type**: `multipart/form-data; boundary=BoUnDaRyStRiNg`
**.format**: `'.multipart'`
**.charset**: `utf-8`
---
## Custom renderers
custom renderer를 구현하려면 `BaseRenderer`를 재정의하고, `.media_type``.format`속성을 설정하고 `.render(self, data, media_type=None, renderer_context=None)` 메서드를 구현해야 합니다.
메서드는 HTTP response의 본문으로 사용될 바이트 테스트를 반환해야합니다.
`render()`메서드에 전달 된 인수는 다음과 같습니다.
```
date
```
`response()` 인스턴스화에 의해 설정된 요청 데이터입니다.
```
media_type=None
```
선택사항. 제공되는 경우 콘텐츠 협상 단계에서 결정한대로 허용되는 미디어 타입입니다.
클라이언트의 `Accept:` 헤더에 따라 renderer의 `media_type`속성보다 더 구체적 일 수 있으며, 미디어 타입 parameter가 포함될 수 있습니다. 예를 들어 `"application/json; neated=true"`와 같습니다.
```
renderer_context=None
```
선택사항. 제공된 경우, 이는 뷰에서 제공하는 상황별 정보의 dict입니다.
기본적으로 이 키에는 `view`, `request`, `response`, `args`, `kwargs` 와 같은 키가 포함됩니다.
### Example
다음은 `data` parameter가 포함된 response를 응답내용으로 반환하는 일반텍스트 렌더러의 예입니다.
```python
from django.utils.encoding import smart_unicode
from rest_framework import renderers
class PlainTextRenderer(renderers.BaseRenderer):
media_type = 'text/plain'
format = 'txt'
def render(self, data, media_type=None, renderer_context=None):
return data.encode(self.charset)
```
### Setting the character set
기본적으로 renderer 클래스는 `UTF-8`인코딩을 사용한다고 가정합니다. 다른 인코딩을 사용하려면 renderer에서 `charset` 속성을 설정하세요.
```python
class PlainTextRenderer(renderers.BaseRenderer):
media_type = 'text/plain'
format = 'txt'
charset = 'iso-8859-1'
def render(self, data, media_type=None, renderer_context=None):
return data.encode(self.charset)
```
renderer 클래스가 유니코드 문자열을 반환하면 인코딩을 결정하는데 사용되는 renderer의 `charset` 속성이 설정 된 `Response`클래스에 의해 응답 내용이 bytestring으로 강제 변환됩니다.
renderer가 기존 이진 내용을 나타내는 바이트 테스트를 반환하는 경우 response의 `charset`값을 `None`으로 설정해야 합니다.(response의 `Content-Type`헤더에 `charset`값이 설정되지 않도록 보장합니다.)
경우에 따라 `renderer_style`속성을 `binary`로 설정할 수도 있습니다. 그렇게 하면 browsable API가 이진 컨텐츠를 문자열로 표시하지 않게 됩니다.
```python
class JPEGRenderer(renderers.BaseRenderer):
media_type = 'image/jpeg'
format = 'jpg'
charset = None
render_style = 'binary'
def render(self, data, media_type=None, renderer_context=None):
return data
```
---
## Advanced renderer usage
REST 프레임워크의 renderer를 사용하여 매우 유연한 작업을 수행 할 수 있습니다. 몇가지 예...
- 요청한 미디어 타입에 따라 같은 엔드포인트에서 플랫 또는 중첩된 표현을 제공하세요.
- 일반 HTML 웹 페이지와 JSON 기반의 API응답을 동일한 엔드포인트에서 제공하세요.
- 사용할 API 클라이언트에 대해 여러 타입의 HTML 표현을 지정하세요.
- `media_type = 'image/*'`을 사용하는 것과 같이 renderer의 미디어 타입을 지정하고 `Accept`헤더를 사용하여 response의 인코딩을 변경합니다.
### Varying behaviour by media type
경우에 따라 view에서 허용되는 미디어 타입에 따라 다른 serializer 스타일을 사용하는 것이 좋습니다. 이 작업을 수행해야하는 경우 `request.accepted_renderer`에 액서스하여 response에 사용될 협상 된 renderer를 결정할 수 있습니다.
예:
```python
@api_view(('GET',))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def list_users(request):
"""
A view that can return JSON or HTML representations
of the users in the system.
"""
queryset = Users.objects.filter(active=True)
if request.accepted_renderer.format == 'html':
# TemplateHTMLRenderer takes a context dict,
# and additionally requires a 'template_name'.
# It does not require serialization.
data = {'users': queryset}
return Response(data, template_name='list_users.html')
# JSONRenderer requires serialized data as normal.
serializer = UserSerializer(instance=queryset)
data = serializer.data
return Response(data)
```
### Underspecifying the media type (미디어 타입을 지정하지 않음)
경우에 따라 renderer가 다양한 미디어타입을 제공해야 할 수도 있습니다. 이 경우 `image/*`이나 `*/*`과 같은 `media_type`값을 사용하여 미디어 타입을 명확하게 지정할 수 있습니다.
renderer의 미디어 타입을 명시하지 않은 경우 `content_type`속성을 사용하여 response을 반환 할 때 명시적으로 미디어타입을 지정해야합니다. 예:
```python
return Response(data, content_type='image/png')
```
### Designing your media types
많은 웹 API를 위해, 하이퍼링크 관계를 갖는 단순 `JSON` 응답은 충분할 수 있다. RESTful 디자인과 [`HATEOAS`](http://timelessrepo.com/haters-gonna-hateoas)를 완전히 포용하려면 미디어타입의 디자인과 사용법을 더 자세히 고려해야합니다.
[the words of Roy Fielding](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)에서는 _"REST API는 리소스를 표현하고 애플리케이션 상태를 유도하거나 기존 표준 미디어 타입에 대한 확장 관계 이름 및 `/` 또는 하이퍼 텍스트 사용 가능 마크 업을 정의하는 데 사용되는 미디어 유형을 정의하는데 필요한 모든 노력을 기울여야합니다."_
custom 미디어 타입의 좋은 예는 GitHub의 custom [application/vnd.github+json](https://developer.github.com/v3/media/) 미디어 타입 사용과 Mike Amundsen의 IANA 승인 [application/vnd.collection+json](http://www.amundsen.com/media-types/collection/)기반 하이퍼 미디어를 참조하십시오.
### HTML error views
일반적으로, renderer는 `Http404``PermissionDenied`예외 또는 `APIException`의 서브 클래스와 같이 일반 response를 처리하는지 또는 예외가 발생하여 response가 발생하는지에 관계없이 동일하게 동작합니다.
`TemplateHTMLRenderer` 또는 `StaticHTMLRenderer`를 사용중이고 예외가 발생하면 동작이 약간 다르며 [Django's default handling of error views](https://docs.djangoproject.com/en/1.10/topics/http/views/#customizing-error-views)가 그대로 반영됩니다.
HTML renderer에 의해 발생되고 처리되는 예외는 우선 순위에 따라 다음 방법 중 하나를 사용하여 렌더링을 시도합니다.
- `{status_code}.html`이라는 템플릿을 로드하고 렌더링합니다.
- `api_exception.html`이라는 템플릿을 로드하고 렌더링합니다.
- HTTP 상태 코드와 텍스트를 렌더링합니다.(ex. `"404 Not Found"`)
템플릿은 `status_code``detail` 키를 포함하는 `RequestContext`로 렌더링됩니다.
**Note**: `DEBUG=True`이면 Django의 표준 추적 오류 페이지가 HTTP 상태 코드와 텍스트를 렌더링하는 대신 표시됩니다.
---
## Third party packages
다음의 타사 패키지도 제공됩니다.
### YAML
[REST framework YAML](http://jpadilla.github.io/django-rest-framework-yaml/)은 [YAML](http://www.yaml.org/) 파싱 및 렌더링 지원을 제공합니다. 이전에 REST 프레임 워크 패키지에 직접 포함되어 있었으며 이제는 타사 패키지로 대신 지원됩니다.
#### 설치 및 구성
pip을 사용해 설치합니다.
```
$ pip install djangorestframework-yaml
```
REST 프레임워크 설정을 수정합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_yaml.parsers.YAMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_yaml.renderers.YAMLRenderer',
),
}
```
### XML
[REST Framework XML](http://jpadilla.github.io/django-rest-framework-xml/)은 간단한 비공식 XML 형식을 제공합니다. 이전에 REST 프레임 워크 패키지에 직접 포함되어 있었으며 이제는 타사 패키지로 대신 지원됩니다.
#### 설치와 구성
pip를 사용하여 설치합니다.
```
$ pip install djangorestframework-xml
```
REST 프레임워크 설정을 수정합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_xml.parsers.XMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_xml.renderers.XMLRenderer',
),
}
```
### JSONP
[REST framework JSONP](http://jpadilla.github.io/django-rest-framework-jsonp/)는 JSONP 렌더링을 지원합니다. 이전에 REST 프레임워크 패키지에 직접 포함되어 있었으며 이제는 타사 패키지로 대신 지원됩니다.
---
**Warning**: 도메인 간 AJAX 요청이 필요한 경우 일반적으로 `JSONP` 대신 CORS의 최신 접근 방식을 사용해야합니다. 자세한 내용은 [CORS 설명서](http://www.django-rest-framework.org/topics/ajax-csrf-cors/)를 참조하십시오.
`jsonp` 접근법은 본질적으로 브라우저 해킹이며 `GET` 요청이 인증되지 않고 사용자 권한이 필요하지 않은 [전 세계적으로 읽을 수 있는 API 엔드포인트](http://stackoverflow.com/questions/613962/is-jsonp-safe-to-use)에만 적합합니다.
---
#### 설치와 구성
pip를 사용하여 설치합니다.
```
$ pip install djangorestframework-jsonp
```
REST 프레임워크 설정을 수정합니다.
```python
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_jsonp.renderers.JSONPRenderer',
),
}
```
### MessagePack
[MessagePack]()은 빠르고 효율적인 바이너리 serializer 형식입니다. [Juan Riaza]()는 MessagePack 렌더러와 REST 프레임 워크에 대한 파서 지원을 제공하는 [djangorestframework-msgpack 패키지]()를 유지 관리합니다.
### CSV
쉼표로 구분 된 값은 스프레드 시트 응용 프로그램으로 쉽게 가져올 수 있는 일반 텍스트 형식의 데이터 형식입니다. [Mjumbe Poe](https://github.com/mjumbewu)는 REST 프레임 워크에 대한 CSV 렌더러 지원을 제공하는 [djangorestframework-csv](https://github.com/mjumbewu/django-rest-framework-csv) 패키지를 유지 관리합니다.
### UltraJSON
[UltraJSON](https://github.com/esnme/ultrajson)은 상당히 빠른 JSON 렌더링을 제공 할 수 있는 최적화 된 C JSON 인코더입니다. [Jacob Haslehurst](https://github.com/hzy)는 UJSON 패키지를 사용하여 JSON 렌더링을 구현하는 [drf-ujson-renderer](https://github.com/gizmag/drf-ujson-renderer) 패키지를 유지 관리합니다.
### CamelCase JSON
[djangorestframework-camel-case](https://github.com/vbabiy/djangorestframework-camel-case)는 REST 프레임워크를 위한 parser와 camel-case JSON 렌더러를 제공합니다. 이를 통해 serializer는 파이썬 스타일의 underscored 필드 이름을 사용할 수 있지만, 자바 스크립트 스타일의 camel case field names으로 API에 표시됩니다. 그것은 [Vitaly Babiy](https://github.com/vbabiy)에 의해 관리됩니다.
### Pandas (CSV, Excel, PNG)
[Django REST Pandas](https://github.com/wq/django-rest-pandas)는 Pandas DataFrame API를 통해 추가 데이터 처리 및 출력을 지원하는 serializer 및 렌더러를 제공합니다. Django REST Pandas에는 판다 스타일 CSV 파일, Excel 통합 문서 (`.xls` 및 `.xlsx`) 및 [기타 다양한 형식](https://github.com/wq/django-rest-pandas#supported-formats)의 렌더러가 포함되어 있습니다. [wq 프로젝트](https://github.com/wq)의 일환으로 [S. Andrew Sheppard](https://github.com/sheppard)에 의해 유지 관리됩니다.
### LaTeX
[Rest Framework Latex는 Laulatex](https://github.com/mypebble/rest-framework-latex)를 사용하여 PDF를 출력하는 렌더러를 제공합니다. 이것은 [Pebble (S/F Software)](https://github.com/mypebble)에서 관리합니다.

View File

@ -0,0 +1,94 @@
# Django REST Framework - Requests
---
_"If you're doing REST-based web service stuff ... you should ignore request.POST."
"REST 기반 웹 서비스 작업을 하고있다면 ... POST 요청을 무시해야한다."
— Malcom Tredinnick_
## Requests
REST 프레임워크의 `Request` 클래스는 표준 `HttpRequest`를 확장하여 REST 프레임워크의 유연한 request 구문 분석 및 요청 인증을 지원합니다.
## Request parsing
REST 프레임워크의 Request 객체는 유연한 request 구문 분석 기능을 제공하므로 사용자가 일반적으로 form 데이터를 처리하는 것과 같은 방식으로 JSON 데이터 또는 다른 미디어 유형으로 요청을 처리 할 수 ​​있습니다.
### .data
`request.data`는 요청 본문의 구문 분석 된 내용을 반환합니다. 이는 다음을 제외하고 표준 `request.POST``request.FILES` 속성과 유사합니다.
- 여기에는 파일과 파일이 아닌 입력을 포함하여 파싱 된 모든 내용이 포함됩니다.
- `POST`가 아닌 `HTTP`메소드의 컨텐츠 분석을 지원합니다. 즉, `PUT``PATCH` 요청의 컨텐츠에 액서스 할 수 있습니다.
- 이는 form 테이터를 지원하는 것보다 REST 프레임워크의 유연한 request 구문 분석을 지원합니다. 예를 들어, 들어오는 form 데이터를 처리하는 것과 같은 방식으로 들어오는 JSON 데이터를 처리 할 수 있습니다.
더 자세한 내용은 [parsers documentation](http://www.django-rest-framework.org/api-guide/parsers/)을 참조하세요.
### .query_params
`request.query_params``request.GET`에 대해 보다 정확하게 명명 된 동의어입니다.
코드 내에서 명확성을 위해 Django의 표준 `request.GET` 대신 `request.query_params`를 사용하는 것이 좋습니다. 이렇게 하면 코드베이스를 보다 정확하고 명확하게 유지할 수 있습니다. 모든 HTTP 메소드 유형에는 `GET`request 뿐만 아니라 쿼리 parameter가 포함될 수 있습니다.
### .parsers
`APIView` 클래스나 `@api_view` 데코레이터는 뷰에 설정 된 `parser_classes``DEFAULT_PARSER_CLASSES`설정에 따라 속성이 자동으로 `Parser` 인스턴스 목록으로 설정되도록 합니다.
일반적으로 이 속성에 액서스 할 필요는 없습니다.
---
**NOTE**: 클라이언트가 조작 된 콘텐츠를 보낸 경우 `request.data`에 액서스하면 `ParserError`가 발생할 수 있습니다. 기본적으로 REST 프레임워크의 `APIView` 클래스나 `@api_view`데코레이터는 오류를 포착하고, `400 Bad Request` 응답을 반환합니다.
클라이언트가 파싱 할 수 없는 content-type을 가진 request를 보내면 `UnsuppoertedMediaType`예외가 발생합니다. 이 예외는 기본적으로 포착되어 지원되지 않는 미디어 유형 응답을 반환합니다.
---
## Content negotiation
request는 콘텐츠 협상 단계의 결과를 결정할 수 있는 몇가지 속성을 제공합니다. 이를 통해 다양한 미디어 유형에 대해 다른 serializer 스키마를 선택하는 것과 같은 동작을 구현할 수 있습니다.
### .accepted_renderer
renderer 인스턴스는 컨텐츠 협상 단계에서 선택 된 인스턴스입니다.
### .accepted_media_type
내용 협상 단계에서 수락 한 미디어 유형을 나타내는 문자열입니다.
---
## Authentication (입증)
REST 프레임워크는 다음과 같은 기능을 제공하는 유연한 request 별 인증을 제공합니다.
- API의 다른 부분에 대해 서로 다른 인증 정책을 사용합니다.
- 다중 인증 정책의 사용을 지원합니다.
- 들어오는 request와 관련된 사용자와 토큰 정보를 제공합니다.
### .user
`request.user`는 일반적으로 `django.contrib.auth.models.User`의 인스턴스를 반환하지만 동작은 사용되는 인증 정책에 따라 다릅니다.
request이 인증되지 않은 경우 request.user의 기본값은 `django.contrib.auth.models.AnonymousUser`의 인스턴스입니다.
자세한 내용은 [authentication documentation](http://www.django-rest-framework.org/api-guide/authentication/)을 참조하세요.
### .auth
`request.auth`는 추가 인증 컨텍스트를 리턴합니다. `request.auth`의 정확한 작동은 사용되는 인증 정책에 따라 다르지만 대개 request가 인증 된 토큰의 인스턴스 일 수 있습니다.
request가 인증되지 않았거나 추가 컨텍스트가 없는 경우, `request.auth`의 기본값은 없습니다.
자세한 내용은 [authentication documentation](http://www.django-rest-framework.org/api-guide/authentication/)을 참조하세요.
### .authenticators
`APIView` 클래스나 `@api_view`데코레이터는 뷰에 설정된 `authentication_classes``DEFAULT_AUTHENTICATORS` 설정에 따라 속성이 자동으로 `Authentication`인스턴스 목록으로 설정되도록 합니다.
일반적으로 이 속성에 액서스 할 필요는 없습니다.
---
## Browser enhancements
REST 프레임워크는 브라우저 기반의 `PUT`, `PATCH`, `DELETE` form과 같은 몇 가지 브라우저 개선 사항을 지원합니다.
### .method
`request.method`는 request의 HTTP 메소드의 **uppercased**(대문자)로 된 문자열 표현을 리턴합니다.
브라우저 기반의 `PUT`, `PATCH``DELETE` form이 투명하게 지원됩니다.
자세한 내용은 [browser enhancements documentation](http://www.django-rest-framework.org/topics/browser-enhancements/)을 참조하세요.
### .content_type
`request.content_type`은 HTTP request 본문의 미디어 유형을 나타내는 문자열 객체를 반환하거나 미디어 유형이 제공되지 않은 경우 빈 문자열을 반환합니다.
일반적으로 REST 프레임워크의 기본 request 구문 분석 동작에 의존하므로 일반적으로 request의 콘텐츠 형식에 직접 액서스 할 필요가 없습니다.
request의 콘텐츠 형식에 액서스해야하는 경우 브라우저 기반 non-form 콘텐츠에 대한 투명한 지원을 제공하므로 `request.META.get('HTTP_CONTENT_TYPE')`을 사용하는 것보다 `.content_type`속성을 사용해야 합니다.
자세한 내용은 [browser enhancements documentation](http://www.django-rest-framework.org/topics/browser-enhancements/)을 참조하세요.
### .stream
`request.stream`은 request 본문의 내용을 나타내는 스트림을 반환합니다.
일반적으로 REST 프레임워크의 기본 request 구문 분석 동작에 의존하므로 대개 request의 콘텐츠에 직접 액세스 할 필요가 없습니다.
---
## Standard HttpRequest attributes
REST 프레임워크의 `request`는 Django의 `HttpRequest`를 확장하므로 다른 모든 표준 속성과 메소드도 사용할 수 있습니다. 예를 들어, `request.META``request.session` dict는 정상적으로 사용 가능합니다.
구현 이유로 인해 `Request`클래스는 `HttpRequest`클래스에 상속하지 않고 대신 `composition`을 사용하여 클래스를 확장합니다.

View File

@ -0,0 +1,74 @@
# Django REST Framework - Responses
---
_"Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process."_
_"기본 HttpResponse 객체와 달리 TemplateResponse 객체는 응답을 계산하기 위해 뷰에서 제공한 컨텍스트의 세부 정보를 유지합니다. response의 최종 출력은 나중에 응답 프로세스에서 필요할 때까지 계산되지 않습니다."_
_— Django documentation_
## Responses
REST 프레임워크는 클라이언트 요청에 따라 여러 콘텐츠 형식으로 렌더링 할 수 있는 콘텐츠를 반환할 수 있는 `Response` 클래스를 제공하여 HTTP 콘텐츠 협상을 지원합니다.
`response` 클래스는 Django의 `SimpleTemplateResponse`하위 클래스입니다. `response`객체는 Python 기본 요소로 구성되어야 하는 데이터로 초기화됩니다. 그런 다음 REST 프레임워크는 표준 HTTP 내용 협상을 사용하여 최종 응답 내용을 렌더링하는 방법을 결정합니다.
`Response` 클래스를 사용할 필요는 없으며, 필요한 경우 일반 `HttpResponse``StreamingHttpResponse` 객체를 뷰에서 반환 할 수도 있습니다. `Response`클래스를 사용하면 여러가지 형식으로 렌더링 할 수 있는 컨텐츠 협상 웹 API 응답을 반환하기에 더 좋은 인터페이스만 제공됩니다.
어떤 이유로든 REST 프레임워크를 많이 사용자 정의하지 않으려면 `Response`객체를 반환하는 뷰에 항상 `APIView`클래스나 `@api_view`함수를 사용해야 합니다. 이렇게하면 뷰에서 내용협상을 수행하고 응답에 적합한 렌더러를 선택하여 뷰에 반환 할 수 있습니다.
---
## Creating responses
### Response()
**Signature** : `Response(data, status=None, template_name=None, headers=None, content_type=None)`
일반 `HttpResponse`개체와 달리 렌더링 된 콘텐츠로 `Response` 개체를 인스턴스화하지 않습니다. 대신 기존의 파이썬으로 구성된 렌더링되지 않은 데이터를 전달합니다.
`Response`클래스에서 사용하는 렌더러는 Django모델 인스턴스와 같은 복잡한 데이터 유형을 기본적으로 처리 할 수 없으므로 `Response`객체를 만들기 전에 데이터를 기본 데이터 유형으로 serializer해야 합니다.
REST 프레임워크의 `Serializer`클래스를 사용하여 데이터를 serializer를 수행하거나 custom serializer를 사용할 수 있습니다.
Arguments:
- `data`: response의 serializer 된 데이터입니다.
- `status`: response의 상태 코드입니다. 기본값은 200입니다. [status codes](http://www.django-rest-framework.org/api-guide/status-codes/) 참조
- `template_name`: `HTMLRenderer`가 선택된 경우 사용할 템플릿 이름입니다.
- `headers`: 응답에 사용할 HTTP 헤더 dict입니다.
- `content_type`: 응답의 내용 유형입니다. 일반적으로 콘텐츠 협상에 따라 렌더러에서 자동으로 설정되지만 콘텐츠 유형을 명시적으로 지정해야하는 경우가 있습니다.
---
## Attributes
### .data
`Request` 객체의 렌더링되지 않은 내용입니다.
### .status_code
HTTP 응답의 숫자 상태 코드입니다.
### .content
`response`의 렌더링 된 내용입니다. `.content`에 액서스하려면 먼저 `.render()`메서드를 호출해야 합니다.
### .template_name
`template_name`이 제공된 경우. `HTTPRenderer`나 다른 custom 템플릿 렌더러가 응답에 대해 허용된 렌더러인 경우에만 필요합니다.
### .accepted_renderer
응답을 렌더링하는데 사용되는 렌더러 인스턴스입니다.
뷰에서 응답이 반환되기 직전에 `APIView``@api_view`에 의해 자동으로 설정됩니다.
### .accepted_media_type
콘텐츠 협상 단계에서 선택한 미디어 유형입니다.
뷰에서 응답이 반환되기 직전에 `APIView``@api_view`에 의해 자동으로 설정됩니다.
### .renderer_context
렌더러의 `.render()`메소드에 전달 될 추가 컨텍스트 정보의 dict입니다.
뷰에서 응답이 반환되기 직전에 `APIView``@api_view`에 의해 자동으로 설정됩니다.
## Standard HttpResponse attributes
`Response`클래스는 `SimpleTemplateResponse`를 확장하고 모든 일반적이니 특성과 메서드를 response에서도 사용할 수 있습니다. 예를 들어 표준방식으로 response에 헤더를 설정 할 수 있습니다.
```python
response = Response()
response['Cache-Control'] = 'no-cache'
```
### .render()
**Signature**: `.render()`
다른 `TemplateResponse`와 마찬가지로 이 메소드는 응답의 serializer 된 데이터를 최종 response 컨텐츠로 렌더링하기 위해 호출됩니다. `.render()`가 호출되면 `accept_renderer`인스턴스에서 `.render (data, accepted_media_type, renderer_context)` 메서드를 호출 한 결과로 response 내용이 설정됩니다.
일반적으로 Django의 표준 응답주기에 의해 처리되므로 `.render()`를 직접 호출 할 필요가 없습니다.

View File

@ -0,0 +1,54 @@
# Django REST Framework - Returning URLs
---
_"The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components."_
_"REST 아키텍처 스타일을 다른 네트워크 기반 스타일과 구별하는 핵심 기능은 구성 요소 간의 균일한 인터페리스에 중점을 둡니다."_
_— Roy Fielding, Architectural Styles and the Design of Network-based Software Architectures_
---
## Returning URLs
일반적으로 `/foobar`와 같은 상대URL를 반환하는 것이 아니라 `http://example.com/foobar`와 같이 웹 API에서 절대 URI를 반환하는 것이 좋습니다.
이렇게 하는 이점은 다음과 같습니다.
- 이것이 더 명시적입니다.
- 당신의 API 클라이언트에 대한 작업을 적게 남겨둡니다.
- 네이티브 URI 유형이 없는 JSON과 같은 표현에서 문자열의 의미에 대한 모호성이 없습니다.
- 하이퍼링크를 사용하여 마크업 HTML 표현과 같은 작업을 쉽게 수행할 수 있습니다.
REST 프레임워크는 웹 API에서 절대 URI를 리턴하는 것을 보다 간단하게 해주는 두가지 유틸리티 함수를 제공합니다.
사용자가 직접 사용하도록 요구할 필요는 없지만 사용자가 직접 입력하면 자체 설명 API가 출력을 자동으로 하이퍼링크로 연결할 수 있으므로 API를 훨씬 쉽게 찾을 수 있습니다.
### reverse
**Signature**: `reverse(viewname, *args, **kwargs)`
[`django.urls.reverse`](https://docs.djangoproject.com/en/1.10/topics/http/urls/#reverse)와 동일한 동작을 하지만 호스트와 포트를 결정하기 위한 요청을 사용하여 정규화 된 URL을 반환합니다.
함수에 대한 **키워드 인수로 request을 포함**해야합니다. 예:
```python
from rest_framework.reverse import reverse
from rest_framework.views import APIView
from django.utils.timezone import now
class APIRootView(APIView):
def get(self, request):
year = now().year
data = {
...
'year-summary-url': reverse('year-summary', args=[year], request=request)
}
return Response(data)
```
### reverse_lazy
**Signature**: `reverse_lazy(viewname, *args, **kwargs)`
`django.urls.reverse_lazy`와 동일한 동작을 하지만 호스트와 포트를 결정하기위한 요청을 사용하여 정규화 된 URL을 반환한다는 점만 다릅니다.
`reverse` 함수와 마찬가지로 함수에 대한 **키워드 인수로 request를 포함**해야합니다. 예:
```
api_root = reverse_lazy('api-root', request=request)
```

View File

@ -0,0 +1,292 @@
# Django REST Framework - Routers
---
_"Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code."_
_"리소스 라우팅을 사용하면 주어진 리소스가 많은 컨트롤러에 대한 모든 일반 경로를 빠르게 선언 할 수 있습니다. 인덱스에 대해 별도의 경로를 선언하는 대신... 유용한 루트는 코드 한 줄로 선언합니다."_
_— Ruby on Rails Documentation_
---
## Routers
`Rails`와 같은 일부 웹 프레임워크는 응용 프로그램의 URL을 들어오는 요청을 처리하는 논리에 매핑하는 방법을 자동으로 결정하는 기능을 제공합니다.
REST 프레임워크는 Django에 대한 자동 URL라우팅을 지원을 추가하고 뷰 로직을 URL set에 간단하고 빠르게 연관되게 연결하는 방법을 제공합니다.
### Usage
다음은 `SimpleRouter`를 사용하는 간단한 URL 구성의 예입니다.
```python
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
```
`register()`메서드는 두 가지 필수 인수가 있습니다.
- `prefix` : router의 set에 사용할 URL접두어 입니다.
- `viewset` : `viewset`클래스입니다.
선택적으로 추가 인수를 지정할 수도 있습니다.
- `Base_name` : 작성된 URL 이름에 사용합니다. 설정되지 않은 경우 기본이름은 viewset의 쿼리셋 속성을 기반으로 자동 생성됩니다. viewset에 쿼리셋 특성이 포함되어 있지 않으면 viewset을 등록할 때 `base_name`을 설정해야 합니다.
위의 예는 다음 URL패턴을 생성합니다.
- URL pattern: `^users/$` Name: `'user-list'`
- URL pattern: `^users/{pk}/$` Name: `'user-detail'`
- URL pattern: `^accounts/$` Name: `'account-list'`
- URL pattern: `^accounts/{pk}/$` Name: `'account-detail'`
---
**Note**: `base_name`인수는 뷰 이름 패턴의 초기 부분을 지정하는데 사용됩니다. 위의 예에서는 사용자나 계정 부분입니다.
일반적으로 `base_name`인수를 지정할 필요는 없지만, custom `get_queryset`메서드를 정의한 viewset이 있는 경우, viewset에는 `.queryset` 속성 set이 없을 수 있습니다. 해당 viewset을 등록하려고하면 다음과 같은 오류가 표시됩니다.
```
'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
```
즉, 모델 이름에서 자동으로 결정할 수 없으므로 viewset을 등록할 때 `base_name`인수를 명시적으로 설정해야 합니다.
---
#### Using include with routers
라우터 인스턴스의 `.urls`속성은 URL 패턴의 표준 list일 뿐입니다. 이러한 URL을 포함할 수 있는 방법에는 여러 스타일이 있습니다.
예를 들어 `router.urls`를 views 목록에 추가할 수 있습니다.
```python
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
]
urlpatterns += router.urls
```
또는 Django의 `include` 함수를 사용할 수 있습니다.
```python
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^', include(router.urls)),
]
```
라우터 URL 패턴도 네임스페이스가 될 수 있습니다.
```python
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^api/', include(router.urls, namespace='api')),
]
```
하이퍼링크가 있는 serializer와 함께 네임 스페이스를 사용하는 경우 serializer의 `view_name` parameter가 네임 스페이스를 올바르게 반영하는지 확인해야 합니다. 위의 예제에서 사용자 detail view에 하이퍼링크 된 serializer 필드에 대해 `view_name='api:user-detail'`과 같은 parameter를 포함해야합니다.
#### Extra link and actions
`@detail_route``@list_route`로 장식 된 viewset의 모든 메서드도 라우트됩니다. 예를 들어, `UserViewSet`클래스에서 다음과 같은 메서드가 제공됩니다.
```python
from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route
class UserViewSet(ModelViewSet):
...
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
```
다음 URL패턴이 추가로 생성됩니다.
- URL pattern: `^users/{pk}/set_password/$` Name: `'user-set-password'`
custom 작업에 대해 생성 된 기본 URL을 사용하지 않으려면 대신 `url_path` parameter를 사용하여 custom 할 수 있습니다.
예를 들어 custom 액션의 URL을 `^users/{pk}/change-password/$`으로 변경하려면 다음과 같이 작성하세요.
```python
from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route
class UserViewSet(ModelViewSet):
...
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')
def set_password(self, request, pk=None):
...
```
위의 예제는 이제 다음 URL패턴을 생성합니다.
- URL pattern: `^users/{pk}/change-password/$` Name: `'user-change-password'`
custom 액션에 대해 생성된 기본 이름을 사용하지 않으려는 경우 `url_name`parameter를 사용하여 custom 할 수 있습니다.
예를 들어, custo,액션의 이름을 `'user-change-password'`로 변경하려면 다음과 같이 작성할 수 있습니다.
```python
from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route
class UserViewSet(ModelViewSet):
...
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')
def set_password(self, request, pk=None):
...
```
위의 예제는 이제 다음 URL패턴을 생성합니다.
- URL pattern: `^users/{pk}/set_password/$` Name: `'user-change-password'`
또한 `url_path``url_name` parameter를 함께 사용하여 custom view에 대한 URL생성을 제어할 수 있습니다.
더 자세한 내용은 [marking extra actions for routing](http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing)참조하세요.
## API Guide
### SimpleRouter
이 라우터에는 `list`, `create`, `retrieve`, `update`, `partial_update`, `destroy` 표준 set 작업에 대한 경로가 포함됩니다. viewset은 `@detail_route``@list_route`데코레이터를 사용하여 라우트 될 추가 메서드를 표시 할 수고 있습니다.
![](./images/SimpleRouter.png)
기본적으로 `SimpleRouter`로 만든 URL 뒤에는 슬래시가 추가됩니다. 이 동작은 라우터를 인스턴스화 할때 `trailing_slash` 인수를 `False`로 설정하여 수정할 수 있습니다. 예:
```
router = SimpleRouter(trailing_slash=False)
```
뒤에 오는 슬래시는 Django에서는 일반적이지만 레일스와 같은 다른 프레임워크에서는 기본적으로 사용되지 않습니다. 어떤 자바스크립트 프레임워크가 특정 라우팅 스타일을 기대할지라도, 어떤 스타일을 선탣 하느냐는 대부분 환경 설정의 문제입니다.
라우터는 슬래시와 마침표를 제외한 문자가 포함 된 조회값을 매치시킵니다. 보다 제한적인(혹은 관대한) 검색 패턴의 경우, viewset에 `lookup_value_regex`속성을 설정하세요. 예를 들어, 조회를 유효한 `UUID`로 제한할 수 있습니다.
```python
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
```
### DefaultRouter
이 라우터는 위와 같이 `SimpleRouter`와 비슷하지만 모든 list views에 대한 하이퍼링크가 포함 된 response을 반환하는 기본 API root view를 추가로 포함합니다. 선택적 `.json` 스타일 형식 접미사에 대한 경로도 생성합니다.
![](./images/DefaultRouter.png)
`SimpleRouter`과 마찬가지로 라우터를 인스턴스화 할때 `trailing_slash` 인수를 `False`로 설정하면 URL 경로에 따라오는 슬래시를 제거할 수 있습니다.
```python
router = DefaultRouter(trailing_slash=False)
```
## Custom Routers
`custom router`를 구현하는 것은 자주해야 할 일은 아니지만 `API URL`이 어떻게 구성되는지에 대한 요구사항이 있는 경우 유용합니다. 이렇게 하면 재사용 할 수 있는 방식으로 URL구조를 캡슐화 할 수 있으므로 각 새로운 view에 대해 명시적으로 URL 패턴을 작성 할 필요가 없습니다.
`custom router`를 구현하는 가장 간단한 방법은 기본 라우터 클래스 중 하나를 서브 클래스로 만드는 것입니다. `.routes` 속성은 각 viewset에 맵핑 될 URL 패턴을 template하는데 사용됩니다. `.routes`속성은 경로지정 튜플의 list입니다.
`Route`라는 튜플에 대한 인수는 다음과 같습니다.
**url** : 라우트 될 URL을 나타내는 문자열. 다음 타입의 문자열을 포함할 수 있습니다.
- `{prefix}` : 이 경로 집합에 사용할 URL 접두사입니다.
- `{lookup}` : 단일 인스턴스와 매치시키는데 사용되는 조회 필드입니다.
- `{trailing_slash}` : `trailing_slash`인수에 따라 `'/'`나 빈 문자열입니다.
**mapping** : HTTP 메서드 이름을 뷰 메서드에 매핑.
**name** : `reverse` 호출에 사용되는 URL의 이름입니다. 다음 타입의 문자열을 포함 할 수 있씁니다.
- `{basename}` : 생성된 URL 이름에 사용할 기준입니다.
**initkwargs** : view를 인스턴스화 할 때 전달되어야하는 추가 인수의 dict. `suffix`인수는 뷰 이름과 탐색 경로 링크를 생성 할 떄 사용되는 viewset 유형을 식별하기 위해 예약되어 있습니다.
### Customizing dynamic routes
`@list_route``@detail_route`데코레이터가 라우팅되는 방법을 custom 할 수 있습니다. 이 데코레이터 중 하나나 모두를 라우트하려면 `.routes`목록에 `DynamicListRoute``/`이나 `DynamicDetailRoute`라는 이름의 튜플을 포함하세요.
`DynamicListRoute``DynamicDetailRoute`의 인수는 다음과 같습니다.
**url** : 라우트 될 URL을 나타내는 문자열. `Route`와 동일한 타입의 문자열을 포함할 수 있으며, `{methodname}``{methodnamehyphen}`형식 문자열을 추가로 허용합니다.
**name** : `reverse`호출에 사용되는 URL의 이름입니다. `{basename}`, `{methodname}``{methodnamehyphen}`과 같은 형식 문자열을 포함합니다.
**initkwargs** : 뷰를 인스턴스화 할 때 전달되어야 하는 추가 인수의 dict
### Example
다음 예는 'list'와 'retrieve`의 액션에만 라우팅하며, 후행 슬래시 규칙은 사용하지 않습니다.
```python
from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter
class CustomReadOnlyRouter(SimpleRouter):
"""
A router for read-only APIs, which doesn't use trailing slashes.
"""
routes = [
Route(
url=r'^{prefix}$',
mapping={'get': 'list'},
name='{basename}-list',
initkwargs={'suffix': 'List'}
),
Route(
url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
initkwargs={'suffix': 'Detail'}
),
DynamicDetailRoute(
url=r'^{prefix}/{lookup}/{methodnamehyphen}$',
name='{basename}-{methodnamehyphen}',
initkwargs={}
)
]
```
`CustomReadOnlyRouter`가 간단한 viewset을 위해 생성 할 라우트를 살펴 보겠습니다.
`views.py`:
```python
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'username'
@detail_route()
def group_names(self, request):
"""
Returns a list of all the group names that the given
user belongs to.
"""
user = self.get_object()
groups = user.groups.all()
return Response([group.name for group in groups])
```
`urls.py` :
```python
router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = router.urls
```
다음과 같은 매칭이 생성됩니다...
URL | HTTP Method| Action | URL Name
---|---|---|---
/users | GET | list | user-list
/users/{username} | GET | retrieve | user-detail
/users/{username}/group-names | GET | group_names | user-group-names
`.routes`속성을 설정하는 다른 예제는 `SimpleRouter`클래스의 소스 코드를 참조하세요.
### Advanced custom routers
완전히 custom된 동작을 제공하려면 `BaseRouter`를 대체하고 `get_urls(self)`메서드를 대체할 수 있습니다. 이 메서드는 등록 된 viewset을 검사하고, URL 패턴 list를 리턴해야합니다. 등록된 prefix, viewset, basename 튜플은 `self.registry`속성에 액서스하여 검사할 수 있습니다.
`get_default_base_name(self, viewset)`메서드를 오버라이드하거나, viewset을 라우터에 등록 할 때 항상 `base_name` 인수를 명시적으로 설정할 수 있습니다.
## Third Party Packages
다음의 타사 패키지도 제공됩니다.
### DRF Nested Routers
[`drf-nested-routers`패키지](https://github.com/alanjds/drf-nested-routers)는 중첩된 리소스로 작업하기 위한 라우터와 관계 필드를 제공합니다.
### ModelRouter (wq.db.rest)
[`wq.db 패키지`](https://wq.io/wq.db)는 `register_model()` API로 `DefaultRouter`를 확장하는 고급 [`ModelRouter`](https://wq.io/1.0/docs/router) 클래스(및 싱글 톤 인스턴스)를 제공합니다. Django의 `admin.site.register`와 마찬가지로 `rest.router.register_model`에 필요한 유일한 인수는 모델 클래스입니다. url prefix, serializer, viewset에 대한 합리적인 기본값은 모델과 전역구성에서 유추됩니다.
```python
from wq.db import rest
from myapp.models import MyModel
rest.router.register_model(MyModel)
```
### DRF-extensions
[`DRF-extensions` package](http://chibisov.github.io/drf-extensions/docs/)는 [중첩된 viewset](http://chibisov.github.io/drf-extensions/docs/#nested-routes), [custom가 가능한 엔드포인트 이름](http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name)을 가진 [콜렉션 레벨 컨트롤러](http://chibisov.github.io/drf-extensions/docs/#collection-level-controllers)를 작성하기 위한 [라우터](http://chibisov.github.io/drf-extensions/docs/#routers)를 제공합니다.

View File

@ -0,0 +1,428 @@
# Django REST Framework - Schemas
---
_"A machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support."_
_"기계 판독 가능한 [스키마]는 API를 통해 사용할 수있는 리소스, 해당 URL의 의미, 표현 방법 및 지원 작업을 설명합니다."_
_— Heroku, JSON Schema for the Heroku Platform API_
---
## Schemas
API schema는 참조 문서를 생성하거나 API와 상호 작용 할 수 있는 동적 클라이언트 라이브러리를 구동하는 등 다양한 사용 사례를 허용하는 유용한 도구입니다.
### Representing schemas internally (내부적으로 스키마 표현하기)
REST 프레임워크는 형식 독립적인 표현으로 스키마 정보를 모델링하기 위해 [Core API](http://www.coreapi.org/)를 사용합니다. 이 정보는 다양한 스키마 형식으로 렌더링되거나 API 문서를 생성하는데 사용됩니다.
Core API를 사용하는 경우 스키마는 API에 대한 정보의 최상위 컨테이너 객체인 문서로 표시됩니다. 사용 가능한 API 상호작용은 링크 객체를 사용하여 표시됩니다. 각 링크는 URL, HTTP 메서드를 포함하며 API 엔드포인트에서 승인 할 수 있는 매개변수를 설명하는 `Field` 인스턴스 목록을 포함할 수 있습니다. `Link``Field` 인스턴스에는 API 스키마를 사용자 문서로 렌더링 할 수 있는 설명이 포함될 수도 있습니다.
다음은 단일 검색 엔드포인트를 포함하는 API 설명의 예입니다.
```python
coreapi.Document(
title='Flight Search API',
url='https://api.example.org/',
content={
'search': coreapi.Link(
url='/search/',
action='get',
fields=[
coreapi.Field(
name='from',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='to',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='date',
required=True,
location='query',
description='Flight date in "YYYY-MM-DD" format.'
)
],
description='Return flight availability and prices.'
)
}
)
```
### Schema output formats
HTTP response으로 표시되려면 내부 표현이 response에 사용 된 실제 바이트로 렌더링되어야 합니다.
[Core JSON]()은 Core API와 함께 사용하기 위한 표준 형식으로 설계되었습니다. REST 프레임워크에는 이 미디어 유형을 처리하기 위한 렌더러 클래스가 포함되어 있으며, 이 렌더러클래스는 `CoreJSONRenderer`로 사용할 수 있습니다.
[Open API](https://openapis.org/)("Swagger"), [JSON HyperSchema](http://json-schema.org/latest/json-schema-hypermedia.html), [API Blueprint](https://apiblueprint.org/)와 같은 다른 스키마 형식도 custom renderer 클래스를 구현하여 지원할 수 있습니다.
### Schemas vs Hypermedia
Core API는 API 스키마에 대한 대안적인 상호작용 스타일을 제시하는 하이퍼 미디어 응답을 모델링하는데 사용될 수 있다는 점을 여기서 지적 할 필요가 있습니다.
API 스키마를 사용할 수 있는 전체 인터페이스가 단일 엔드포인트로 제공됩니다. 개별 API 엔드포인트에 대한 응답은 일반적으로 각 response에 추가 상호 작용없이 일반 데이터로 표시됩니다.
Hypermedia를 사용하면 클라이언트에 데이터와 사용 가능한 상호 작용이 모두 포함된 문서가 제공됩니다. 각 상호 작용을 통해 현재 상태와 사용 가능한 상호 작용을 자세히 설명하는 새 문서가 생성됩니다.
REST 프레임워크를 사용하여 Hypermedia API를 빌드하는데 대한 자세한 정보와 지원은 향후 버전에서 계획됩니다.
---
## Adding a schema
REST 프레임워크에 대한 스키마 지원을 추가하려면 `coreapi` 패키지를 설치해야합니다.
```
pip install coreapi
```
REST 프레임워크에는 스키마 자동 생성 기능이 포함되어 있거나 명시적을 스키마를 지정할 수 있습니다. 필요한 항목에 따라 API에 스키마를 추가하는 몇가지 방법이 있습니다.
### The get_schema_view shortcut
프로젝트에 스키마를 포함시키는 가장 간단한 방법은 `get_schema_view()`함수를 사용하는 것입니다.
```python
schema_view = get_schema_view(title="Server Monitoring API")
urlpatterns = [
url('^$', schema_view),
...
]
```
view가 추가되면 자동 생성 스키마 정의를 검색하기 위한 API 요청을 할 수 있습니다.
```python
$ http http://127.0.0.1:8000/ Accept:application/vnd.coreapi+json
HTTP/1.0 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/vnd.coreapi+json
{
"_meta": {
"title": "Server Monitoring API"
},
"_type": "document",
...
}
```
`get_schema_view()`에 대한 인수는 다음과 같습니다.
- `title` : 스키마 정의를 설명하는 제목을 제공하는데 사용할 수 있습니다.
- `url` : 스키마의 표준 URL을 전달하는데 사용될 수 있습니다.
```python
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/'
)
```
- `urlconf` : API 스키마를 생성하려는 URL conf의 가져오기 경로를 나타내는 문자열입니다. 기본값은 Django의 `ROOT_URLCONF` 설정 값입니다.
```python
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
urlconf='myproject.urls'
)
```
- `renderer_classes` : API root 엔드포인트의 렌더링에 사용할 수 있는 렌더러 클래스 셋을 전달하는데 사용할 수 있습니다.
```python
from rest_framework.renderers import CoreJSONRenderer
from my_custom_package import APIBlueprintRenderer
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]
)
```
### Using an explicit schema view
`get_schema_view()` shortcut이 제공하는 것보다 더 많은 컨트롤이 필요한 경우 `SchemaGenerator` 클래스를 직접 사용하여 Document 인스턴스를 자동으로 생성하고 뷰에서 이를 반환 할 수 있습니다.
이 옵셥을 사용하면 원하는 모든 동작으로 스키마 엔드포인트를 설정할 수 있습니다. 예를 들어, 스키마 엔드포인트에 다른 사용 권한, 제한 또는 인증 정책을 적용 할 수 있습니다.
다음은 `SchemaGenerator`를 뷰와 함께 사용하려 스키마를 반환하는 예제입니다.
get_schema_view () 바로 가기가 제공하는 것보다 더 많은 컨트롤이 필요한 경우 SchemaGenerator 클래스를 직접 사용하여 Document 인스턴스를 자동으로 생성하고 뷰에서이를 반환 할 수 있습니다.
**views.py**:
```python
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response, schemas
generator = schemas.SchemaGenerator(title='Bookings API')
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
schema = generator.get_schema(request)
return response.Response(schema)
```
**urls.py**:
```python
urlpatterns = [
url('/', schema_view),
...
]
```
사용 가능한 권한에 따라 다른 사용자에게 다른 스키마를 제공할 수도 있습니다. 이 접근법은 인증되지 않은 요청이 인증된 요청과 다른 스키마로 제공되거나 API의 다른 부분이 해당 역할에 따라 다른 사용자에게 표시되도록하는데 사용할 수 있습니다.
사용자 권한으로 필터링 된 엔드포인트가 있는 스키마를 표시하려면 `get_schema()`메서드에 `request` 인수를 전달해야 합니다. 예를 들면 다음과 같습니다.
```python
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return response.Response(generator.get_schema(request=request))
```
### Explicit schema definition
자동 생성 방식의 대안은 코드베이스에 `Document` 객체를 선언하여 API 스키마를 명시적으로 지정하는 것입니다. 그렇게 하는것은 조금 더 작업 할 수 있지만 스키마 표현을 완전히 제어 할 수 있습니다.
```python
import coreapi
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response
schema = coreapi.Document(
title='Bookings API',
content={
...
}
)
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
return response.Response(schema)
```
### Static schema file
마지막 옵션은 Core JSON 또는 Open API 와 같은 사용 가능한 형식 중 하나를 사용하여 API schema를 static 파일로 작성하는 것입니다.
다음 중 하나를 수행 할 수 있습니다.
- 스키마 정의를 static 파일로 작성하고 [static 파일을 직접 제공하세요](https://docs.djangoproject.com/en/1.10/howto/static-files/).
- Core API를 사용하여 로드 된 스키마 정의를 작성한 다음 클라이언트 요청에 따라 여러가지 사용 가능한 형식중 하나로 렌더링합니다.
---
## Schemas as documentation
API 스키마의 일반적인 사용법 중 하나는 문서 페이지를 작성하는데 사용합니다.
REST 프레임워크의 스키마 생성은 docstring을 사용하여 스키마 문서의 설명을 자동으로 채웁니다.
이 설명은 다음을 기반으로 합니다.
- 해당 메소드 docstring이 있는 경우는 그것을 돌려줍니다.
- docstring 클래스 내의 명명된 섹션으로, 한 줄 또는 여러 줄이 될 수 있습니다.
- The class docstring.
### Examples
명시적인 메서드 docstring이 있는 `APIView`입니다.
```python
class ListUsernames(APIView):
def get(self, request):
"""
Return a list of all user names in the system.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
```
설명하는 액션 docstring이 있는 `ViewSet`입니다.
```python
class ListUsernames(ViewSet):
def list(self, request):
"""
Return a list of all user names in the system.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
```
단일 행 스타일을 사용하여 docstring 클래스의 섹션이 있는 generic view입니다.
```python
class UserList(generics.ListCreateAPIView):
"""
get: List all the users.
post: Create a new user.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
```
다중 회선 스타일을 사용하여 docstring 클래스의 섹션이 있는 generic viewset입니다.
```python
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
retrieve:
Return a user instance.
list:
Return all users, ordered by most recently joined.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
```
---
## Alternate schema formats
대체 스키마 형식을 지원하려면 `Document` 인스턴스를 바이트 표현으로 변환하는 처리를 담당하는 custom의 rederer 클래스를 구현해야합니다.
사용할 형식을 인코딩을 지원하는 Core API 코덱패키지가 있는 경우 해당 코덱을 사용하여 rederer 클래스를 구현 할 수 있습니다.
### Example
예를 들어 `openapi_codec` 패키지는 Open API("Swagger") 형식의 인코딩 또는 디코딩을 지원합니다.
```python
from rest_framework import renderers
from openapi_codec import OpenAPICodec
class SwaggerRenderer(renderers.BaseRenderer):
media_type = 'application/openapi+json'
format = 'swagger'
def render(self, data, media_type=None, renderer_context=None):
codec = OpenAPICodec()
return codec.dump(data)
```
---
## API Reference
### SchemaGenerator
스키마를 생성하는데 사용 할 수 있는 API view를 검토하는 클래스입니다.
일반적으로 다음과 같이 단일 인수로 `SchemaGenerator`를 인스턴스화합니다.
```
generator = SchemaGenerator(title='Stock Prices API')
```
Arguments:
- `title` **required** : API의 이름.
- `url` : API 스키마의 루트 URL입니다. 스키마가 경로 접두어에 포함되지 않으면 이 옵션이 필요하지 않습니다.
- `patterns` : 스키마를 생성 할 때 검사 할 URL 목록입니다. 기본값은 프로젝트의 URL conf입니다.
- `urlconf` : 스키마를 생성 할 때 사용할 URL conf 모듈 이름입니다. 기본값은 `settings.ROOT_URLCONF`입니다.
#### get_schema(self, request)
API 스키마를 나타내는 `coreapi.Document` 인스턴스를 반환합니다.
```python
@api_view
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return Response(generator.get_schema())
```
`request` 인수는 선택 사항이며, 결과 스키마 생성에 사용자 별 권한을 적용하려는 경우에 사용할 수 있습니다.
#### get_links(self, request)
API 스키마에 포함되어야 하는 모든 링크가 포함된 중첩된 dict를 반환합니다.
다른 레이아웃으로 새 dict를 빌드할 수 있으므로 생성된 스키마의 결과 구조를 수정하려는 경우 이를 대체하는 것이 좋습니다.
#### get_link(self, path, method, view)
주어진 뷰에 해당하는 `coreapi.Link`인스턴스를 반환합니다.
특정 뷰에 대해 custom 동작을 제공해야하는 경우 이 설정을 오버라이드 할 수 있습니다.
#### get_description(self, path, method, view)
링크 설명으로 사용할 문자열을 반환합니다. 기본적으로 이는 위의 "Schemas as Documentation" 섹션에서 설명한대로 docstring을 기반으로합니다.
#### get_encoding(self, path, method, view)
지정된 뷰와 상호 작용할 때 모든 request 본문에 대한 인코딩을 나타내는 문자열을 반환합니다.
예: `application/json`. request 본문을 기대하지 않는 뷰에 빈 문자열을 반환할 수 있습니다.
#### get_path_fields(self, path, method, view):
`coreapi.Link()`인스턴스의 list를 반환합니다. URL의 각 경로 parameter에 하나씩.
#### get_serializer_fields(self, path, method, view)
`coreapi.Link()` 인스턴스의 list를 반환합니다. 뷰가 사용하는 serializer 클래스의 각 필드에 하나씩.
#### get_pagination_fields(self, path, method, view)
뷰가 사용하는 pagination 클래스의 `get_schema_fields()` 메소드가 반환 한 `coreapi.Link()` 인스턴스의 list를 반환합니다.
#### get_filter_fields(self, path, method, view)
뷰에 의해 사용 된 filter 클래스의 `get_schema_fields()` 메소드에 의해 돌려 주어지는 `coreapi.Link()` 인스턴스의 list를 돌려줍니다.
---
### Core API
이 문서는 API 스키마를 표현하는데 사용되는 `coreapi` 패키지 내의 구성 요소에 대한 간략한 개요를 제공합니다.
이러한 클래스는 `rest_framework` 패키지가 아니라 `coreapi`패키지에서 가져옵니다.
#### Document
API 스키마 컨테이너를 나타냅니다.
`title` : API의 이름
`url` : API의 표준 URL
`content` : 스키마에 포함 된 `Link` 개체를 포함하는 dict입니다.
스키마에 더 많은 구조를 제공하기 위해 content dict는 일반적으로 두번째 레벨로 중첩 될 수 있습니다.
예:
```python
content={
"bookings": {
"list": Link(...),
"create": Link(...),
...
},
"venues": {
"list": Link(...),
...
},
...
}
```
#### Link
개별 API 엔드포인트를 나타냅니다.
`url` : 엔드포인트의 URL. `/users/{username}/`와 같은 URI 템플릿 일 수 있습니다.
`action` : 엔드포인트와 연관된 HTTP 방법. 하나 개 이상의 HTTP 메서드를 지원하는 URL은, 각각 하나의 `Link`에 해당해야합니다.
`fields` : 입력에 사용 할 수 있는 parameter를 설명하는 `Field`인스턴스의 list입니다.
`description` : 엔드포인트의 의미와 용도에 대해 간단한 설명.
#### Field
지정된 API 엔드포인트에서 단일 입력 매개변수를 나타냅니다.
`name` : 입력을 설명하는 이름입니다.
`required` : 클라이언트가 값을 포함하는 경우 또는 parameter를 생략할 수 있는지 여부를 나타내는 boolean 입니다.
`location` : 정보가 request에 어떻게 인코딩되는지 결정합니다. 다음 문자열 중 하나이어야 합니다.
>
**"path"**
템플릿 화 된 URL에 포함됩니다. 예를 들어 `/products/slim-fit-jeans/`와 같은 URL path에서 API 입력을 처리하기 위해 `/products/{product_code}/`의 URL 값을 `"path"` 입력란과 함께 사용할 수 있습니다.
이 필드는 대개 [프로젝트 URL conf의 명명 된 인수](https://docs.djangoproject.com/en/1.10/topics/http/urls/#named-groups)와 일치합니다.
>
**"query"**
URL 쿼리 매개변수로 포함됩니다. 예: `?search=sale`. 일반적으로 `GET` 요청에 사용됩니다.
이러한 필드는 일반적으로 뷰의 pagination 및 필터링 컨트롤과 일치합니다.
>
**"form"**
request 본문에 JSON 객체 또는 HTML 양식의 단일 항목으로 포함됩니다. 예 : `{"color":"blue",...}`. 일반적으로 `POST`, `PUT``PATCH` 요청에 사용됩니다. 여러 `"form"`입력란은 단일 링크에 포함될 수 있습니다.
이러한 필드는 일반적으로 뷰의 serializer 필드와 일치합니다.
>
**"body"**
전체 request 본문에 포함됩니다. 일반적으로 `POST`, `PUT``PATCH` 요청에 사용됩니다. 링크에는 둘 이상의 `"body"` 필드가 존재 할 수 없습니다. `"form"`필드와 함께 사용 할 수 없습니다.
이러한 필드는 보통 `ListSerializer`를 사용하는 request 입력의 유효성을 검사하거나 파일 업로드 뷰를 사용하는 view와 일치합니다.
`encoding`
>
**"application/json"**
JSON 인코딩 된 request 컨텐츠. `JSONParser`를 사용하는 뷰에 해당합니다. 하나 이상의 `location="form"`필드 또는 단일 `location="body"`필드가 링크에 포함 된 경우에만 유효합니다.
>
**"multipart/form-data"**
멀티 파트로 인코딩 된 request content. `MultiPartParser`를 사용하는 뷰에 해당합니다 하나 이상의 `location="form"`필드가 링크에 포함 된 경우에만 유효합니다.
>
**"application/x-www-form-urlencoded"**
URL로 인코딩 된 requetst content. `FormParser`를 사용하는 뷰에 해당합니다. 하나 이상의 `location="form"`필드가 링크에 포함 된 경우에만 유효합니다.
>
**"application/octet-stream"**
이진 업로드 request content. `FileUploadParser`를 사용하는 뷰에 해당합니다. `location="body"`필드가 링크에 포함된 경우에만 유효합니다.
`description` : 입력 필드의 의미와 용도에 대한 간단한 설명

View File

@ -0,0 +1,601 @@
# Django REST framework - Serializer fields
---
_"Each field in a Form class is responsible not only for validating data, but also for "cleaning" it — normalizing it to a consistent format."_
_"Form 클래스의 각 필드는 데이터 유효성 검사뿐만 아니라 일관된 형식으로 정규화하려 "정리"하는 역할을 담당합니다."_
_— Django documentation_
---
## Serializer fields
serializer 필드는 기존 값과 내부 데이터 유형간의 변환을 처리합니다. 또한 입력 값의 유효성 검사와 부모 오브젝트에서 값 검색 및 설정을 처리합니다.
---
**Note**: serializer 필드는 `fields.py`에 선언되어 있지만, 규칙에 따라 `from rest)framework import serializer`에서 가져와서 `setializers.<FiledName>` 필드를 참조해야합니다.
---
### Core arguments
각 serializer 필드 생성자는 최소한 이러한 인수를 취합니다. 일부 Field 클래스는 필드 별 인수를 추가로 가져오지만 항상 다음 사항을 받아들여야합니다.
`read_only`
읽기 전용 필드는 API 출력에 포함되지만 create 또는 update 조작 중 입력에 포함되면 안됩니다. serializer 입력에 잘못 된 'read_only'필드는 무시됩니다.
표현식을 serializer 할 떄 필드가 사용되도록하려면 이 값을 `True`로 설정하고 serializer 복원 중 인스턴스를 만들거나 업데이트 할 떄는 필드를 사용하지 마세요.
Default: `False`
`write_only`
이 값을 `True`로 설정하면 인스턴스를 업데이트하거나 만들때 필드가 사용될 수 있지만 표현을 serializer 할 때는 필드가 포함되지 않습니다.
Default: `True`
`required`
deserializer 중에 필드가 제공되지 않으면 일반적으로 오류가 발생합니다. deserializer 중에 이 필드가 필요하지 않은 경우 `False`로 설정하세요.
이 값을 `False`로 설정하면 인스턴스를 serializer 할 때 객체 속성 또는 dict 키가 출력에 생략 될 수 있습니다. 키가 없으면 출력 표현에 포함되지 않습니다.
Default: `True`
`allow_null`
serializer 필드에 `None`이 전달되면 일반적으로 오류가 발생합니다. `None`을 유효한 값으로 간주해야하는 경우 이 키워드 인수를 `True`로 설정하세요.
Default: `False`
`default`
설정되면, 입력 값이 제공되지 않으면 필드에 사용될 기본값이 제공됩니다. 설정되지 않은 경우 기본 동작은 속성을 전혀 채우지 않는 것입니다.
부분 업데이트 조작중에는 `default`값이 적용되지 않습니다. 부분 업데이트의 경우 들어오는 데이터에서 제공되는 필드에만 유효성 검사 된 값이 반환됩니다.
함수 또는 다른 호출 가능 객체로 설정 될 수 있습니다. 이 경우 값은 사용될 때마다 평가됩니다. 호출 될 때 인수가 없습니다. 'callable'에 `set_context`메서드가 있는 경우, 필드 인스턴스를 인수로 사용하기 전에 매번 호출됩니다. 이는 [validators](http://www.django-rest-framework.org/api-guide/validators/#using-set_context)와 동일한 방식으로 작동합니다.
인스턴스를 serializer 할 때 오브젝트 속성 또는 dict 키가 인스턴스에 없는 경우 기본값이 사용됩니다.
기본값을 설정하면 필드가 필요하지 않음을 의미합니다. 기본 및 필수 키워드 인수를 모두 포함하면 올바르지 않으며 오류가 발생합니다.
`source`
필드를 채우는데 사용할 속성의 이름입니다. `URLField(source='get_absolute_url')`와 같은 자체 인수만 사용하거나 `EmailField(source='user.email')`와 같은 속성을 통과하는 점으로 구분 된 표기법을 사용할 수 있습니다.
`source='*'`는 특별한 의미를 가지며 전체 객체가 필드로 전달되어야 함을 나타내기 위해 사용됩니다. 중첩된 표현을 작성하거나 출력 표현을 결정하기 위해 전체 오브젝트에 액세스해야하는 필드에 유용합니다.
기본값은 필드의 이름입니다.
`validators`
입력 필드 입력에 적용되어야하고 유효성 검사 오류를 발생시키거나 단순히 반환해야하는 validator 함수의 list입니다. 'Validator'함수는 일반적으로 `serializers.ValidationError`를 발생시켜야하지만 Django에 내장된 `ValidationError`는 Djang 코드베이스 또는 타사 Django 패키지에 정의된 유효성 검사기와의 호환성을 위해 지원됩니다.
`error_messages`
오류 메시지에 대한 오류코드 dict
`label`
HTML 양식 필드 또는 기타 설명적인 요소의 필드 이름으로 사용할 수 있는 짧은 텍스트 문자열입니다.
`help_text`
HTML 양식 필드나 기타 설명적인 요소의 필드에 대한 설명으로 사용될 수 있는 텍스트 문자열입니다.
`initial`
HTML 양식 피드 값을 미리 채우는 데 사용해야하는 값입니다. 일반 Django `field`와 마찬가지로 호출 대상을 전달할 수 있습니다.
```python
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
day = serializers.DateField(initial=datetime.date.today)
```
`style`
렌더러가 필드를 렌더링하는 방법을 제어하는데 사용할 수 있는 key-value dict입니다.
다음은 `'input_type'``'base_template'`의 두 가지 예입니다.
```python
# Use <input type="password"> for the input.
password = serializers.CharField(
style={'input_type': 'password'}
)
# Use a radio input instead of a select input.
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'}
)
```
자세한 내용은 [HTML & Forms documentation](http://www.django-rest-framework.org/topics/html-and-forms/)를 참조하세요.
---
## Boolean fields
### BooleanField
boolean 표현입니다.
HTML으로 인코딩 된 양식 입력을 사용할 때 `default=True`옵션이 지정되어 있어도 값을 생략하면 항상 필드를 `False`로 설정하는 것으로 처리됩니다. 이것은 HTML 체크 상자 입력이 값을 생략하여 선택되지 않은 상태를 나타내므로, REST 프레임워크는 생략을 빈 체크 박스 입력으로 처리합니다.
`django.db.models.fields.BooleanField`에 해당합니다.
**Signature**: `BooleanField()`
### NullBooleanField
유효한 값으로 `None`도 허용하는 boolean 표현입니다.
`django.db.models.fields.NullBooleanField`에 해당합니다.
**Signature**: `NullBooleanField()`
---
## String fields
### CharField
텍스트 표현입니다. 선택적으로 텍스트가 `max_length`보다 짧고 `min_length`보다 길도록 유효성을 검사합니다.
`django.db.models.fields.CharField` 또는 `django.db.models.fields.TextField`에 해당합니다.
**Signature**: `CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)`
- `max_length` : 입력이 이 문자 수를 초과하지 않는지 확인합니다.
- `min_length` : 입력에 이 수보다 적은 문자가 들어 있는지 확인합니다.
- `allow_blank` : `True`로 설정하면 빈 문자열을 유효한 값으로 간주해야합니다. `False`로 설정하면 빈 문자열이 유효하지 않은 것으로 간주되어 유효성 검사 오류가 발생합니다. 기본값은 `False`입니다.
- `rim_whitespace` : `True`로 설정하면 앞뒤 공백이 잘립니다. 기본값은 `True`입니다.
`allow_null` 옵션은 문자열 필드에도 사용할 수 있지만, `allow_blank`를 사용하면 사용하지 않는 것이 좋습니다. `allow_blank=True``allow_null=True`를 모두 설정하는 것은 유효하지만 문자열 표현에 허용되는 두 가지 유형의 빈 값이 존재하므로 데이터 불일치와 미세한 응용 프로그램 버그가 발생할 수 있습니다.
### EmailField
텍스트 표현은 유효한 Email 주소로 텍스트의 유효성을 검사합니다.
`django.db.models.fields.EmailField`에 해당합니다.
**Signature**: `EmailField(max_length=None, min_length=None, allow_blank=False)`
### RegexField
지정된 값의 유효성을 검사하는 텍스트 표현은 특정 정규 표현식과 일치합니다.
`django.forms.fields.RegexField`에 해당합니다.
**Signature**: `RegexField(regex, max_length=None, min_length=None, allow_blank=False)`
필수 정규 표현식 인자는 문자열이거나 컴파일 된 파이썬 정규 표현식 객체일 수 있습니다.
검증을 위한 Django의 `django.core.validators.RegexValidator`을 사용합니다.
### SlugField
패턴 `[a-zA-Z0-9_-]+`에 대한 입력의 유효성을 검사하는 `RegexField`입니다.
`django.db.models.fields.SlugField`에 해당합니다.
**Signature**: `SlugField(max_length=50, min_length=None, allow_blank=False)`
### URLField
URL 일치 패턴에 대해 입력의 유효성을 검사하는 `RegexField`입니다. `http://<host>/<path>` 형식의 정규화 된 URL이 필요합니다.
`django.db.models.fields.URLField`에 해당합니다. 확인을 위해 장고의 `django.core.validators.URLValidator`을 사용합니다.
**Signature**: `URLField(max_length=200, min_length=None, allow_blank=False)`
### UUIDField
입력이 유효한 UUID 문자열임을 보장하는 필드입니다. `to_internal_value` 메서드는 `uuid.UUID` 인스턴스를 리턴합니다. 출력시 필드는 정규 하이픈 형시의 문자열을 반환합니다. 예:
```
"de305d54-75b4-431b-adb2-eb6b9e546013"
```
**Signature**: `UUIDField(format='hex_verbose')`
- `format` : uuid 값의 표현 형식을 결정합니다.
- `'hex_verbose'` : 하이픈을 포함한 비표준 16 진수 표현 : `"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`
- `'hex'` : 하이픈을 제외하고 UUID의 압축 된 16 진수 표현 : `"5ce0e9a55ffa654bcee01238041fb31a"`
- `'int'` : UUID의 128 비트 정수 표현 : `"123456789012312313134124512351145145114"`
- `'urn'` : RFC 4122 URID의 URN 표현 : `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`형식 parameter를 변경하면 표현 값에만 영향을 줍니다. 모든 형식은 `to_internal_value`에서 허용됩니다.
### FilePathField
파일 시스템의 특정 디렉토리에 있는 파일 이름으로 제한 되는 필드입니다.
`django.forms.fields.FilePathField`에 해당합니다.
**Signature**: `FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)`
- `path` : 이 FilePathField가 선택해야하는 디렉토리에 대한 절대 파일 시스템 경로.
- `match` : 파일 경로 필터링을 사용하여 파일 이름을 필터링하는 정규 표현식입니다.
- `recursive` : path의 모든 하위 디렉토리가 포함되어야하는지 여부를 지정합니다. 기본값은 `False`입니다.
- `allow_files` : 지정된 위치의 파일을 포함할지 여부를 지정합니다. 기본값은 `True`입니다. `allow_files` 또는 `allow_folders``True` 이어야합니다.
- `allow_folders` : 지정된 위치의 폴더를 포함할지 여부를 지정합니다. 기본값은 `False`입니다. `allow_folders` 또는 `allow_files``True` 여야합니다.
### IPAddressField
입력이 유효한 IPv4 또는 IPv6 문자열인지 확인하는 필드입니다.
`django.forms.fields.IPAddressField``django.forms.fields.GenericIPAddressField`에 해당합니다.
**Signature**: `IPAddressField(protocol='both', unpack_ipv4=False, **options)`
- `protocol`의 유효한 입력을 지정된 프로토콜로 제한합니다. 허용되는 값은 'both'(기본값), 'IPv4'또는 'IPv6'입니다. 매칭은 대소문자를 구분하지 않습니다.
- `unpack_ipv4``::ffff:192.0.2.1`과 같은 IPv4 매핑 주소의 압축을 풉니다. 이 옵션을 사용하면 주소가 `192.0.2.1`로 압축 해제됩니다. 기본값은 사용하지 않습니다. 프로토콜이 'both'로 설정된 경우에만 사용할 수 있습니다.
---
## Numeric fields
### IntegerField
정수 표현.
`django.db.models.fields.IntegerField`, `django.db.models.fields.SmallIntegerField`, `django.db.models.fields.PositiveIntegerField`, `django.db.models.fields.PositiveSmallIntegerField`에 해당합니다.
**Signature**: `IntegerField(max_value=None, min_value=None)`
- `max_value` : 제공된 숫자가이 값보다 크지 않은지 확인합니다.
- `min_value` : 제공된 숫자가이 값보다 작지 않음을 검증합니다.
### FloatField
부동 소수점 표현.
`django.db.models.fields.FloatField`에 해당합니다.
**Signature**: `FloatField(max_value=None, min_value=None)`
- `max_value` : 제공된 숫자가이 값보다 크지 않은지 확인합니다.
- `min_value` : 제공된 숫자가이 값보다 작지 않음을 검증합니다.
### DecimalField
10 진수 표현으로, Python에서 `Decimal` 인스턴스로 나타냅니다.
`django.db.models.fields.DecimalField`에 해당합니다.
**Signature**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)`
- `max_digits` : 숫자에 허용되는 최대 자릿수. `None`이거나 `decimal_places`보다 크거나 같은 정수 여야합니다.
- `decimal_places` : 숫자와 함께 저장할 소수 자릿수입니다.
- `coerce_to_string` : 표현식에 문자열 값을 반환해야하는 경우 `True`로 설정하고 `Decimal` 객체를 반환해야하는 경우 `False`로 설정합니다. 기본값은 `COERCE_DECIMAL_TO_STRING` 설정 키와 같은 값으로, 오버라이드 하지 않으면 `True`입니다. serializer가 `Decimal` 객체를 반환하면 최종 출력 형식은 렌더러에 의해 결정됩니다. `localize`를 설정하면 값이 `True`로 설정됩니다.
- `max_value` : 제공된 숫자가이 값보다 크지 않은지 확인합니다.
- `min_value` : 제공된 숫자가이 값보다 작지 않음을 검증합니다.
- `localize` : 현재 로케일을 기반으로 입력 및 출력의 지역화를 사용하려면 `True`로 설정하십시오. 또한 `coerce_to_string``True`로 설정합니다. 기본값은 `False`입니다. 설정 파일에서 `USE_L10N=True`로 설정하면 데이터 서식이 활성화됩니다.
#### Example usage
소수점 2 자리의 해상도로 999까지의 숫자의 유효성을 검사하려면 다음을 사용합니다.
```
serializers.DecimalField(max_digits=5, decimal_places=2)
```
소수 자릿수 10의 해상도로 10 억 미만의 숫자를 검증하려면 다음을 수행하십시오.
```
serializers.DecimalField(max_digits=19, decimal_places=10)
```
이 필드에는 선택적 인수 `coerce_to_string`도 사용됩니다. `True`로 설정하면 표현이 문자열로 출력됩니다. `False`로 설정하면 표현은 `Decimal`인스턴스로 남게되고 최종 표현은 렌더러에 의해 결정됩니다.
설정을 해제하면 기본값은 `COERCE_DECIMAL_TO_STRING`설정과 동일한 값으로 설정되며, 그렇지 않은 경우 `True`로 설정됩니다.
---
## Date and time fields
### DateTimeField
날짜 및 시간 표현.
`django.db.models.fields.DateTimeField`에 해당합니다.
**Signature**: `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)`
- `format` : 출력 포맷을 나타내는 문자열. 지정하지 않으면 기본값은 `DATETIME_FORMAT` 설정 키와 동일한 값으로 설정되며, 설정하지 않으면 `'iso-8601'`이 됩니다. 형식 문자열로 설정하면 `to_representation` 반환 값을 문자열 출력으로 강제 변환해야합니다. 형식 문자열은 아래에 설명되어 있습니다. 이 값을 `None`으로 설정하면 Python `datetime` 객체가 `to_representation`에 의해 반환되어야합니다. 이 경우 datetime 인코딩은 렌더러에 의해 결정됩니다.
- `input_formats` : 날짜를 파싱하는데 사용할 수 있는 입력 형식을 나타내는 문자열 list입니다. 지정하지 않으면 `DATETIME_INPUT_FORMATS` 설정이 사용되며 기본값은 `['iso-8601']`입니다.
#### `DateTimeField` format strings.
형식 문자열은 명시적으로 형식을 지정하는 [Python `strftime`](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) 형식이거나 [ISO 8601](https://www.w3.org/TR/NOTE-datetime) 스타일 datetimes가 사용되어야 함을 나타내는 특수 문자열 `'iso-8601'`일 수 있습니다. (예 : `'2013-01-29T12:34:56.000000Z'`)
형식의 값으로 `None` 값이 사용되면 `datetime` 객체는 `to_representation`에 의해 반환되고 최종 출력 표현은 렌더러 클래스에 의해 결정됩니다.
#### `auto_now` and `auto_now_add` model fields
`ModelSerializer` 또는 `HyperlinkedModelSerializer`를 사용할 때 `auto_now=True` 또는 `auto_now_add=True` 인 모델 필드는 기본적으로 `read_only=True` 인 serializer 필드를 사용합니다.
이 동작을 재정의하려면 serializer에서 `DateTimeField`를 명시적으로 선언해야합니다. 예 :
```python
class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
class Meta:
model = Comment
```
### DateField
날짜 표현입니다.
`django.db.models.fields.DateField`에 해당합니다.
**Signature**: `DateField(format=api_settings.DATE_FORMAT, input_formats=None)`
- `format` : 출력 포맷을 나타내는 문자열. 지정하지 않으면 기본값은 `DATE_FORMAT` 설정 키와 동일한 값으로 설정되며, 설정하지 않으면 `'iso-8601'`이 됩니다. 형식 문자열로 설정하면 `to_representation` 반환 값을 문자열 출력으로 강제 변환해야합니다. 형식 문자열은 아래에 설명되어 있습니다. 이 값을 `None`으로 설정하면 Python `date` 객체가 `to_representation`에 의해 반환되어야합니다. 이 경우 date 인코딩은 렌더러에 의해 결정됩니다.
- `input_formats` : date를 파싱하는 데 사용할 수 있는 입력 형식을 나타내는 문자열 목록입니다. 지정하지 않으면 `DATE_INPUT_FORMATS` 설정이 사용되며 기본값은 `['iso-8601']`입니다.
#### `DateField` format strings
형식 문자열은 명시적으로 형식을 지정하는 [Python strftime 형식](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior)이거나 [ISO 8601](https://www.w3.org/TR/NOTE-datetime) 스타일 날짜를 사용해야한다는 것을 나타내는 특수 문자열 `'iso-8601'`일 수 있습니다. (예 : `'2013-01-29'`)
### TimeField
시간 표현.
`django.db.models.fields.TimeField`에 해당합니다.
**Signature**: `TimeField(format=api_settings.TIME_FORMAT, input_formats=None)`
- `format` : 출력 포맷을 나타내는 문자열. 지정하지 않으면 기본값은 `TIME_FORMAT` 설정 키와 동일한 값으로 설정되며, 설정하지 않으면 `'iso-8601'`이 됩니다. 형식 문자열로 설정하면 `to_representation` 반환 값을 문자열 출력으로 강제 변환해야합니다. 형식 문자열은 아래에 설명되어 있습니다. 이 값을 `None`으로 설정하면 Python `time` 객체가 `to_representation`에 의해 반환되어야 함을 나타냅니다. 이 경우 time 인코딩은 렌더러에 의해 결정됩니다.
- `input_formats` : date를 파싱하는데 사용할 수있는 입력 형식을 나타내는 문자열 list입니다. 지정하지 않으면 `TIME_INPUT_FORMATS` 설정이 사용되며 기본값은 `['iso-8601']`입니다.
#### `TimeField` format strings
형식 문자열은 명시적으로 형식을 지정하는 [Python strftime 형식](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior)이거나 [ISO 8601](https://www.w3.org/TR/NOTE-datetime) 스타일 시간이 사용되어야 함을 나타내는 특수 문자열 `'iso-8601'`일 수 있습니다. (예 : `'12:34:56.000000'`)
### DurationField
지속 시간 표현.
`django.db.models.fields.DurationField`에 해당합니다.
이 필드의 `validated_data`에는 `datetime.timedelta` 인스턴스가 포함됩니다. 표현은 `'[DD] [HH:[MM:]]ss[.uuuuuu]'` 형식의 문자열입니다.
**Note**: 이 필드는 Django 버전 1.8 이상에서만 사용 가능합니다.
**Signature**: `DurationField()`
---
## Choice selection fields
### ChoiceField
제한된 choice set에서 값을 허용 할 수 있는 필드입니다.
`ModelSerializer`가 해당 모델 필드에 `choices=...` 인수가 포함되어 있으면 필드를 자동으로 생성하는데 사용됩니다.
**Signature**: `ChoiceField(choices)`
- `choices` : 유효한 값의 list 또는 `(key, display_name)` tuple의 list.
- `allow_blank` : `True`로 설정하면 빈 문자열을 유효한 값으로 간주해야합니다. `False`로 설정하면 빈 문자열이 유효하지 않은 것으로 간주되어 유효성 검사 오류가 발생합니다. 기본값은 `False`입니다.
- `html_cutoff` : 설정된 경우 HTML 선택 드롭 다운에 표시 될 최대 선택항목 수입니다. 매우 큰 선택 항목이 있는 자동 생성 된 ChoiceField가 템플릿 렌더링을 방해하지 않도록하기 위해 사용할 수 있습니다. 기본값은 `None`입니다.
- `html_cutoff_text` : 설정된 경우 HTML 선택 드롭 다운에서 최대 항목 수가 잘린 경우 텍스트 표시기가 표시됩니다. 기본값은 `"More than {count} items…"`입니다.
`allow_blank``allow_null`은 모두 `ChoiceField`의 유효한 옵션입니다. 하지만 둘 중 하나만 사용하는 것이 좋습니다. `allow_blank`는 텍스트 선택에 선호되고 `allow_null`은 숫자 또는 기타 텍스트가 아닌 선택에 우선해야합니다.
### MultipleChoiceField
제한 된 선택 항목 set에서 선택된 0, 하나 또는 여러 값 집합을 허용 할 수 있는 필드입니다. 하나의 필수 인수를 취합니다. `to_internal_value`는 선택된 값을 포함하는 세트를 리턴합니다.
**Signature**: `MultipleChoiceField(choices)`
- `choices` : 유효한 값의 list 또는 `(key, display_name)` tuple의 list입니다.
- `allow_blank` : `True`로 설정하면 빈 문자열을 유효한 값으로 간주해야합니다. `False`로 설정하면 빈 문자열이 유효하지 않은 것으로 간주되어 유효성 검사 오류가 발생합니다. 기본값은 `False`입니다.
- `html_cutoff` : 설정된 경우 HTML 선택 드롭 다운에 표시 될 최대 선택 항목 수입니다. 매우 큰 선택 항목이 있는 자동 생성 된 ChoiceField가 템플릿 렌더링을 방해하지 않도록하기 위해 사용할 수 있습니다. 기본값은 `None`입니다.
- `html_cutoff_text` : 설정된 경우 HTML 선택 드롭 다운에서 최대 항목 수가 잘린 경우 텍스트 표시기가 표시됩니다. 기본값은 `"More than {count} items…"`입니다.
`ChoiceField`와 마찬가지로 `allow_blank``allow_null` 옵션이 모두 유효하지만 하나만 사용하고 둘 다 사용하지 않는 것이 좋습니다. `allow_blank`는 텍스트 선택에 선호되고 `allow_null`은 숫자 또는 기타 텍스트가 아닌 선택에 우선해야합니다.
---
## File upload fields
### Parsers and file uploads.
`FileField``ImageField` 클래스는 `MultiPartParser` 또는 `FileUploadParser`에서만 사용하기에 적합합니다. 대부분의 파서, 예를 들어. JSON은 파일 업로드를 지원하지 않습니다. Django의 일반 [FILE_UPLOAD_HANDLERS](https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS)는 업로드 된 파일을 처리하는 데 사용됩니다.
### FileField
파일 표현.
Django의 표준 FileField 유효성 검사를 수행합니다.
`django.forms.fields.FileField`에 해당합니다.
**Signature**: `FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`
- `max_length` : 파일 이름의 최대 길이를 지정합니다.
- `allow_empty_file` : 빈 파일이 허용 된 경우 지정합니다.
- `use_url` : `True`로 설정하면 URL 문자열 값이 출력 표현에 사용됩니다. `False`로 설정하면 파일 이름 문자열 값이 출력 표현에 사용됩니다. `UPLOADED_FILES_USE_URL` 설정 키의 기본값으로 설정되며, 그렇지 않은 경우 `True`로 설정됩니다.
### ImageField
이미지 표현.
업로드 된 파일 내용을 알려진 이미지 형식과 일치하는지 확인합니다.
**Signature**: `ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`
- `max_length` : 파일 이름의 최대 길이를 지정합니다.
- `allow_empty_file` : 빈 파일이 허용 된 경우 지정합니다.
- `use_url` : `True`로 설정하면 URL 문자열 값이 출력 표현에 사용됩니다. `False`로 설정하면 파일 이름 문자열 값이 출력 표현에 사용됩니다. `UPLOADED_FILES_USE_URL` 설정 키의 기본값으로 설정되며, 그렇지 않은 경우 `True`로 설정됩니다.
---
## Composite fields
### ListField
오브젝트의 list를 검증하는 필드 클래스입니다.
**Signature**: `ListField(child, min_length=None, max_length=None)`
- `child` : 리스트 내의 object의 검증에 사용하는 필드 인스턴스입니다. 이 인수가 제공되지 않으면 목록에있는 객체의 유효성이 검사되지 않습니다.
- `min_length` : 목록에이 수보다 적은 요소가 포함되는지 확인합니다.
- `max_length` : 목록에이 개수의 요소만 포함되는지 확인합니다.
예를 들어, 정수 목록을 검증하려면 다음과 같은 것을 사용할 수 있습니다.
```python
scores = serializers.ListField(
child=serializers.IntegerField(min_value=0, max_value=100)
)
```
또한 `ListField` 클래스는 재사용 가능한 목록 필드 클래스를 작성할 수 있는 선언 스타일을 지원합니다.
```python
class StringListField(serializers.ListField):
child = serializers.CharField()
```
이제 우리는 custom `StringListField` 클래스를 `child` 인자를 제공 할 필요없이 애플리케이션 전반에 재사용 할 수 있습니다.
### DictField
개체 dict을 확인하는 필드 클래스입니다. `DictField`의 키는 항상 문자열 값으로 간주됩니다.
**Signature**: `DictField(child)`
- `child` : dict의 값을 확인하는데 사용해야하는 필드 인스턴스입니다. 이 인수가 제공되지 않으면 매핑의 값이 유효하지 않습니다.
예를 들어 문자열과 문자열의 매핑을 검증하는 필드를 만들려면 다음과 같이 작성합니다.
```python
document = DictField(child=CharField())
```
`ListField`와 마찬가지로 선언 스타일을 사용할 수도 있습니다. 예 :
```python
class DocumentField(DictField):
child = CharField()
```
### JSONField
들어오는 데이터 구조가 유효한 JSON 프리미티브로 구성되었는지 확인하는 필드 클래스입니다. 대체 바이너리 모드에서는 JSON으로 인코딩 된 바이너리 문자열을 나타내고 유효성을 검사합니다.
**Signature**: `JSONField(binary)`
- `binary` : `True`로 설정하면 필드가 프리미티브 데이터 구조가 아닌 JSON 인코딩 된 문자열을 출력하고 유효성을 검사합니다. 기본값은 `False`입니다.
---
## Miscellaneous fields
### ReadOnlyField
수정하지 않고 단순히 필드 값을 반환하는 필드 클래스입니다.
이 필드는 모델 필드가 아닌 속성과 관련된 필드 이름을 포함 할 때 `ModelSerializer`에서 기본적으로 사용됩니다.
**Signature**: `ReadOnlyField()`
예를 들어, `has_expired``Account` 모델의 속성 인 경우 다음 serializer가이를 자동으로 `ReadOnlyField`로 생성합니다.
```python
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'has_expired')
```
### HiddenField
사용자 입력에 따라 값을 사용하지 않고 대신 기본값 또는 호출 가능 값에서 값을 가져오는 필드 클래스입니다.
**Signature**: `HiddenField()`
예를 들어, serializer 유효성 검사 데이터의 일부로 항상 현재 시간을 제공하는 필드를 포함 시키려면 다음을 사용합니다.
```python
modified = serializers.HiddenField(default=timezone.now)
```
`HiddenField` 클래스는 사전 정의 된 일부 필드 값을 기반으로 실행해야하는 유효성 검사가 있지만 해당 필드를 모두 최종 사용자에게 공개하지 않으려는 경우에만 필요합니다.
HiddenField에 대한 추가 예제는 [validators](http://www.django-rest-framework.org/api-guide/validators/) 설명서를 참조하십시오.
### ModelField
임의의 모델 필드에 묶을 수 있는 generic 필드입니다. `ModelField`클래스는 serializer/deserializer 작업을 관련 모델 필드에 위임합니다. 이 필드는 새 custom serializer 필드를 만들지 않고도 custom 모델 필드에 대한 serializer 필드를 만드는데 사용할 수 있습니다.
이 필드는 `ModelSerializer`에서 custom 모델 필드 클래스에 일치하는데 사용됩니다.
**Signature**: `ModelField(model_field=<Django ModelField instance>)`
`ModelField`클래스는 일반적으로 내부 사용을 위한 클래스이지만 필요한 경우 API에서 사용할 수 있습니다. `ModelField`를 올바르게 인스턴스화하려면 인스턴스화 된 모델에 첨부 된 필드를 전달해야합니다. 예: `ModelField(model_field=MyModel()._meta.get_field('custom_field'))`
### SerializerMethodField
이 필드는 읽기 전용 필드입니다. 이 클래스는 첨부 된 serializer 클래스에서 메서드를 호출하여 값을 가져옵니다. 객체의 serializer 된 표현에 모든 종류의 데이터를 추가하는데 사용할 수 있습니다.
**Signature**: `SerializerMethodField(method_name=None)`
- `method_name` : 호출되는 serializer의 메서드 이름입니다. 포함되지 않은 경우 기본값은 `get_<field_name>`입니다.
`method_name` 인수로 참조되는 serializer 메서드는 serializer 될 객체인 단일 인수 (`self` 외)를 채택해야합니다. 객체의 serializer 된 표현에 포함되기를 원하는 모든 것을 반환해야합니다. 예:
```python
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
```
## Custom fields
custom 필드를 만들려면 `Field`를 서브 클래스화한 다음 `.to_representation()``.to_internal_value()`메서드 중 하나 또는 모두를 오버라이드해야합니다. 이 두 메서드는 초기 데이터 유형과 기본 serializer 가능 데이터 유형간에 변환하는데 사용됩니다. 기본 데이터 유형은 일반적으로 number, string, boolean, `date` / `time` / `datetime` 또는 `None` 중 하나입니다. 그것들은 또한 다른 프리미티브 객체만을 포함하는 객체와 같은 list 또는 dict일 수 있습니다. 사용중인 렌더러에 따라 다른 유형이 지원 될 수 있습니다.
`.to_representation()`메서드는 초기 데이터 유형을 기존의 serializer 가능 데이터 유형으로 변환하기 위해 호출됩니다.
`.to_internal_value()`메서드는 기본 데이터 유형을 내부 파이썬 표현으로 복원하기 위해 호출됩니다. 데이터가 유효하지 않은 경우 이 메서드는 `serializers.ValidationError`를 발생시켜야합니다.
버전 2.x에 있던 `WritableField` 클래스는 더 이상 존재하지 않습니다. 필드가 데이터 입력을 지원하면 `Field`의 하위 클래스를 만들고 `to_internal_value()`를 재정의해야합니다.
### Examples
RGB 색상 값을 나타내는 클래스를 serializer하는 예를 살펴 보겠습니다.
```python
class Color(object):
"""
A color represented in the RGB colorspace.
"""
def __init__(self, red, green, blue):
assert(red >= 0 and green >= 0 and blue >= 0)
assert(red < 256 and green < 256 and blue < 256)
self.red, self.green, self.blue = red, green, blue
class ColorField(serializers.Field):
"""
Color objects are serialized into 'rgb(#, #, #)' notation.
"""
def to_representation(self, obj):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue)
def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue)
```
기본적으로 필드 값은 객체의 속성에 매핑으로 처리됩니다. 필드 값에 액서스하고 설정하는 방법을 custom 해야하는 경우 `.get_attribute()``/` 또는 `.get_value()`를 오버라이드해야합니다.
예를 들어, serializer 되는 객체의 클래스 이름을 나타내는데 사용할 수 있는 필드를 만듭니다.
```python
class ClassNameField(serializers.Field):
def get_attribute(self, obj):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return obj
def to_representation(self, obj):
"""
Serialize the object's class name.
"""
return obj.__class__.__name__
```
#### Raising validation errors
위의 `ColorField` 클래스는 현재 데이터 유효성 검사를 수행하지 않습니다. 잘못된 데이터를 나타내려면 `serializers.ValidationError`를 발생시켜야합니다.
```python
def to_internal_value(self, data):
if not isinstance(data, six.text_type):
msg = 'Incorrect type. Expected a string, but got %s'
raise ValidationError(msg % type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
raise ValidationError('Value out of range. Must be between 0 and 255.')
return Color(red, green, blue)
```
`.fail()`메서드는 `error_messages` dict에서 메시지 문자열을 취하는 `ValidationError`를 발생시키는 shortcut 입니다. 예:
```python
default_error_messages = {
'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
'out_of_range': 'Value out of range. Must be between 0 and 255.'
}
def to_internal_value(self, data):
if not isinstance(data, six.text_type):
self.fail('incorrect_type', input_type=type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
self.fail('incorrect_format')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
self.fail('out_of_range')
return Color(red, green, blue)
```
이 스타일은 오류 메시지를 코드에서보다 명확하게 분리하고 선호해야합니다.
## Third party packages
다음의 타사 패키지도 제공됩니다.
### DRF Compound Fields
[drf-compound-fields](https://drf-compound-fields.readthedocs.io/en/latest/) 패키지는 `many=True`옵션을 사용하는 serializer가 아닌 다른 필드로 설명 할 수 있는 간단한 값 목록과 같은 "compound(복합)" serializer 필드를 제공합니다. 또한 특정 유형 또는 해당 유형의 항목 목록 일 수 있는 입력 된 dict 및 값에 대한 필드가 제공됩니다.
### DRF Extra Fields
[drf-extra-fields](https://github.com/Hipo/drf-extra-fields)패키지는 `Base64ImageField``PointField` 클래스를 포함하여 REST 프레임워크에 대한 추가 serializer 필드를 제공합니다.
### djangrestframework-recursive
[djangorestframework-recursive](https://github.com/heywbj/django-rest-framework-recursive) 패키지는 재귀적 구조의 serializer와 deserializer를 위한 `RecursiceField`를 제공합니다.
### django-rest-framework-gis
[django-rest-framework-gis](https://github.com/djangonauts/django-rest-framework-gis) 패키지는 `GeometryField` 필드와 GeoJSON serializer 같은 django rest 프레임워크를 위한 지리적 추가 기능을 제공합니다.
### django-rest-framework-hstore
[django-rest-framework-hstore](https://github.com/djangonauts/django-rest-framework-hstore) 패키지는 [django-hstore](https://github.com/djangonauts/django-hstore) `DictionaryField` 모델 필드를 지원하는 `HStoreField`를 제공합니다.

View File

@ -0,0 +1,571 @@
# Django REST framework - Serializer relations
---
_"Bad programmers worry about the code. Good programmers worry about data structures and their relationships."_
_"나쁜 프로그래머는 코드에 대해 걱정합니다. 좋은 프로그래머는 데이터 구조와 그 관계에 대해 걱정합니다."_
_— Linus Torvalds_
---
## Serializer relations
relational field는 모델 관계를 나타내는데 사용됩니다. `ForeignKey`, `ManyToManyField``OneToOneField` 관계는 물론 관계 및 custom 관계 (예 : `GenericForeignKey`)를 역으로 적용 할 수 있습니다.
---
**Note**: 관계형 필드는 `relations.py`에 선언되어 있지만, 관습에 따라 `serializer` 모듈에서 가져와야하며, `rest_framework import serializer`에서 사용하고 `serializer.<FiledName>` 로 필드를 참조해야합니다.
---
### Inspecting relationships.
`ModelSerializer` 클래스를 사용하면 serializer 필드와 관계가 자동으로 생성됩니다. 이러한 자동 생성 필드를 검사하는 것은 관계 스타일을 custom하는 방법을 결정하는데 유용한 도구가 될 수 있습니다.
이렇게 하려면, Django의 쉘을 열고, `python manage.py shell`을 사용하고, serializer 클래스를 가져와서 인스턴스화하고, 객체 표현을 출력하세요.
```python
>>> from myapp.serializers import AccountSerializer
>>> serializer = AccountSerializer()
>>> print repr(serializer) # Or `print(repr(serializer))` in Python 3.x.
AccountSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(allow_blank=True, max_length=100, required=False)
owner = PrimaryKeyRelatedField(queryset=User.objects.all())
```
## API Reference
다양한 유형의 관계 필드를 설명하기 위해 예제에 몇가지 간단한 모델을 사용합니다. 우리 모델은 음악 앨범과 각 앨범에 수록된 트랙을 대상으로 합니다.
```python
class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
order = models.IntegerField()
title = models.CharField(max_length=100)
duration = models.IntegerField()
class Meta:
unique_together = ('album', 'order')
ordering = ['order']
def __unicode__(self):
return '%d: %s' % (self.order, self.title)
```
### StringRelatedField
`StringRelatedField``__unicode__`메서드를 사용하여 관계의 대상을 나타내는데 사용할 수 있습니다.
예를 들어 다음 serializer와 같습니다.
```python
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
다음과 같은 표현으로 serializer합니다.
```python
{
'album_name': 'Things We Lost In The Fire',
'artist': 'Low',
'tracks': [
'1: Sunflower',
'2: Whitetail',
'3: Dinosaur Act',
...
]
}
```
이 필드는 읽기 전용입니다.
**Arguments**:
- `many` : to-many 관계에 적용되면 이 인수는 `True`로 설정해야합니다.
### PrimaryKeyRelatedField
`primaryKeyRelatedField`는 primary key를 사용하여 관계의 대상을 나타내는데 사용할 수 있습니다.
예를 들어 다음 serializer가 있습니다.
```python
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
다음과 같이 표현할 수 있습니다.
```python
{
'album_name': 'Undun',
'artist': 'The Roots',
'tracks': [
89,
90,
91,
...
]
}
```
기본적으로 이 필드는 읽기전용이지만, `read_only`플래그를 사용하여 이 동작을 변경할 수 있습니다.
**Arguments**:
- `queryset` : 필드 입력의 유효성을 검사 할 때 모델 인스턴스 조회에 사용되는 쿼리 세트입니다. 관계는 명시적으로 쿼리 세트를 설정하거나 `read_only=True`로 설정해야합니다.
- `many` : to-many 관계에 적용되면이 인수를 `True`로 설정해야합니다.
- `allow_null` : `True`로 설정하면 필드에 `None` 값 또는 null 허용 관계에 대한 빈 문자열을 허용합니다. 기본값은 `False`입니다.
- `pk_field` : primary key 값의 serialzier/deserializer를 제어하는 ​​필드로 설정합니다. 예를 들어 ₩pk_field=UUIDField(format='hex')₩는 UUID primary key를 컴팩트 16 진수 표현으로 serializer화합니다.
### HyperlinkedRelatedField
`HyperlinkedRelatedField`는 하이퍼링크를 사용하여 관계의 대상을 나타내는데 사용할 수 있습니다.
예를 들어 다음 serializer가 있습니다.
```python
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.HyperlinkedRelatedField(
many=True,
read_only=True,
view_name='track-detail'
)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
다음과 같이 표현할 수 있습니다.
```python
{
'album_name': 'Graceland',
'artist': 'Paul Simon',
'tracks': [
'http://www.example.com/api/tracks/45/',
'http://www.example.com/api/tracks/46/',
'http://www.example.com/api/tracks/47/',
...
]
}
```
기본적으로 이 필드는 읽기전용이지만, `read_only`플래그를 사용하여 이 동작을 변경할 수 있습니다.
---
**Note**: 이 필드는 `lookup_field``lookup_url_kwarg` 인수를 사용하여 설정된대로 단일 URL 키워드 인수를 허용하는 URL에 매핑되는 개체를 위해 설계되었습니다.
URL의 일부로 단일 primary key 또는 slug 인수가 포함된 URL에 적합힙니다.
보다 복잡한 하이퍼 링크로 표현이 필요한 경우에는 아래의 [custom hyperlinked field](http://www.django-rest-framework.org/api-guide/relations/#custom-hyperlinked-fields)섹션에 설명 된대로 custom해야 합니다.
---
**Arguments**:
- `view_name` : 관계의 대상으로 사용해야하는 view 이름입니다. [표준 라우터 클래스]()를 사용하는 경우 `<modelname>-detail` 형식의 문자열이 됩니다. **필수.**
- `queryset` : 필드 입력의 유효성을 검사 할 때 모델 인스턴스 조회에 사용되는 쿼리셋입니다. 관계는 명시적으로 쿼리셋을 설정하거나 `read_only=True`로 설정해야합니다.
- `many` - to-many 관계에 적용되면 이 인수를 `True`로 설정해야합니다.
- `allow_null` : `True`로 설정하면 필드에 `None` 값 또는 null 허용 관계에 대한 빈 문자열을 허용합니다. 기본값은 `False`입니다.
- `lookup_field` : 조회에 사용해야하는 대상의 필드입니다. 참조 된 뷰의 URL 키워드 인수에 해당해야합니다. 기본값은 `pk`입니다.
- `lookup_url_kwarg` : 조회 필드에 해당하는 URL conf에 정의된 키워드 인수의 이름입니다. 기본적으로 `lookup_field`와 같은 값을 사용합니다.
- `format` : format suffix를 사용하는 경우, 하이퍼 링크 된 필드는 `format`인수를 사용하여 오버라이드하지 않는 한 대상에 대해 동일한 format suffix를 사용합니다.
### SlugRelatedField
`slugRelatedField`는 대상 필드를 사용하여 관계 대상을 나타내는데 사용할 수 있습니다.
예를 들어 다음 serializer가 있습니다.
```python
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
다음과 같이 표현할 수 있습니다.
```python
{
'album_name': 'Dear John',
'artist': 'Loney Dear',
'tracks': [
'Airport Surroundings',
'Everything Turns to You',
'I Was Only Going Out',
...
]
}
```
기본적으로 이 필드는 읽기 전용이지만, `read_only`플래그를 사용하여 이 동작을 변경할 수 있습니다.
`SlugRelatedField`를 read-write 필드로 사용할 때는 일반적으로 slug 필드가 `unique=True`인 모델 필드에 해당하는지 확인해야합니다.
**Arguments**:
- `slug_field` : 그것을 나타내는데 사용해야하는 대상의 필드입니다. 주어진 인스턴스를 고유하게 식별하는 필드이어야 합니다. 예: `username`. **필수**
- `queryset` : 필드 입력의 유효성을 검사 할 때 모델 인스턴스 조회에 사용되는 쿼리셋입니다. 관계는 명시적으로 쿼리셋을 설정하거나 `read_only=True`로 설정해야 합니다.
- `many` : to-many 관계에 적용되면 이 인수를 `True`로 설정해야합니다.
- `allow_null` : `True`로 설정하면 필드에 `None` 값 또는 null 허용 관계에 대한 빈 문자열을 허용합니다. 기본값은 `False`입니다.
### HyperlinkedIdentityField
이 필드는 `HyperlinkedModelSerializer``url`필드와 같은 동일한 관계로 적용될 수 있습니다. 객체의 속성에도 사용할 수 있습니다. 예를 들어, 다음 serializer가 있습니다.
```python
class AlbumSerializer(serializers.HyperlinkedModelSerializer):
track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')
class Meta:
model = Album
fields = ('album_name', 'artist', 'track_listing')
```
다음과 같이 표현할 수 있습니다.
```python
{
'album_name': 'The Eraser',
'artist': 'Thom Yorke',
'track_listing': 'http://www.example.com/api/track_list/12/',
}
```
이 필드는 항상 읽기 전용입니다.
**Arguments**:
- `view_name` : 관계의 대상으로 사용해야하는 view 이름입니다. 표준 라우터 클래스를 사용하는 경우 `<model_name>-detail` 형식의 문자열이 됩니다. **필수**
- `lookup_field` : 조회에 사용해야하는 대상의 필드입니다. 참조 된 뷰의 URL 키워드 인수에 해당해야합니다. 기본값은 `'pk'`입니다.
- `lookup_url_kwarg` : 조회 필드에 해당하는 URL conf에 정의 된 키워드 인수의 이름입니다. 기본적으로 `lookup_field`와 같은 값을 사용합니다.
- `format` - format suffix를 사용하는 경우 하이퍼 링크 된 필드는 `format` 인수를 사용하여 오버라이드하지 않는한 대상에 대해 동일한 format suffix를 사용합니다.
---
## Nested relationships
중첩 된 관계는 serializer를 필드로 사용하여 표현할 수 있습니다.
필드가 to-many 관계를 나타내는데 사용되는 경우 serializer필드에 `many=True`플래그를 추가해야합니다.
### Example
예를 들어 다음 serializer가 있습니다.
```python
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title', 'duration')
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
다음과 같이 중첩된 표현으로 serializer 합니다.
```python
>>> album = Album.objects.create(album_name="The Grey Album", artist='Danger Mouse')
>>> Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=245)
<Track: Track object>
>>> Track.objects.create(album=album, order=2, title='What More Can I Say', duration=264)
<Track: Track object>
>>> Track.objects.create(album=album, order=3, title='Encore', duration=159)
<Track: Track object>
>>> serializer = AlbumSerializer(instance=album)
>>> serializer.data
{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
{'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
{'order': 2, 'title': 'What More Can I Say', 'duration': 264},
{'order': 3, 'title': 'Encore', 'duration': 159},
...
],
}
```
### Writable nested serializers
기본적으로 nested serializer는 읽기 전용입니다. 중첩 된 serializer 필드에 대한 쓰기 작업을 지원하려면 `creat()``/`또는 `update()`메서드를 만들어 자식 관계를 저장하는 방법을 명시적으로 지정해야합니다.
```python
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title', 'duration')
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
def create(self, validated_data):
tracks_data = validated_data.pop('tracks')
album = Album.objects.create(**validated_data)
for track_data in tracks_data:
Track.objects.create(album=album, **track_data)
return album
>>> data = {
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
{'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
{'order': 2, 'title': 'What More Can I Say', 'duration': 264},
{'order': 3, 'title': 'Encore', 'duration': 159},
],
}
>>> serializer = AlbumSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.save()
<Album: Album object>
```
---
## Custom relational fields
기존의 관계형 스타일이 필요하지 않은 경우가 드물지만 모델 인스턴스에서 출력 표현을 생성하는 방법을 정확하게 설명하는 완벽한 custom relational field를 구현할 수 있습니다.
custom relational field를 구현하려면 RelatedField를 오버라이드하고 `.to_representation(self, value)` 메서드를 구현해야합니다. 이 메서드는 필드의 대상을 `value`인수로 사용하고 대상을 serializer하는데 사용해야하는 표현을 반환해야합니다. `value`인수는 일반적으로 모델 인스턴스입니다.
read-write relational field를 구현하려면 `.to_internal_value(self, data)` 메소드도 구현해야합니다.
contextd를 기반으로 동적 쿼리셋을 제공하려면 클래스에서 `.queryset`을 지정하거나 필드를 초기화 할 때 `.get_queryset(self)`를 오버라이드 할 수도 있습니다.
### Example
예를 들어, 순서, 제목, 기간을 사용하여 트랙을 custom 문자열 표현으로 serializer하는 relational field를 정의할 수 있습니다.
```python
import time
class TrackListingField(serializers.RelatedField):
def to_representation(self, value):
duration = time.strftime('%M:%S', time.gmtime(value.duration))
return 'Track %d: %s (%s)' % (value.order, value.name, duration)
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackListingField(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
```
이 custom 필드는 다음 표현으로 serializer 됩니다.
```python
{
'album_name': 'Sometimes I Wish We Were an Eagle',
'artist': 'Bill Callahan',
'tracks': [
'Track 1: Jim Cain (04:39)',
'Track 2: Eid Ma Clack Shaw (04:19)',
'Track 3: The Wind and the Dove (04:34)',
...
]
}
```
---
## Custom hyperlinked fields
어떤 경우에는 하나 이상의 조회 필드가 필요한 URL을 나타내기 위해 하이퍼링크 필드의 동작을 custom 해야 할 수도 있습니다.
`HyperlinkedRelatedField`를 오버라이드 하여 이 작업을 수행 할 수 있습니다. 오버라이드 할 수 있는 두 가지 방법이 있습니다.
#### get_url(self, obj, view_name, request, format)
`get_url` 메서드는 객체 인스턴스를 URL 표현에 매핑하는 데 사용됩니다.
`view_name``lookup_field` 속성이 URL conf와 정확하게 일치하도록 구성되지 않은 경우 `NoReverseMatch`를 발생시킬 수 있습니다.
#### get_object(self, queryset, view_name, view_args, view_kwargs)
쓰기 가능한 하이퍼링크 필드를 지원하려면 들어오는 URL을 그들이 나타내는 객체로 다시 매핑하기 위해 `get_object`를 오버라이드해야합니다. 읽기 전용 하이퍼링크 필드의 경우 이 메서드를 오버라이드 할 필요가 없습니다.
이 메서드의 반환 값은 일치하는 URL conf 인수에 해당하는 객체이어야 합니다.
`ObjectDoesNotExist` 예외가 발생할 수 있습니다.
### Example
다음과 같이 두 개의 키워드 인수를 취하는 고객 객체의 URL이 있다고 가정해보세요.
```
/api/<organization_slug>/customers/<customer_pk>/
```
단일의 lookup field 만을 받아들이는 기본 구현에서는 이것을 표현할 수 없습니다.
이 경우 우리가 원하는 동작을 얻으려면 `HyperlinkedRelatedField`를 오버라이드해야합니다.
```python
from rest_framework import serializers
from rest_framework.reverse import reverse
class CustomerHyperlink(serializers.HyperlinkedRelatedField):
# We define these as class attributes, so we don't need to pass them as arguments.
view_name = 'customer-detail'
queryset = Customer.objects.all()
def get_url(self, obj, view_name, request, format):
url_kwargs = {
'organization_slug': obj.organization.slug,
'customer_pk': obj.pk
}
return reverse(view_name, kwargs=url_kwargs, request=request, format=format)
def get_object(self, view_name, view_args, view_kwargs):
lookup_kwargs = {
'organization__slug': view_kwargs['organization_slug'],
'pk': view_kwargs['customer_pk']
}
return self.get_queryset().get(**lookup_kwargs)
```
이 스타일을 generic view 와 함께 사용하려는 경우 올바른 조회 동작을 얻으려면 뷰에서 `.get_object`를 오버라이드 해야합니다.
일반적으로 가능한 경우 API 표현에 플랫 스타일을 사용하는 것이 좋지만, 중첩된 URL 스타일은 적당히 사용하면 합리적일 수 있습니다.
---
## Further notes
### The `queryset` argument
`queryset`인수는 쓰기 가능한 관계 필드에만 필요합니다. 이 경우 기본 인스턴스 사용자 입력 모델 인스턴스로 매핑되는 모델 인스턴스 조회를 수행하는데 사용됩니다.
버전 2.x에서는 serializer 클래스가 `ModelSerializer` 클래스가 사용되는 경우 `queryset` 인수를 자동으로 결정할 수 있습니다.
이 동작은 이제 쓰기 가능한 관계형 필드에 대해 명시적 쿼리셋 인수를 항상 사용하여 대체되었습니다.
이렇게하면 `ModelSerializer`이 제공하는 숨겨진 'magic'양이 줄어들고 필드의 동작이 더 명확해지며 `ModelSerializer` shortcut를 사용하거나 완전하게 명시적인 `Serializer`클래스를 사용하는 것이 쉽다는 것을 보증합니다.
### Customizing the HTML display
모델의 내장 `__str__`메서드는 `choices`속성을 채우는데 사용 된 객체의 문자열 표현을 생성하는데 사용됩니다. 이러한 선택사항은 탐색 가능한 API에서 선택된 HTML 입력을 채우는데 사용됩니다.
이러한 입력에 대해 custom 된 표현을 제공하려면 `RelatedField` 서브 클래스의 `display_value()`를 대체하세요. 이 메서드는 모델 객체를 수신하고 모델 객체를 나타내는데 적합한 문자열을 반환해야합니다. 예:
```python
class TrackPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def display_value(self, instance):
return 'Track: %s' % (instance.title)
```
### Select field cutoffs
browsable API에서 렌더링 될 때 관계형 필드는 기본적으로 최대 1000개의 선택 가능한 항목만 표시합니다. 더 많은 항목이 있으면 "More than 1000 items..."와 함께 비활성화 된 옵션이 표시됩니다.
이 동작은 매우 많은 수의 관계가 표시되어 허용되는 범위 내에서 템플릿을 렌더링 할 수 없도록 하기 위한 것입니다.
이 동작을 제어하는데 사용할 수 있는 두 개의 키워드인수가 있습니다.
- `html_cutoff` : 설정된 경우 HTML 선택 드롭 다운에 표시 될 최대 선택 항목 수입니다. 제한을 해제하려면 `None`으로 설정하십시오. 기본값은 `1000`입니다.
- `html_cutoff_text` - 설정된 경우 HTML 선택 드롭 다운에서 최대 항목 수가 잘린 경우 텍스트 표시를 보여줍니다. 기본값은 `"More than {count} items…"`입니다.
`HTML_SELECT_CUTOFF``HTML_SELECT_CUTOFF_TEXT` 설정을 사용하여 전역으로 제어 할 수도 있습니다.
컷오프가 적용되는 경우 HTML 양식에 일반 입력 필드를 대신 사용할 수 있습니다. `style` 키워드 인수를 사용하면됩니다. 예 :
```python
assigned_to = serializers.SlugRelatedField(
queryset=User.objects.all(),
slug_field='username',
style={'base_template': 'input.html'}
)
```
### Reverse relations
reverse 관계는 `ModelSerializer``HyperlinkedModelSerializer`클래스에 자동으로 포함되지 않습니다. reverse 관계를 포함 시키려면 필드 목록에 명시적으로 추가해야합니다. 예:
```python
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ('tracks', ...)
```
일반적으로 필드 이름으로 사용할 수 있는 적절한 `related_name`인수를 관계에 설정했는지 확인해야합니다. 예:
```python
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
...
```
reverse 관계에 대한 관련 이름을 설정하지 않은 경우 `fields`인수에 자동으로 생성 된 관련 이름을 사용해야합니다. 예:
```python
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ('track_set', ...)
```
자세한 내용은 [reverse relationships](https://docs.djangoproject.com/en/1.10/topics/db/queries/#following-relationships-backward)에 대한 Django 문서를 참조하세요.
### Generic relationships
일반적인 foreign key를 serializer하려면 관계의 대상을 serializer화하는 방법을 명시적으로 결정하기 위해 custom 필드를 정의해야합니다.
예를 들어, 다른 임의의 모델과 일반적인 관계가 있는 태그에 대해 다음 모델이 제공됩니다.
```python
class TaggedItem(models.Model):
"""
Tags arbitrary model instances using a generic relation.
See: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/
"""
tag_name = models.SlugField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
tagged_object = GenericForeignKey('content_type', 'object_id')
def __unicode__(self):
return self.tag_name
```
그리고 다음 두 모델의 관련 태그를 가질 수 있습니다.
```python
class Bookmark(models.Model):
"""
A bookmark consists of a URL, and 0 or more descriptive tags.
"""
url = models.URLField()
tags = GenericRelation(TaggedItem)
class Note(models.Model):
"""
A note consists of some text, and 0 or more descriptive tags.
"""
text = models.CharField(max_length=1000)
tags = GenericRelation(TaggedItem)
```
태그가 지정된 인스턴스를 serializer하는데 사용할 수 있는 custom 필드를 정의하여 각 인스턴스의 유형을 사용하여 serializer 해야하는 방식을 결정할 수 있습니다.
```python
class TaggedObjectRelatedField(serializers.RelatedField):
"""
A custom field to use for the `tagged_object` generic relationship.
"""
def to_representation(self, value):
"""
Serialize tagged objects to a simple textual representation.
"""
if isinstance(value, Bookmark):
return 'Bookmark: ' + value.url
elif isinstance(value, Note):
return 'Note: ' + value.text
raise Exception('Unexpected type of tagged object')
```
관계의 타겟이 중첩 된 표현을 필요로 하는 경우 `.to_representation()`메서드 내에서 필요한 serializer를 사용할 수 있습니다.
```python
def to_representation(self, value):
"""
Serialize bookmark instances using a bookmark serializer,
and note instances using a note serializer.
"""
if isinstance(value, Bookmark):
serializer = BookmarkSerializer(value)
elif isinstance(value, Note):
serializer = NoteSerializer(value)
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
```
`GenericRelation`필드를 사용하여 표현된 reverse generic key는 관계의 대상 유형이 항상 알려져 있으므로 일반 관계형 필드 유형을 사용하여 serializer화 할 수 있습니다.
더 자세한 정보는 [the Django documentation on generic relations](https://docs.djangoproject.com/en/1.10/ref/contrib/contenttypes/#id1)를 참조하세요.
### ManyToManyFields with a Through Model
기본적으로 지정된 `through` 모델을 사용하여 `ManyToManyField`를 대상으로하는 관계형 필드는 읽기전용으로 설정됩니다.
through 모델을 사용하여 `manyToManyField`를 가리키는 관계 필드를 명시적으로 지정하면 `read_only``True`로 설정하세요.
---
## Third Party Packages
다음의 타사 패키지도 제공됩니다.
### DRF Nested Routers
[drf-nested-routers](https://github.com/alanjds/drf-nested-routers) 패키지는 중첩 된 리소스로 작업하기 위한 라우터 및 관계 필드를 제공합니다.
### Rest Framework Generic Relations
[rest-framework-generic-relations](https://github.com/Ian-Foote/rest-framework-generic-relations) 라이브러리는 일반적인 foreign key에 대한 read/write serializer화를 제공합니다.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,416 @@
# Django REST Framework - Settings
---
_"Namespaces are one honking great idea - let's do more of those!"_
_"네임 스페이스는 훌륭한 아이디어를 제공합니다. let's do more of those!"_
_— The Zen of Python_
---
## Settings
REST 프레임워크의 모든 설정은 `REST_FRAMEWORK`라는 단일 Django 설정에 네임 스페이스를 설정합니다.
예를 들어 프로젝트의 `settings.py`파일에는 다음과 같은 내용이 포함될 수 있습니다.
```python
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
)
}
```
### Accessing settings
프로젝트에서 REST 프레임워크의 API 설정값에 액서스해야하는 경우 `api_settings`객체를 사용해야합니다. 예를 들면.
```python
from rest_framework.settings import api_settings
print api_settings.DEFAULT_AUTHENTICATION_CLASSES
```
`api_settings`객체는 사용자가 정의한 설정을 확인하고 그렇지 않으면 기본값을 fall back합니다. 클래스를 참조하기 위해 string import path를 사용하여 모든 설정은 문자열 리터럴 대신 참조 된 클래스를 자동으로 가져오고 반환합니다.
---
## API Reference
### API policy settings
다음 설정은 기본 API 정책을 제어하며 모든 `APIView` CBV 또는 `@api_view` FBV에 적용됩니다.
#### `DEFAULT_RENDERER_CLASSES`
`Response` 객체를 반환할 때 사용할 수 있는 renderer의 기본 set을 결정하는 rederer 클래스의 list 또는 tuple입니다.
Default:
```python
(
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
)
```
#### `DEFAULT_PARSER_CLASSES`
`request.data`속성에 액서스 할 때 사용되는 parser의 기본 set을 결정하는 parser 클래스의 list 또는 tuple입니다.
Default:
```python
(
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
)
```
#### `DEFAULT_AUTHENTICATION_CLASSES`
`request.user` 또는 `request.auth`등록 정보에 액서스할 때 사용되는 인증자의 기본 set을 판별하는 authentication 클래스의 list 또는 tuple입니다.
Default:
```python
(
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
```
#### `DEFAULT_PERMISSION_CLASSES`
view의 시작에 체크 된 권한의 기본 set을 결정하는 permission 클래스의 list 또는 tuple입니다. permission은 list의 모든 클래스에서 부여해야합니 다.
Default:
```python
(
'rest_framework.permissions.AllowAny',
)
```
#### `DEFAULT_THROTTLE_CLASSES`
view의 시작에서 점검되는 기본 throttle set을 결정하는 throttle 클래스의 list 또는 tuple입니다.
Default: `()`
#### `DEFAULT_CONTENT_NEGOTIATION_CLASS`
들어오는 request에 따라 rederer가 response에 대해 선택되는 방법을 결정하는 content negotiation 클래스 입니다.
Default: `'rest_framework.negotiation.DefaultContentNegotiation'`
---
### Generic view settings
다음 설정은 generic CBV의 동작을 제어합니다.
#### `DEFAULT_PAGINATION_SERIALIZER_CLASS`
---
**이 설정은 제거되었습니다.**
pagination API는 출력 형식을 결정하기 위해 serializer를 사용하지 않으므로 대신 출력 형식 제어 방법을 지정하기 위해 pagination 클래스의 `'get_paginated_response`` 메서드를 대체해야합니다.
---
#### `DEFAULT_FILTER_BACKENDS`
generic 필터링에 사용해야 하는 filter backend 클래스 list입니다. `None`으로 설정하면 generic 필터링이 비활성화됩니다.
#### `PAGINATE_BY`
---
**이 설정은 제거 되었습니다.**
pagination 스타일 설정에 대한 자세한 지침은 [setting the pagination style](http://www.django-rest-framework.org/api-guide/pagination/#modifying-the-pagination-style)를 참조하세요.
---
#### `PAGE_SIZE`
pagination에 사용할 기본 페이지 크기입니다. `None`으로 설정하면 기본적으로 pagination이 비활성화됩니다.
Default: `None`
#### `PAGINATE_BY_PARAM`
---
**이 설정은 제거 되었습니다.**
pagination 스타일 설정에 대한 자세한 지침은 [setting the pagination style](http://www.django-rest-framework.org/api-guide/pagination/#modifying-the-pagination-style)를 참조하세요.
---
#### `MAX_PAGINATE_BY`
---
**이 설정은 지원 중단 예정입니다.**
pagination 스타일 설정에 대한 자세한 지침은 [setting the pagination style](http://www.django-rest-framework.org/api-guide/pagination/#modifying-the-pagination-style)를 참조하세요.
---
#### SEARCH_PARAM
`SearchFilter`가 사용하는 검색어를 지정하는데 사용 할 수 있는 검색어 parameter의 이름입니다.
Default: `search`
#### ORDERING_PARAM
`OrderingFilter`에 의해 반환 된 결과의 순서를 지정하는데 사용할 수 있는 쿼리 parameter의 이름입니다.
Default: `ordering`
---
### Versioning settings
#### DEFAULT_VERSION
버전 정보가 없는 경우 `request.version`에 사용해야 하는 값입니다.
Default: `None`
#### ALLOWED_VERSIONS
이 값을 설정하면 버전 체계에 의해 반환 될 수 있는 버전 set이 제한되며, 제공된 버전이 이 set에 포함되어 있지 않으면 오류가 발생합니다.
Default: `none`
#### VERSION_PARAM
미디어 타입 또는 URL 쿼리 parameter와 같이 모든 버젼 지정 parameter에 사용해야하는 문자열입니다.
Default: `version`
---
### Authentication settings
다음 설정은 인증되지 않은 요청의 동작을 제어합니다.
#### UNAUTHENTICATED_USER
인증되지 않은 요청에 대해 `request.user`를 초기화하는데 사용해야하는 클래스입니다.
Default: `django.contrib.auth.models.AnonymousUser`
#### UNAUTHENTICATED_TOKEN
인증되지 않은 요청에 대해 `request.auth`를 초기화하는데 사용해야 하는 클래스입니다.
default: `None`
--
### Test settings
다음 설정은 APIRequestFactory 및 APIClient의 동작을 제어합니다.
#### `TEST_REQUEST_DEFAULT_FORMAT`
테스트 요청을 할때 사용해야하는 기본 형식입니다.
이 값은 `TEST_REQUEST_RENDERER_CLASSES`설정의 renderer 클래스 중 하나의 형식과 일치해야합니다.
Default: `'multipart'`
#### `TEST_REQUEST_RENDERER_CLASSES`
테스트 요청을 작성할 때 지원되는 renderer 클래스입니다.
`client.post('/users', {'username': 'jamie'}, format='json')` 이러한 renderer 클래스의 형식은 테스트 요청을 구성 할 때 사용할 수 있습니다.
Default:
```python
(
'rest_framework.renderers.MultiPartRenderer',
'rest_framework.renderers.JSONRenderer'
)
```
---
### Schema generation controls
#### `SCHEMA_COERCE_PATH_PK`
이것을 설정하면 schema path parameter를 생성할 때 URL conf의 `'pk'`식별자를 실제 필드 이름으로 매핑합니다. 일반적으로 `'id'`가 됩니다. 이것은 "indentifer"가 좀 더 일반적인 개념인 반면 "primary key"는 세부 사항이므로 보다 적합한 표현을 제공합니다.
Default: `True`
#### `SCHEMA_COERCE_METHOD_NAMES`
이것이 설정되면 내부 viewset 메소드 이름을 schema generation에 사용 딘 외부 액션 이름에 매핑하는데 사용됩니다. 이것은 코드 베이스에서 내부적으로 사용되는 것보다 외부 표현에 더 적합한 이름을 생성할 수 있게 해줍니다.
Default: `{'retrieve': 'read', 'destroy': 'delete'}`
---
### Content type controls
#### `URL_FORMAT_OVERRIDE`
기본 content negotiation `Accept`을 오버라이드하는데 사용할 수 있는 URL parameter의 이름 요청 URL에서 `format=...` 쿼리 parameter를 사용하여 헤더의 동작을 허용합니다.
예: `http://example.com/organizations/?format=csv`
이 설정 값이 `None`이면 URL 형식 오버라이드가 비활성화 됩니다.
Default: `'format'`
#### `FORMAT_SUFFIX_KWARG`
format suffix를 제공하는데 사용할 수 있는 URL conf의 parameter 이름입니다. 이 설정은 format_suffix_pattern`을 사용하여 접미사로 된 URL패턴을 포함할 때 적용됩니다.
예: `http://example.com/organizations.csv/`
Default: `'format'`
---
### Date and time formatting
다음 설정은 날짜 및 시간 표현을 파싱하고 렌더링하는 방법을 제어하는데 사용됩니다.
#### `DATETIME_FORMAT`
`DateTimeField` Serializer 필드의 출력을 렌더링하기 위해 기본적으로 사용해야 하는 형식 문자열입니다. `None`이면 `DateTimeField` serializer 필드는 Python `datetime`객체를 반환하고, datetime 인코딩은 렌더러에 의해 결정됩니다.
`None`, `'iso-8601'`또는 Python [strftime format](https://docs.python.org/3/library/time.html#time.strftime) 형식 문자열 주 하나 일 수 있습니다.
Default: `'iso-8601'`
#### `DATETIME_INPUT_FORMATS`
`DateTimeField` serializer 필드에 대한 입력을 파싱하기위해 기본적으로 사용해야하는 형식문자열 list입니다.
문자열 `'iso-8601'`또는 python [strftime format](https://docs.python.org/3/library/time.html#time.strftime)형식 문자열을 포함하는 list일 수 있습니다.
Default: `['iso-8601']`
#### `DATE_FORMAT`
`DateField` serializer필드의 출력을 렌더링하기 위해 기본적으로 사용해야하는 형식 문자열입니다. `None`이면 `DateField` serializer 필드는 Python `date` 객체를 반환하고 날짜 인코딩은 렌더러에 의해 결정됩니다.
`None`, `'iso-8601'`또는 python [strftime format](https://docs.python.org/3/library/time.html#time.strftime)형식 문자열을 포함하는 list일 수 있습니다.
Default: `['iso-8601']`
#### `DATE_INPUT_FORMATS`
`DateField` serializer 필드에 대한 입력을 파싱하기 위해 기본적으로 사용해야하는 형식 문자열 list입니다.
문자열 `'iso-8601'`또는 python [strftime format](https://docs.python.org/3/library/time.html#time.strftime)형식 문자열을 포함하는 list일 수 있습니다.
Default: `['iso-8601']`
#### `TIME_FORMAT`
`TimeField` serializer 필드의 출력을 렌더링 할 때 기본저긍로 사용해야하는 형식 문자열입니다. `None` 이면 `TimeField` serializer 필드는 Python `time` 객체를 반환하고 time 인코딩은 렌더러에 의해 결정됩니다.
`None`, `'iso-8601'`또는 python [strftime format](https://docs.python.org/3/library/time.html#time.strftime)형식 문자열을 포함하는 list일 수 있습니다.
Default: `['iso-8601']`
#### `TIME_INPUT_FORMATS`
`TimeField` serializer 필드에 대한 입력을 파싱하기 위해 기본적으로 사용해야 하는 형식 문자열 list입니다.
문자열 `'iso-8601'`또는 python [strftime format](https://docs.python.org/3/library/time.html#time.strftime)형식 문자열을 포함하는 list일 수 있습니다.
Default: `['iso-8601']`
---
### Encodings
#### `UNICODE_JSON`
`True`로 설정하면, JSON response가 response에 유니코드 문자를 허용합니다.
```
{"unicode black star":"★"}
```
`False`로 설정하면 JSON response가 다음과 같이 non-ascii 문자를 이스케이프합니다.
```
{"unicode black star":"\u2605"}
```
두 스타일 모두 [RFC 4627]()을 준수하며 구문적으로 유효한 JSON입니다. 유니코드 스타일은 API 응답을 검사할 때보다 사용자에게 친숙한 것으로 선호됩니다.
Default: `True`
#### `COMPACT_JSON`
`True`로 설정하면 JSON response sms `':'``','`문자 다음에 공백없이 간결한 표현을 반환합니다.
```
{"is_admin":false,"email":"jane@example"}
```
`False`로 설정하면 JSON 응답이 다음과 같이 약간 더 자세한 표현을 반환합니다.
```
{"is_admin": false, "email": "jane@example"}
```
기본 스타일은 [Heroku's API design guidelines](https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses)에 따라 축소 된 응답을 반환하는 것입니다.
Default: `True`
#### `COERCE_DECIMAL_TO_STRING`
기존 decimal(10진) type을 지원하지 않는 API 표현에서 decimal 오브젝트를 리턴할 때, 일반적으로 값을 문자열로 리턴하는 것이 가장 좋습니다. 따라서 바이너리 부동 소수점 구현에서 발생하는 정밀도의 손실을 피할 수 있습니다.
`True`로 설정하면 serializer `DecimalField` 클래스가 Decimal 객체 대신 문자열을 반환합니다. `False`로 설정하면, serializer는 Decimal 객체를 반환합니다. 이 객체는 기본 JSON 인코더가 float으로 반환합니다.
Default: `True`
---
### View names and descriptions
**다음 설정은 `OPTIONS` 요청에 대한 응답 및 Browsable API에서 사용되는 것과 같이 뷰 이름 및 설명을 생성하는데 사용됩니다.**
#### `VIEW_NAME_FUNCTION`
뷰 이름을 생성할 때 사용해야하는 함수를 나타내는 문자열입니다.
이것은 다음 시그니처가 있는 함수이어야 합니다.
```
view_name(cls, suffix=None)
```
- `cls` : 뷰 클래스. 일반적으로 이름 함수는 `cls.__name__`에 액서스하여 설명적인 이름을 생성 할 때 클래스 이름을 검사합니다.
- `suffix` : viewset에서 개별 뷰를 구별 할 때 사용되는 선택적 suffix
Default: `'rest_framework.views.get_view_name'`
#### `VIEW_DESCRIPTION_FUNCTION`
뷰 설명을 생성 할 때 사용해야하는 함수를 나타내는 문자열입니다.
기본 설정 값 이외의 태그 스타일을 지원하도록 이 설정을 변경할 수 있습니다. 예를 들어, 브라우저에서 볼 수 있는 API로 출력되는 뷰 문서 문자열의 `rst` 마크업을 지원하는데 사용할 수 있습니다.
이것은 다음 시그니처가 있는 함수이어야 합니다.
```
view_description(cls, html=False)
```
- `cls` : 뷰 클래스. 일반적으로 설명 함수는 `cls.__doc__`에 액서스하여 설명을 생성 할 때 클래스의 문서화 문자열을 검사합니다.
- `html` : HTML 출력이 필요한지 나타내는 boolean입니다. 탐색 가능한 API에서 사용되면 `True`이고, `OPTIONS`응답을 생성하는데 사용되면 `False`입니다.
Default: `'rest_framework.views.get_view_description'`
### HTML Select Field cutoffs
Browsable API에서 [관계형 필드를 렌더링하기 위한 선택 필드 컷오프](http://www.django-rest-framework.org/api-guide/relations/#select-field-cutoffs)에 대한 전역 설정입니다.
#### `HTML_SELECT_CUTOFF`
`html_cutoff`값의 전역 설정입니다. 정수이어야 합니다.
Default: 1000
#### `HTML_SELECT_CUTOFF_TEXT`
`html_cutoff_text`의 전역 설정을 나타내는 문자열입니다.
Default: `"More than {count} items..."`
---
### Miscellaneous settings
#### `EXCEPTION_HANDLER`
지정된 예외에 대한 응답을 반환할 때 사용해야하는 함수를 나타내는 문자열입니다. 이 함수가 `None`을 반환하면 500 error가 발생합니다.
이 설정은 기본 `{"detail": "Failure..."}`응답 이외의 오류 응답을 지원하도록 변경할 수 있습니다. 예를 들어 `{"errors": [{"message": "Failure...", "code": ""} ...]}`와 같은 API 응답을 제공하는데 사용할 수 있습니다.
이것은 다음 시그니처가 있는 함수이어야 합니다.
```
exception_handler(exc, context)
```
- `exc` : 예외
Default: `'rest_framework.views.exception_handler'`
#### `NON_FIELD_ERRORS_KEY`
특정 필드를 참조하지 않고 일반적인 오류인 serializer 오류에 사용해야하는 키를 나타내는 문자열입니다.
Default: `'non_field_errors'`
#### `URL_FIELD_NAME`
`HyperlinkedModelSerializer`에 의해 생성 된 URL 필드에 사용해야하는 키를 나타내는 문자열입니다.
Default: `'url'`
#### `NUM_PROXIES`
API가 실행되는 응용 프로그램 프록시 수를 지정하는데 사용할 수 있는 0 이상의 정수입니다. 이렇게 하면 throttling을 통해 클라이언트 IP 주소를 보다 정확하게 식별할 수 있습니다. `None`으로 설정하면 덜 엄격한 IP 매칭이 throttle 클래스에서 사용됩니다.
Default: `None`

View File

@ -0,0 +1,129 @@
# Django REST Framework - Status Codes
---
_"418 I'm a teapot - Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout."_
_"418 저는 주전자입니다 - 주전자로 커피를 양조하려고하면 "418 나는 주전자입니다"라는 오류 코드가 나타납니다. 그 결과로 생성 된 실제 몸체는 짧고 튼튼 할 수 있다."_
_— RFC 2324, Hyper Text Coffee Pot Control Protocol_
---
## Status Codes
응답에 베어 상태 코드를 사용하는 것은 좋지 않습니다. REST 프레임워크에는 더 많은 코드를 보다 명확하고 읽기 쉽게 만드는데 사용 할 수 있는 명명 된 상수 set이 포함되어 있습니다.
```python
from rest_framework import status
from rest_framework.response import Response
def empty_view(self):
content = {'please move along': 'nothing to see here'}
return Response(content, status=status.HTTP_404_NOT_FOUND)
```
`status` 모듈에 포함된 HTTP status code의 full set은 다음과 같습니다.
모듈에는 status code가 주어진 범위에 있는지 테스트하기 위한 helper 함수 set가 포함되어 있습니다.
```python
from rest_framework import status
from rest_framework.test import APITestCase
class ExampleTestCase(APITestCase):
def test_url_root(self):
url = reverse('index')
response = self.client.get(url)
self.assertTrue(status.is_success(response.status_code))
```
HTTP status code의 올바른 사용법에 대한 자세한 내용은 [RFC 2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)와 [RFC 6585](https://tools.ietf.org/html/rfc6585)를 참조사헤요.
### Informational - 1xx
이 status code 클래스는 잠정적인 응답을 나타냅니다. 기본적으로 REST 프레임워크에는 1xx status code가 사용되지 않습니다.
```
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
```
### Successful - 2xx
이 status code 클래스는 클라이언트 요청이 성공적으로 수신, 이해, 승인되었음을 나타냅니다.
```
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
```
### Redirection - 3xx
이 status code 클래스는 요청을 수행하기 위해 사용자 에이전트가 추가 조치를 취해야 함을 나타냅니다.
```
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
```
### Client Error - 4xx
4xx 클래스의 status code는 클라이언트가 오류가 있는 것으로 보이는 경우를 위한 것입니다. HEAD request에 응답 할 때를 제외하고, 서버 SHOULD는 오류 상황에 대한 설명과 일시적인 것인지 지속적인 것인지를 포함한 엔티티를 포함해야합니다.
```
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
```
### Server Error - 5xx
숫자 "5"로 시작하는 response status code는 서버에 오류가 발생했거나 요청을 수행 할 수 없다는 것을 알고있는 경우를 나타냅니다. HEAD requset에 응답할 때를 제외하고, 서버 SHOULD 는 오류 상황에 대한 설명과 일시적인지 것인지 지속적인 것인지를 포함한 엔티티를 포함해야합니다.
```
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
```
### Helper functions
다음 helper 함수는 응답 코드의 범주를 식별하는데 사용할 수 있습니다.
```
is_informational() # 1xx
is_success() # 2xx
is_redirect() # 3xx
is_client_error() # 4xx
is_server_error() # 5xx
```

View File

@ -0,0 +1,376 @@
# Django REST Framework - Testing
_**"Code without tests is broken as designed."
"테스트가 없는 코드는 의도 한대로 작동하지 않는다." - Jacob Kaplan-Moss**_
REST 프레임워크는 Django의 기존 테스트 프레임워크를 확장하고, API Requests 작성에 대한 지원을 향상시키는 서포트 클래스를 포함하고 있습니다.
## APIRequestFactory
Django의 기존 `RequestFactory` 클래스를 확장합니다.
### Creating test requests
`APIRequestFactory` 클래스는 Django의 표준 `RequestFactory` 클래스와 거의 동일한 API를 지원합니다. 즉 표준 `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()``.options()` 메서드를 모두 사용할 수 있습니다.
```
rom rest_framework.test import APIRequestFactory
# 표준 `RequestFactory` API을 사용ㅎ여 POST request form을 만든다.
factory = APIRequestFactory()
request = factory.post('/notes/', {'title': 'new idea'})
```
#### Using the `format` argument
`post`,`put`,`patch`와 같은 requests를 만드는 메서드에는 content type을 사용하여 requests를 쉽게 생성 할 수 있도록 하는 argument가 포함되어 있습니다.
```
# Create a JSON POST request
factory = APIRequestFactory()
request = factory.post('/notes/', {'title': 'new idea'}, format='json')
```
기본적으로 사용 가능한 형식은 `multipart``json`입니다. Django의 기존 `RequestFactory`와의 호환성을 위해 기본 형식은 `multipart`입니다.
더 많은 형식에 대한 정보는 [configuration section](http://www.django-rest-framework.org/api-guide/testing/#configuration)을 참조하세요.
#### Explicitly encoding the request body
request 본문을 명시적으로 인코딩해야 하는 경우 `context_type` 플래그를 설정하여 request 본문을 인코딩할 수 있습니다.
```
request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')
```
#### PUT and PATCH with form data
Django의 `RequestFactory`와 REST 프레임 워크의 `APIRequestFactory` 사이에 주목할 만한 차이점은 다중 파트 양식 데이터가 `.post()` 이외의 메소드로 인코딩된다는 것입니다.
예를 들어, `APIRequestFactory`를 사용하면 다음과 같이 `put`요청을 할 수 있습니다.
```
factory = APIRequestFactory()
request = factory.put('/notes/547/', {'title': 'remember to email dave'})
```
Django의 `RequestFactory`를 사용하면 명시적으로 데이터를 직접 인코딩해야합니다.
```
from django.test.client import encode_multipart, RequestFactory
factory = RequestFactory()
data = {'title': 'remember to email dave'}
content = encode_multipart('BoUnDaRyStRiNg', data)
content_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'
request = factory.put('/notes/547/', content, content_type=content_type)
```
#### Forcing authentication
`RequestFactory`를 사용하여 직접 뷰를 테스트 할 때는 인증자격 증명을 작성하지않고 직접 자격요청을 인증하는 것이 편리합니다.
강제 요청을 인증하려면 `force_authenticate()` 메소드를 사용하십시오.
```
from rest_framework.test import force_authenticate
factory = APIRequestFactory()
user = User.objects.get(username='olivia')
view = AccountDetail.as_view()
# Make an authenticated request to the view...
request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user)
response = view(request)
```
이 메소드의 서명은 `force_authenticate(request, user = None, token = None)`입니다. 전화를 걸 때 사용자와 토큰 중 하나 또는 둘 모두가 설정 될 수 있습니다.
예를 들어, 토큰을 사용하여 강제로 인증하는 경우 다음과 같이 할 수 있습니다.
```
user = User.objects.get(username='olivia')
request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user, token=user.token)
```
---
**Note** : `APIRequestFactory`를 사용할 때 반환되는 객체는 Django의 표준 `HttpRequest`이며, REST 프레임워크의 Request 객체는 아니며 뷰가 호출 된 후에만 ​​생성됩니다.
즉, request 객체에 직접 속성을 설정하면 항상 원하는 결과를 얻을 수 없을 수도 있습니다.
예를 들어, `.token`을 직접 설정해도 아무 효과도 없으며 세선 인증을 사용하는 경우 `.user`를 직접 설정할 수 있습니다.
```
# Request은`SessionAuthentication`이 사용 중일 때에 만 인증합니다.
request = factory.get('/accounts/django-superstars/')
request.user = user
response = view(request)
```
---
#### Forcing CSRF validation
기본적으로 `APIRequestFactory`으로 생성 된 request에는 REST 프레임워크 뷰에 전달 될 때 CSRF 유효성 검사가 적용되지 않습니다.
CSRF 유효성 검사를 명시적으로 수행해야하는 경우, 팩토리를 인스턴스화 할 때 `enforce_csrf_checks` 플래그를 설정하면됩니다.
```
factory = APIRequestFactory(enforce_csrf_checks=True)
```
---
**Note** : Django의 표준 `RequestFactory`는 이 옵션을 포함할 필요가 없다는 사실에 주목해야 합니다. Django를 사용할 때 뷰를 직접 테스트 할 때 실행되지 않는 미들웨어에서 CSRF 유효성 검사가 수행되기 때문입니다. REST 프레임워크를 사용할 때 뷰 내부에서 CSRF 유효성 검사가 수행되므로 요청 팩토리는 뷰 수준의 CSRF 검사를 비활성화해야합니다.
---
### APIClient
Django의 기존 `Client`클래스를 확장합니다.
#### Making requests
`APIClient`클래스는 DJango의 표준 Client클래스와 동일한 요청 인터페이스를 지원합니다. 즉, `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()`, `.options()` 메서드를 모두 사용할 수 있습니다.
```
from rest_framework.test import APIClient
client = APIClient()
client.post('/notes/', {'title': 'new idea'}, format='json')
```
더 만은 정보는 [configuration section](http://www.django-rest-framework.org/api-guide/testing/#configuration)를 참조하세요.
#### Authenticating
##### .login(**kwargs)
`login`메소드는 Django의 `Cilent`클래스와 똑같이 작동합니다. 이렇게 하면 `SessionAuthentication`이 포함된 모든 views에 대한 요청을 인증 할 수 있습니다.
```
# Make all requests in the context of a logged in session.
client = APIClient()
client.login(username='lauren', password='secret')
```
로그아웃하려면 `logout`메소드를 호출하세요.
```
# Log out
client.logout()
```
`login` 메소드는 `AJAX API`와의 상호 작용을 포함하는 웹 사이트와 같이 세션 인증을 사용하는 API를 테스트하는데 적합합니다.
##### .credentials(**kwargs)
`credentials`메소드는 테스트 클라이언트가 모든 후속 요청에 포함 할 헤더를 설정하는데 사용할 수 있습니다.
```
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient
# Include an appropriate `Authorization:` header on all requests.
token = Token.objects.get(user__username='lauren')
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
```
`credentials`를 다시 호출하면 기존 `credentials`을 덮어 씁니다. 인수없이 메서드를 호출하여 기존 `credentials`의 설정을 해제할 수 있습니다.
```
# Stop including any credentials
client.credentials()
```
`credentials` 방법은 기본인증, OAuth1a과 OAuth2 인증 및 간단한 토큰 인증스키마와 같은 인증 헤더가 필요한 API를 테스트하는데 적합합니다.
##### .force_authenticate(user=None, token=None)
때로는 인증을 생략하고 테스트 클라이언트의 모든 요청을 인증 된 것으로 자동처리하도록 할 수 있습니다.
이는 API를 테스트하고 있지만 테스트 요청을 하기 위해 유효한 자격 증명을 작성하지 않으려는 경우 유용한 단축키입니다.
```
user = User.objects.get(username='lauren')
client = APIClient()
client.force_authenticate(user=user)
```
후속 요청을 인증 해제하려면 `force_authenticate`를 호출하여 사용자/토큰을 `None`으로 설정하세요.
```
client.force_authenticate(user=None)
```
#### CSRF validation
기본적으로 CSRF 유효성 검사는 APICLient를 사용할 떄 적합하지 않습니다. CSRF 유효성 검사를 명시적으로 활성화해야하는 경우 Client를 인스턴스화 할때 `enforce_csrf_checks`플래그를 설정하면 됩니다.
```
client = APIClient(enforce_csrf_checks=True)
```
평소처럼 CSRF 유효성검사는 세션 인증 된 views에만 적용됩니다. 즉, 클라이언트가 `login()`을 호출하려 로그인한 경우에만 CSRF 유효성 검사가 수행됩니다.
---
### RequestsClient
RESR 프레임워크에는 `request`(Python 라이브러리)를 사용하여 애플리케이션과 상호 작용하는 client도 포함되어 있습니다. 다음과 같은 경우 유용하게 사용할 수 있습니다.
- 주로 다른 Python 서비스의 API와의 인터페이스를 기대하고 있으며, client가 볼 수 있는 것과 동일한 수준에서 서비스를 테스트하려 할 때
- 준비 또는 실제 환경에 대해 실행할 수 있는 방식으로 테스트를 작성할 때 ("Live test" 참조)
이는 requests 세션을 직접 사용하는 것과 동일한 인터페이스를 제공합니다.
```
client = RequestsClient()
response = client.get('http://testserver/users/')
assert response.status_code == 200
```
requests client에서는 정규화 된 URL을 전달해야 합니다.
#### `RequestsClient` and working with the database
`RequestsClient`클래스는 서비스 인터페이스만 상호 작용하는 테스트를 작성하려는 경우에 유용합니다. 이것은 Django 테스트 클라이언트를 사용하는 것보다 조금 더 엄격합니다. 모든 상호작용이 API를 통해 이루어져야하기 떄문입니다.
`RequestsClient`를 사용하는 경우 데이터베이스 모델과 직접 상호 작용하는 대신 테스트 설정 및 결과 주장(?)을 일반 API 호출로 수행해야합니다.
예를 들어, `Customer.objects.count () == 3`를 확인하는 대신 `customers` 마지막점을 나열하고 3개의 레코드가 있는지 확인하세요.
#### Headers & Authentication
custom 헤더와 인증자격 증명은 `requests.Session` 인스턴스를 사용할 때와 동일한 방식으로 제공 될 수 있습니다.
```
from requests.auth import HTTPBasicAuth
client.auth = HTTPBasicAuth('user', 'pass')
client.headers.update({'x-test': 'true'})
```
#### CSRF
`SessionAuthentication`을 사용하는 경우 `POST`, `PUT`, `PATCH`, `DELETE` 요청에 대해 CSRF 토큰을 포함해야합니다.
JavaScript 기반의 클라이언트가 사용하는 것과 동일한 흐름으로 수행 할 수 있습니다.
먼저 CRSF 토큰을 얻기 위해 `GET` 요청을 하고 다음 요청에 토큰을 제시하십시오.
```
client = RequestsClient()
# Obtain a CSRF token.
response = client.get('/homepage/')
assert response.status_code == 200
csrftoken = response.cookies['csrftoken']
# Interact with the API.
response = client.post('/organisations/', json={
'name': 'MegaCorp',
'status': 'active'
}, headers={'X-CSRFToken': csrftoken})
assert response.status_code == 200
```
#### Live tests
신중하게 사용하면 `RequestsClient``CoreAPIClient`가 모두 개발 환경에서 실행되거나 준비 서버 또는 프로덕션 환경에 직접 실행 될 수 있는 테스트 사례를 작성할 수 있습니다.
이럼 스타일로 몇 가지 핵심 기능 중 일부에 대한 기본 테스트를 만드는 것은 실제 서비스를 확인하는 강력한 방법입니다. 이렇게하려면 테스트가 고객 데이터에 직접 영향을 주지 않는 방식으로 실행되도록 설정 및 해제하는데 신중을 기해야합니다.
---
### CoreAPIClient
`CoreAPIClient`를 사용하면 `coreapi` (Python 클라이언트 라이브러리)를 사용하여 API와 상호 작용할 수 있습니다.
```
# Fetch the API schema
client = CoreAPIClient()
schema = client.get('http://testserver/schema/')
# Create a new organisation
params = {'name': 'MegaCorp', 'status': 'active'}
client.action(schema, ['organisations', 'create'], params)
# Ensure that the organisation exists in the listing
data = client.action(schema, ['organisations', 'list'])
assert(len(data) == 1)
assert(data == [{'name': 'MegaCorp', 'status': 'active'}])
```
#### Headers & Authentication
Customs 헤더와 인증은 `RequestsClient`와 비슷한 방식으로 `CoreAPIClient`와 함께 사용할 수 있습니다.
```
from requests.auth import HTTPBasicAuth
client = CoreAPIClient()
client.session.auth = HTTPBasicAuth('user', 'pass')
client.session.headers.update({'x-test': 'true'})
```
---
### Test cases
REST 프레임워크는 DJango 테스트 케이스 클래스를 반영하지만, Django의 기본 클라이언트 대신 `APIClient`를 사용하는 테스트 케이스 클래스를 포함합니다.
- APISimpleTestCase
- APITransactionTestCase
- APITestCase
- APILiveServerTestCase
#### Example]
Django 테스트케이스 클래스처럼 REST 프레임워크의 테스트 케이스 클래스 중 하나를 사용할 수 있습니다. `self.client` 속성은 `APIClient` 인스턴스입니다.
```
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from myproject.apps.core.models import Account
class AccountTests(APITestCase):
def test_create_account(self):
"""
Ensure we can create a new account object.
"""
url = reverse('account-list')
data = {'name': 'DabApps'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Account.objects.count(), 1)
self.assertEqual(Account.objects.get().name, 'DabApps')
```
---
### Testing responses
#### Checking the response data
테스트 응답의 유효성을 검사 할 때 완전히 렌더링 된 응답을 검사하는 것보다 응답이 생성 된 데이터를 검사하는 것이 더 편리합니다.
예를 들어, `response.data`를 검사하는 것이 더 쉽습니다.
```
response = self.client.get('/users/4/')
self.assertEqual(response.data, {'id': 4, 'username': 'lauren'})
```
`response.content`를 구문 분석한 결과를 검사하는 대신:
```
response = self.client.get('/users/4/')
self.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'})
```
#### Rendering responses
`APIRequestFactory`를 사용하여 뷰를 직접 테스트하는 경우, 템플릿 응답의 렌더링이 Django의 내부 requests - response 에 의해 수행되기 때문에 반환되는 응답은 아직 렌더링되지 않습니다. `response.content`에 액세스하려면 먼저 응답을 렌더링해야합니다.
```
view = UserDetail.as_view()
request = factory.get('/users/4')
response = view(request, pk='4')
response.render() # Cannot access `response.content` without this.
self.assertEqual(response.content, '{"username": "lauren", "id": 4}')
```
---
### Configuration
#### Setting the default format
테스트 요청을하는 데 사용되는 기본 형식은 `TEST_REQUEST_DEFAULT_FORMAT` 설정 키를 사용하여 설정할 수 있습니다. 예를 들어, 테스트 요청을 항상 `JSON`을 사용하려면 `settings.py`파일에서 다음을 설정하세요.
```
REST_FRAMEWORK = {
...
'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}
```
#### Setting the available formats
multipart 또는 `json` 요청 이외의 것을 사용하여 요청을 테스트해야하는 경우 `TEST_REQUEST_RENDERER_CLASSES` 설정을 설정하여 요청을 테스트 할 수 있습니다.
예를 들어, 테스트 요청에 `format = 'html'`을 추가하려면 `settings.py` 파일에 다음과 같은 내용이 추가합니다.
```
REST_FRAMEWORK = {
...
'TEST_REQUEST_RENDERER_CLASSES': (
'rest_framework.renderers.MultiPartRenderer',
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer'
)
}
```

View File

@ -0,0 +1,174 @@
# Django REST Framework - Throttling
---
_"HTTP/1.1 420 Enhance Your Calm"_
_Twitter API rate limiting response_
---
## Throttling (제한)
Throttling은 request가 승인되어야하는지 여부를 결정한다는 점에서 permissions와 유사합니다. Throttling은 임시상태를 나타내며 클라이언트가 API에 대해 수행 할 수 있는 request 빈도수를 제어하는데 사용됩니다.
permissions과 마찬가지로, 여러 Throttle을 사용할 수 있습니다. API에는 인증되지 않은 요청에 대해 제한적으로 Throttle과 인증 된 요청에 대한 제한적인 Throttle이 있을 수 있습니다.
특정 서비스가 특히 리소스를 잡아먹기 때문에 API의 다양한 부분에 다른 제약을 부과해야하는 경우, 여러 throttle을 사용하는 다른 시나리오가 있습니다.
버스트 빈도수 제한와 지속적인 빈도수 제한을 동시에 적용하려는 경우, 여러 throttle을 사용할 수 있습니다. 예를 들어, 분당 최대 60개의 요청과 하루에 1000개의 요청으로 사용자를 제한 할 수 있습니다.
throttle은 반드시 rate 제한 요청을 참조하는 것은 아닙니다. 예를 들어, 스토리지 서비스는 대역폭에 대해 조정해야 할 수고 있으며, 유료 데이터 서비스는 액서스되는 특정 레코드 수에 대해 조정할 수 있습니다.
### How throttling is determined
사용 권한 및 인증과 마찬가지로 REST 프레임워크의 Throttling은 항상 클래스 목록으로 정의됩니다.
뷰의 본문을 실행하기 전에 list의 각 throttle이 점검됩니다. throttle 확인이 실패하면 `exceptions.Throttled`예외가 발생하고, 뷰 본문은 실행되지 않습니다.
### Setting the throttling policy
기본 throttling 정책은 `DEFAULT_THROTTLE_CLASSES``DEFAULT_THROTTLE_RATES` 설정을 사용하여 전역으로 설정할 수 있습니다. 예를 들면.
```python
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
```
`DEFAULT_THROTTLE_RATES`에 사용 된 rate에는 throttle 기간으로 `second`, `minute`, `hour`, `day`이 포함 될 수 있습니다.
또한 APIView CBV를 사용하여 뷰 단위 또는 뷰 단위별 조절 정책을 설정할 수 있습니다.
```python
from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
```
또는 FBV와 함께 `@api_view`데코레이터를 사용하는 경우
```python
@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
```
### How clients are identified(클라이언트 식별 방법)
`X-Forwarded_For``Remote-Addr` HTTP 헤더는 throttling을 위해 클라이언트 IP주소를 고유하게 식별하는데 사용됩니다.
`X-Forwarded_For`헤더가 있으면 사용되고, 없으면 `Remote-Addr` 헤더 값이 사용됩니다.
고유한 클라이언트 IP주소를 엄격하게 식별해야하는 경우, 우선 `NUM-PROXIES`설정을 하여 API가 실행되는 응용 프로그램 프록시의 수를 구성해야 합니다. 이 설정은 0 이상의 정수이어야 합니다. 0 이 아닌 값으로 설정된 경우, 클라이언트 IP는 응용 프로그램 프록시 IP 주소가 먼저 제외되면 `X-Forwarded-For` 헤더의 마지막 IP 주소로 식별됩니다. 0 으로 설정하면 `Remote-Addr`헤더가 항상 식별 IP주소로 사용됩니다.
`NUM_PROXIES`설정을 구성하면 고유한 `NAT'd` 게이트웨이 뒤에 있는 모든 클라이언트가 단일 클라이언트로 처리 된다는 것을 이해하는 것이 중요합니다.
`X-Forwarded-For`헤더의 작동 방식 및 원격 클라이언트 IP 식별 방법에 대한 자세한 내용은 [여기](http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster)를 참조하세요.
### Setting up the cache
REST 프레임워크가 제공하는 throttle 클래스는 Django의 캐시 백엔드를 사용합니다. 적절한 [캐시 설정](https://docs.djangoproject.com/en/1.10/ref/settings/#caches)을 지정했는지 확인해야합니다. `LocMemCache`백엔드의 기본값은 간단한 설정으로 괜찮습니다. 자세한 내용은 [cache documentation](https://docs.djangoproject.com/en/1.10/topics/cache/#setting-up-the-cache)을 참조하세요.
`default`가 아닌 캐시를 사용해야하는 경우, custom throttle 클래스를 만들고 캐시 속성을 설정하면 됩니다. 예를 들어:
```python
class CustomAnonRateThrottle(AnonRateThrottle):
cache = get_cache('alternate')
```
`DEFAULT_THROTTLE_CLASSES` 설정 키 또는 `throttle_classes` 뷰 속성을 사용하여 custom throttle 클래스를 기억해야만 합니다.
## API Reference
### AnonRateThrottle
`AnonRateThrottle`은 인증되지 않은 사용자만 차단합니다. 들어오는 request의 IP 주소는 제한할 고유 키를 생성하는데 사용됩니다.
허용 된 request 등급은 다음 중 하나(선호도순)로 결정됩니다.
- 클래스의 `rate` property는 `AnonRateThrottle`을 오버라이드하고 property를 설정하여 제공 될 수 있다.
- `DEFAULT_THROTTLE_RATES ['anon']` 설정입니다.
`AnonRateThrottle`는 알 수 없는 출처에서의 request의 빈도수를 제한하려는 경우에 적합합니다.
### UserRateThrottle
`UserRateThrottle`은 API를 통해 주어진 request rate로 사용자를 제한합니다. user ID는 제한할 고유 키를 생성하는데 사용됩니다. 인증되지 않은 request는 들어오는 request의 IP 주소에 고유한 제한 키를 다시 생성하여 걸러냅니다.
허용 된 request rate는 다음 중 하나(선호도 순)로 결정됩니다.
- 클래스의 `rate`속성은 `UserRateThrottle`을 오버라이드하고 property를 설정하여 제공 될 수 있습니다.
- `DEFAULT_THROTTLE_RATES ['anon']` 설정입니다.
API에는 동시에 여러 `UserRAteThrottles`이 있을 수 있습니다. 이렇게 하려면 `UserRateThrottle`을 무시하고 각 클래스에 대해 고유한 `scope`(범위)를 설정하세요.
예를 들어, 여러 사용자 throttle rate는 다음 클래스를 사용하여 구현할 수 있습니다.
```python
class BurstRateThrottle(UserRateThrottle):
scope = 'burst'
class SustainedRateThrottle(UserRateThrottle):
scope = 'sustained'
```
...그리고 다음 설정입니다.
```python
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'burst': '60/min',
'sustained': '1000/day'
}
}
```
`UserRateThrottle`은 사용자별로 간단한 전역 rate를 원할 때 적합합니다.
### ScopedRateThrottle
`ScopeRateThrottle`클래스를 사용하여 API의 특정 부분에 대한 액서스를 제한 할 수 있습니다. 이 throttle은 액서스되는 뷰에 `.throttle_scope`속성이 포함 된 경우에만 적용됩니다. 고유한 throttle 키는 request의 "scope"를 고유한 user ID 또는 IP 주소와 연결하여 형성합니다.
허용 된 request rate는 request "scope"의 키를 사용하여 `DEFAULT_THROTTLE_RATES`설정에 의해 결정됩니다.
예를 들어, 다음의 뷰가 주어진 경우...
```python
class ContactListView(APIView):
throttle_scope = 'contacts'
...
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
```
...그리고 다음 설정입니다.
```python
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
```
`ContactListView` 또는 `ContactDetailView`에 대한 사용자 요청은 하루에 총 1000 개의 요청으로 제한됩니다. `UploadView`에 대한 사용자 요청은 하루에 20 건으로 제한됩니다.
## Custom throttles
custom throttle을 만들려면 `BaseThrottle`을 재정의하고 `.allow_request(self, request, view)`를 구현하십시오. 이 메소드는 요청을 허용해야하는 경우 `True`를 반환하고 그렇지 않으면 `False`를 반환해야합니다.
선택적으로 `.wait()` 메서드를 재정의 할 수도 있습니다. 구현 된 경우 `.wait()`는 다음 요청을 시도하기 전에 기다리는 권장 시간(초)을 반환하거나 `None`을 반환해야합니다. `.wait()` 메서드는 `.allow_request()`가 이전에 `False`를 반환 한 경우에만 호출됩니다.
`.wait()` 메서드가 구현되고 요청이 제한되면 `Retry-After` 헤더가 응답에 포함됩니다.
### Example
다음은 10의 요청마다 1을 무작위로 조절하는 rate throttle의 예입니다.
```python
import random
class RandomRateThrottle(throttling.BaseThrottle):
def allow_request(self, request, view):
return random.randint(1, 10) != 1
```

View File

@ -0,0 +1,272 @@
# Django REST Framework - Validators
---
_"Validators can be useful for re-using validation logic between different types of fields."_
_"유효성 검사기는 다른 유형의 필드간에 유효성 검사논리를 다시 사용하는데 유용할 수 있습니다."_
_— Django documentation_
---
## Validators(유효성 검사기)
대부분 REST 프레임워크에서 유효성 검사를 처리하는 경우 기본 필드 유효성 검사에 의존하거나 serializer 또는 필드 클래스에 대한 명시적인 `Validator` 메소드를 작성하기만 하면 됩니다.
그러나 때때로 유효성 검사 논리를 재사용 가능한 구성 요소에 배치하여 코드 베이스 전체에서 쉽게 재사용 할 수 있습니다. 이 작업은 Validator 함수와 Validators 클래스를 사용하여 수행할 수 있습니다.
### Validation in REST framework
Django의 REST 프레임워크 serializer의 validation는 Django의 `ModelForm`클래스에서 validation이 작동하는 방식과 조금 다르게 처리됩니다.
`ModelForm`을 사용하면 validation이 부분적으로 form에서 수행되고, 부분적으로 모델 인스턴스에서 수행됩니다. REST 프레임워크를 사용하면 validation은 전체적으로 serializer클래스에서 수행됩니다. 이는 다음과 같은 이유로 유리합니다.
- 적절한 구분을 제공하여 코드 동작을 보다 명확하게 만듭니다.
- shortcut `ModelSerializer`클래스를 사용하거나 명시적 serializer클래스를 사용하는 것은 쉽게 전환할 수 있습니다. `ModelSerializer`에 사용되는 모든 validation 동작은 복제가 간단합니다.
- serializer 인스턴스의 `repr`을 출력(print)하면 validation 규칙이 정확하게 표시됩니다. 모델 인스턴스에서 추가 숨겨진 validation 동작이 호출되지 않습니다.
`ModelSerializer`를 사용하면 모든 것이 자동으로 처리됩니다. 대신 Serializer클래스를 사용하여 드롭다운하려면 validation 규칙을 명시적으로 정의해야 합니다.
#### Example
REST 프레임워크가 명시적 validation을 사용하는 방법의 예로, 고유성 제약 조건이 있는 필드가 있는 간단한 모델 클래스를 사용합니다.
```python
class CustomerReportRecord(models.Model):
time_raised = models.DateTimeField(default=timezone.now, editable=False)
reference = models.CharField(unique=True, max_length=20)
description = models.TextField()
```
다음은 `CustomReportRecord`인스턴스를 생성하거나 업데이트할 때 사용할 수 있는 기본 `ModelSerializer`입니다.
```python
class CustomerReportSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerReportRecord
```
`manage.py` shell을 사용하여 Django shell을 열면 이제 할 수 있습니다.
```python
>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
id = IntegerField(label='ID', read_only=True)
time_raised = DateTimeField(read_only=True)
reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
description = CharField(style={'type': 'textarea'})
```
여기서 흥미로운 부분은 참조필드입니다. 고유성 제약이 serializer 필드의 validator에 의해 명시적으로 적용되고 있음을 알 수 있습니다.
더 명시적인 스타일 때문에 REST 프레임워크는 Django의 핵심에서 사용할 수 없는 몇가지 validator 클래스를 포함합니다. 이 클래스들은 아래에 자세히 설명되어 있습니다.
---
### UniqueValidator
validator를 사용하여 모델 필드에 `unique=True`제약 조건을 적용 할 수 있습니다. 하나의 필수 인수와 선택적 `massages` 인수를 취합니다.
- `queryset` (필수) : 유일성을 강요해야하는 queryset입니다.
- `massege` : 검증이 실패했을 경우 사용하는 에러 메세지
- `lookup` : 검증되고 있는 값을 가지고 기존의 인스턴스를 찾는데 사용합니다. 기본값은 `exact`입니다.
이 validator는 다음과 같이 serializer 필드에 적용되어야 합니다.
```python
from rest_framework.validators import UniqueValidator
slug = SlugField(
max_length=100,
validators=[UniqueValidator(queryset=BlogPost.objects.all())]
)
```
### UniqueTogetherValidator
이 validator를 사용하여 모델 인스턴스에 `unique_together`제약 조건을 적용할 수 있습니다. 여기에는 두 개의 필수 인수와 단일 선택적 `messages`인수가 있습니다.
- `queryset`(필수) : 유일성을 강요해야하는 queryset입니다.
- `fields`(필수) : 고유한 set을 만들어야 하는 필드이름의 list 또는 tuple. 이들은 serializer 클래스의 필드로 존재해야 합니다.
- `message` : 검증에 실패했을 경우 사용하는 에러 메세지
validator는 다음과 같이 serializer 클래스에 적용되어야 합니다.
```python
from rest_framework.validators import UniqueTogetherValidator
class ExampleSerializer(serializers.Serializer):
# ...
class Meta:
# ToDo items belong to a parent list, and have an ordering defined
# by the 'position' field. No two items in a given list may share
# the same position.
validators = [
UniqueTogetherValidator(
queryset=ToDoItem.objects.all(),
fields=('list', 'position')
)
]
```
---
**Note**: `UniqueTogetherValidation`클래스는 항상 적용되는 모든 필드가 항상 필요한 것으로 처리된다는 암시적 제약조건을 부과합니다. `default`가 있는 필드는 사용자 입력에서 생략 된 경우에도 항상 값을 제공하므로 예외입니다.
---
### UniqueForDateValidator
### UniqueForMonthValidator
### UniqueForYearValidator
이 validator는 모델 인스턴스에 대해 `unique_for_date`, `unique_for_month`, `unique_for_year` 제약조건을 적용하는데 사용할 수 있습니다.
- `queryset`(필수) : 유일성을 강요해야하는 queryset입니다.
- `field`(필수) : 지정된 날짜 범위의 고유성에 대한 필드 이름입니다. 이것은 serializer 클래스의 필드로 존재해야합니다.
- `date_field`(필수) : 고유성 제한 조건의 날짜 범위를 결정하는데 사용할 필드 이름입니다. 이것은 serializer클래스의 필드로 존재해야 합니다.
- `massege` : 검증이 실패했을 경우에 사용하는 에러 메세지
validator는 다음과 같이 serializer클래스에 적용되어야 합니다.
```python
from rest_framework.validators import UniqueForYearValidator
class ExampleSerializer(serializers.Serializer):
# ...
class Meta:
# Blog posts should have a slug that is unique for the current year.
validators = [
UniqueForYearValidator(
queryset=BlogPostItem.objects.all(),
field='slug',
date_field='published'
)
]
```
validation에 사용되는 날짜 필드는 항상 serializer클래스에 있어야 합니다. validation이 실행될 때까지 기본값에 사용되는 값이 생성되지 않기 때문에 모델 클래스 `default=...`에 의존할 수 없습니다.
API를 어떻게 동작시키는지에 따라 이 스타일을 사용할 수 있는 스타일이 몇가지 있습니다. `ModelSerializer`를 사용하는 경우 REST 프레임워크에서 생성하는 기본값을 사용하는 것이 좋지만 serializer를 사용하거나 보다 명시적인 제어를 원한다면 아래에 설명된 스타일을 사용하세요.
#### Using with a writable date field. (쓰기 가능한 날짜 필드와 함께 사용하기)
날짜 필드를 쓰기 가능하게하려면, 기본 인수를 설정하거나 `required=True`를 설정하여 입력 데이터에서 항상 사용할 수 있도록 해야합니다.
```
published = serializers.DateTimeField(required=True)
```
#### Using with a read-only date field. (읽기 전용 날짜 필드와 함께 사용하기)
사용자가 날짜 필드를 볼 수는 있지만 편집할 수도 없도록 하려면 `read_only=True`로 설정하고 추가로 `default=...`인수를 설정하십시오.
```
published = serializers.DateTimeField(read_only=True, default=timezone.now)
```
필드는 사용자에게 쓸 수 없지만 기본값은 여전히 `validated_data`로 전달됩니다.
#### Using with a hidden date field. (숨겨진 날짜 필드와 함께 사용하기)
사용자가 날짜 필드를 완전히 숨기려면 `HiddenField`를 사용하세요. 이 필드 타입은 사용자 입력을 허용하지 않고 대신 항상 기본값을 serializer의 `validated_data`로 반환합니다.
```
published = serializers.HiddenField(default=timezone.now)
```
---
**Note**: `UniqueFor<Range>Validation`클래스는 적용되는 필드가 항상 필요한 것으로 처리된다는 암시적 제약조건을 적용합니다. `default`가 있는 필드는 사용자 입력에서 생략된 경우에도 항상 값을 제공하므로 예외입니다.
---
## Advanced field defaults
serializer의 여러 필드에 적용되는 valistor는 API 클라이언트가 제공해서는 안되지만 validator의 입력으로 사용할 수 있는 필드 입력이 필요할 수 있습니다.
이러한 유형의 validation에 사용할 수 있는 두가지 패턴은 다음과 같습니다.
- `HiddenField`를 사용하는 것입니다. 이 필드는 `validated_data`에 있지만 serializer 출력 표현에서는 사용되지 않습니다.
- `read_only=True`와 함께 표준 필드는 사용하지만 `default=...`인수도 포함합니다. 이 필드는 serializer 출력 표현에 사용되지만 사용자가 직접 설정할 수는 없습니다.
REST 프레임워크는 이 컨텍스트에서 유용 할 수 있는 몇 가지 기본값을 포함합니다.
### CurrentUserDefault
현재 사용자를 나타내는데 사용할 수 있는 기본 클래스입니다. 이것을 사용하기 위해서는, serializer를 인스턴스화 할때 `request`가 컨텍스트 dict의 일부로 제공되어야 합니다.
```python
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
```
### CreateOnlyDefault
작성 조작 중 default의 인수만을 설정하는데 사용할 수 있는 기본 클래스. 업데이트 중 필드는 생략됩니다.
이것은 작성 작업중에 사용되는 기본값이거나 호출 가능한 단일 인수를 취합니다.
```python
created_at = serializers.DateTimeField(
read_only=True,
default=serializers.CreateOnlyDefault(timezone.now)
)
```
---
## Limitations of validators
`ModelSerializer`이 생성하는 기본 serializer 클래스를 사용하는 대신 validation을 명시적으로 처리해야하는 모호한 경우가 있습니다.
이러한 경우 serializerz `Meta.valisators`속성에 대한 빈 목록을 지정하여 자동 생성 된 validator를 사용하지 않도록 설정할 수 있습니다.
### Optional fields
기본적으로 "unique together"validation는 모든 필드가 `required=True`인지 확인합니다. 경우에 따라 필드 중 하나에 명시적으로 `required=False`를 적용하면 원하는 validation 동작이 모호할 수 있습니다.
이 경우 일반적으로 serializer 클래스에서 validator를 제외하고, `.validate()`메서드나 뷰에서 validation 논리를 명시적으로 작성해야합니다.
예를 들어:
```python
class BillingRecordSerializer(serializers.ModelSerializer):
def validate(self, data):
# Apply custom validation either here, or in the view.
class Meta:
fields = ('client', 'date', 'amount')
extra_kwargs = {'client': {'required': 'False'}}
validators = [] # Remove a default "unique together" constraint.
```
### Updating nested serializers
기존 인스턴스에 업데이트를 적용할 때 고유성 validator는 현재 인스턴스를 고유성 검사에서 제외합니다. 현재 인스턴스는 고유성 검사의 컨텍스트에서 사용 할 수 있습니다. 이 속성은 serializer의 속성으로 존재하기 때문에 처음에는 serializer를 인스턴스화 할때 `instance=...`를 사용하여 전달되었습니다.
중첩 된 serializer에 대한 업데이트 작업의 경우 인스턴스를 사용할 수 없으므로 이 배제를 적용할 방법이 없습니다.
다시 말하면, serializer클래스에서 validator를 명시적으로 제거하고 validation 제약 조건에 대한 코드를 명시적으로 `.validate()`메서드나 뷰에 작성하려고 합니다.
### Debugging complex cases
`ModelSerializer` 클래스가 어떤 동작을 하는지 확실히 모를 경우 `manage.py` 셸을 실행하고 serializer의 인스턴스를 인쇄하면 자동으로 생성되는 필드와 validator를 검사 할 수 있습니다.
```python
>>> serializer = MyComplexModelSerializer()
>>> print(serializer)
class MyComplexModelSerializer:
my_fields = ...
```
또한 복잡한 경우에는 기본 `ModelSerializer` 동작을 사용하는 대신 serializer 클래스를 명시적으로 정의하는 것이 더 나을 수 있습니다.
---
## Writing custom validators
Django의 기존 validator를 사용하거나 custom validator를 작성할 수 있습니다.
### Function based
validator는 아마도 실패하면 `serializer.ValidationError`를 발생시켜 호출합니다.
```python
def even_number(value):
if value % 2 != 0:
raise serializers.ValidationError('This field must be an even number.')
```
#### Field-level validation
Serializer 서브 클래스에 `.validate_<field_name>` 메소드를 추가하여 custom 필드 레벨 vallidation을 지정 할 수 있습니다.
### Class-based
클래스 기반 validator를 작성하려면 `__call__`메서드를 사용하세요. 클래스 기반 validator는 동작을 매개 변수화하고 다시 사용할 수 있으므로 유용합니다.
```python
class MultipleOf(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if value % self.base != 0:
message = 'This field must be a multiple of %d.' % self.base
raise serializers.ValidationError(message)
```
#### Using `set_context()`
일부 고급 예제에서는 validator를 추가 컴텍스트로 사용되는 serializer 필드로 전달해야 할 수 있습니다. 클래스 기반의 validator에서 `set_context`메서드를 선언하여 그렇게 할 수 있습니다.
```python
def set_context(self, serializer_field):
# Determine if this is an update or a create operation.
# In `__call__` we can then use that information to modify the validation behavior.
self.is_update = serializer_field.parent.instance is not None
```

View File

@ -0,0 +1,217 @@
# Django REST Framework - Versioning
---
_"Versioning an interface is just a "polite" way to kill deployed clients."_
_"인터페이스의 버전 관리는 배치 된 클라이언트를 죽이는 "정중한" 방법 일 뿐입니다."_
_— Roy Fielding._
---
## Versioning (버전관리)
API 버전 관리를 통해 서로 다른 클라이언트 간의 동작을 변경할 수 있습니다. REST 프레임워크는 다양한 버전 관리 체계를 제공합니다.
버전 지정은 수신 클라이언트 요청에 의해 결정되며 request URL을 기반으로하거나 request 헤더를 기반으로 할 수 있습니다.
버전 관리에 접근하는데는 여러가지 유효한 방법이 있습니다. 특히 버전을 벗어난 여러 클라이언트를 가진 매우 장기적인 시스템을 엔지니어링하는 경우에는 [버전이 없는 시스템도 적합](https://www.infoq.com/articles/roy-fielding-on-versioning)할 수 있습니다.
### Versioning with REST framework
API 버전 관리가 활성화되면 `request.version`속성에는 들어오는 클라이언트 request에서 요청 된 버전에 해당하는 문자열이 포함됩니다.
기본적으로 버전 관리는 활성화되어있지 않으며 `request.version`은 항상 `None`을 반환합니다.
#### Varying behavior based on the version
API동작을 변경하는 방법은 우리에게 달려있지만 일반적인 한가지 예는 최신 버전의 다른 serializer 스타일로 전환하는 것입니다. 예:
```python
def get_serializer_class(self):
if self.request.version == 'v1':
return AccountSerializerVersion1
return AccountSerializer
```
#### Reversing URLs for versioned APIs
REST 프레임워크에 포함 된 역순 함수는 버전 관리체계와 관련되어 있습니다. 현재 request를 키워드 인수로 포함시켜야 합니다.
```python
from rest_framework.reverse import reverse
reverse('bookings-list', request=request)
```
위의 함수는 요청 버전에 적합한 모든 URL 변환을 적용합니다. 예:
- `NamespacedVersioning`이 사용되고 API 버전이 'v1'인 경우 사용 된 URL 조회는 `http://example.org/v1/bookings/`과 같은 URL로 해석 될 수있는 `'v1 : bookings-list'`입니다.
- `QueryParameterVersioning`이 사용되고 API 버전이 `1.0` 인 경우 반환 된 URL은 `http://example.org/bookings/?version=1.0`과 같을 수 있습니다.
#### Versioned APIs and hyperlinked serializers
하이퍼 링크 된 serializer 스타일을 URL 기반 버전 관리 scheme와 함께 사용하는 경우 해당 요청을 컨텍스트로 serializer에 포함해야 합니다.
```python
def get(self, request):
queryset = Booking.objects.all()
serializer = BookingsSerializer(queryset, many=True, context={'request': request})
return Response({'all_bookings': serializer.data})
```
이렇게 하면 반환 된 모든 URL에 적절한 버전이 포함될 수 있습니다.
### Configuring the versioning scheme
버전 관리 scheme는 `DEFAULT_VERSIONING_CLASS`설정 키로 정의됩니다.
```python
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
```
명시적으로 설정하지 않으면 `DEFAULT_VERSIONING_CLASS`의 값은 `None`이 됩니다. 이 경우 `request.version` 속성은 항상 `None`을 반환합니다.
개별 view에서 versioning scheme를 설정할 수도 있습니다. 일반적으로 전역적으로 single versioning scheme를 사용하는 것이 더 합리적이므로 이 작업을 수행할 필요가 없습니다. 그렇게 해야한다면 `versioning_class` 속성을 사용하세요.
```python
class ProfileList(APIView):
versioning_class = versioning.QueryParameterVersioning
```
#### Other versioning settings
다음 설정 키는 versioning를 제어하는데도 사용됩니다.
- `DEFAULT_VERSION` : 버전 정보가 없는 경우 `request.version`에 사용해야 하는 값입니다. 기본값은 `None`입니다.
- `ALLOWED_VERSIONS` : 이 값을 설정하면 versioning scheme에서 반환 할 수 있는 버전 집합이 제한되며 제공된 버전이 이 집합에 없는 경우 오류가 발생합니다. `DEFAULT_VERSION` 설정에 사용 된 값은 항상 `ALLOWED_VERSIONS` set의 일부로 간주됩니다 (단, `None`이 아닌 경우). 기본값은 `None`입니다.
- `VERSION_PARAM` : 미디어 유형 또는 URL 쿼리 parameter와 같이 모든 버전 지정 parameter에 사용해야하는 문자열입니다. 기본값은 `'version'`입니다.
또한 고유한 versioning scheme를 정의하고 `default_version`, `allowed_version``version_param`클래스 변수를 사용하여 버전 별 또는 뷰 set 별로 세 가지 값을 더한 버전 클래스를 설정할 수 있습니다. 예를 들어, `URLPathVersioning`를 사용하려면 다음과 같이 하십시오.
```python
from rest_framework.versioning import URLPathVersioning
from rest_framework.views import APIView
class ExampleVersioning(URLPathVersioning):
default_version = ...
allowed_versions = ...
version_param = ...
class ExampleView(APIVIew):
versioning_class = ExampleVersioning
```
---
## API Reference
### AcceptHeaderVersioning
이 scheme는 클라이언트가 `Accept` 헤더의 미디어 타입의 일부로 버전을 지정하도록 요구합니다. 이 버전은 기본 미디어 타입을 보완하는 미디어 타입 parameter로 포함됩니다.
다음 accept 헤더 versioning 스타일을 사용하는 HTTP request의 예입니다.
```
GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0
```
위의 예제 request에서 `request.version`속성은 `'1.0'`문자열을 반환합니다.
Accept 헤더에 기반한 versioning는 [일반적](http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http#i_want_my_api_to_be_versioned)으로 [모범 사례](https://github.com/interagent/http-api-design/blob/master/en/foundations/require-versioning-in-the-accepts-header.md)로 간주되지만 클라이언트 요구 사항에 따라 다른 스타일이 적합할 수도 있습니다.
#### Using accept headers with vendor media types
엄밀히 말하자면 `json` 미디어 타입은 [추가 parameter](http://tools.ietf.org/html/rfc4627#section-6)를 포함하는 것으로 지정되지 않습니다. 잘 정의 된 공개 API를 작성하는 경우 [vendor media type](https://en.wikipedia.org/wiki/Internet_media_type#Vendor_tree)을 사용하는 것이 좋습니다. 이렇게 하려면 custom 미디어 타입으로 `JSON` 기반 렌더러를 사용하도록 렌더러를 구성하세요.
```python
class BookingsAPIRenderer(JSONRenderer):
media_type = 'application/vnd.megacorp.bookings+json'
```
클라이언트의 request는 다음과 같습니다.
```
GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/vnd.megacorp.bookings+json; version=1.0
```
### URLPathVersioning
이 스키마는 클라이언트가 URL 경로의 일부로 버전을 지정하도록 요구합니다.
```
GET /v1/bookings/ HTTP/1.1
Host: example.com
Accept: application/json
```
URL conf에는 `'version'`키워드 인수가 있는 버전과 일치하는 패턴이 포함되어야하므로 이 정보를 versioning scheme에서 사용할 수 있습니다.
```python
urlpatterns = [
url(
r'^(?P<version>(v1|v2))/bookings/$',
bookings_list,
name='bookings-list'
),
url(
r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
bookings_detail,
name='bookings-detail'
)
]
```
### NamespaceVersioning
클라이언트에서 이 scheme는 `URLPathVersioning`과 동일합니다. 유일한 차이점은 URL 키워드 인수 대신 URL 네임스페이스를 사용하므로 Django 애플리케이션에서 어떻게 구성되어 있는지입니다.
```
GET /v1/something/ HTTP/1.1
Host: example.com
Accept: application/json
```
이 scheme에서 `request.version`속성은 틀어오는 request 경로와 일치하는 네임스페이스를 기반으로 결정됩니다.
다음 예제에서는 서로 다른 네임 스페이스 아래에 각각 다른 두가지 URL 접두어가 있는 일련의 view를 제공합니다.
```python
# bookings/urls.py
urlpatterns = [
url(r'^$', bookings_list, name='bookings-list'),
url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
]
# urls.py
urlpatterns = [
url(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
url(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
]
```
간단한 versioning scheme가 필요하다면 `URLPathVersioning``NamespaceVersioning` 모두 합리적입니다.
### HostNameVersioning
hostname versioning scheme에서는 클라이어튼가 요청된 버전을 URL의 hostname의 일부로 지정해야합니다.
예를 들어 다음은 `http://v1.example.com/bookings/` URL에 대한 HTTP 요청입니다.
```
GET /bookings/ HTTP/1.1
Host: v1.example.com
Accept: application/json
```
기본적으로 이 구현은 hostname이 다음과 같은 간단한 정규식과 일치 할 것으로 기대합니다.
```
^([a-zA-Z0-9]+)\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$
```
첫 번째 그룹은 대괄호로 묶여 있으며 hostname의 일치하는 부분임을 나타냅니다.
일반적으로 `127.0.0.1`과 같은 기존 IP주소에 액서스하므로 `HostNameVersioning` scheme는 디버그 모드에서 사용하기가 어려울 수 있습니다. 이 경우 도움이 될 수 있는 [`custom subdomain`으로 localhost에 액서스](https://reinteractive.com/posts/199-developing-and-testing-rails-applications-with-subdomains)하는 다양한 온라인 서비스가 있습니다.
hostname versioning scheme는 여러 API 버전에 대해 서로 다른 DNS 레코드를 구성할 수 있으므로 들어오는 request를 버전에 따라 다른 서버로 라우팅해야하는 경우에 특히 유용합니다.
### QueryParameterVersioning
이 스키마는 URL에 쿼리 parameter로 버전을 포함하는 간단한 스타일입니다. 예:
```
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
```
---
## Custom versioning schemes
custom versioning scheme를 구현하려면 `BaseVersioning`를 서브 클래스화하고 `.determine_version`메서드를 대체하세요.
### Example
다음 예에서는 custom `X-API-Version` 헤거를 사용하여 요청한 버전을 확인합니다.
```python
class XAPIVersionScheme(versioning.BaseVersioning):
def determine_version(self, request, *args, **kwargs):
return request.META.get('HTTP_X_API_VERSION', None)
```
versioning scheme가 request URL을 기반으로 하는 경우 버전이 지정된 URL의 결정 방법도 변경해야합니다. 이렇게 하려면 클래스의 `.reverse()`메서드를 오버라이드해야합니다. 예제는 소스코드를 참조하세요.

View File

@ -0,0 +1,250 @@
# Django REST Framework - ViewSets
---
_"After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output."_
_"라우팅에서 request에 사용할 컨트롤러를 결정한 후에 컨트롤러는 request를 이해하고 적절한 출력을 생성해야합니다."_
_— Ruby on Rails Documentation_
---
## ViewSets
Django REST 프레임워크를 사용하면 `ViewSet`이라고하는 단일 클래스에서 `ViewSet`에 대한 논리를 결합할 수 있습니다. 다른 프레임워크에서는 `Resources``Controllers`와 같은 개념적으로 유사한 구현을 찾을 수도 있습니다.
`ViewSet` 클래스는 단순히 `.get()`이나 `.post()`과 같은 메소드 핸들러를 제공하지 않고 CBV 유형이며, 대신 `.list()``.create()`와 같은 액션을 제공합니다.
`ViewSet`의 메서드 핸들러는 `.as_view()`메서드를 사용하여 뷰를 마무리하는 시점의 해당 액션에만 바인딩됩니다.
>바인딩 : 각종 값들이 확정되어 더이상 변경 할 수 없는 상태가 되는것. 식별자(identifier)가 그 대상인 메모리 주소, 데이터형 또는 실제값으로 배정되는 것
일반적으로 urlconf의 viewset에 뷰를 명시적을 등록하는 대신 viewset을 `router`클래스로 등록하면 자동으로 urlconf가 결정됩니다.
### Example
시스템의 모든 사용자를 나열하거나 검색하는데 사용 할 수 있는 간단한 viewset을 정의합시다.
```python
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response
class UserViewSet(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
```
필요한 경우 이 viewset을 다음과 같이 두 개의 개별 뷰 바인딩 할 수 있습니다.
```python
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
```
평소엔 우리는 이것을 하지 않을 것이지만, 대신 viewset을 라우터에 등록하고 urlconf가 자동으로 생성되도록 할 것입니다.
```python
from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = router.urls
```
자신만의 viewset를 작성하는 대신, 기본 동작 set을 제공하는 기존 기본 클래스를 사용하는 것이 좋습니다. 예를 들어:
```python
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
serializer_class = UserSerializer
queryset = User.objects.all()
```
`View` 클래스를 사용하는 것보다 `ViewSet`클래스를 사용하는 두 가지 주요 이점이 있습니다.
- 반복 논리를 하나의 클래스로 결합 할 수 있습니다. 위의 예에서 쿼리셋은 한번만 지정하면 여러 view에서 사용됩니다.
- router를 사용함으로써 우리는 더 이상 URLconf의 연결을 처리 할 필요가 없습니다.
이 두가지 모두 장단점이 있습니다. 일반 views와 URL conf를 사용하면 보다 명확하게 제어할 수 있습니다. `ViewSet`는 신속하게 시작하고 실행하려는 경우, 또는 대규모 API가 있고 전체적으로 일관된 URL conf를 적용하려는 경우 유용합니다.
### Marking extra actions for routing
REST 프레임워크에 포함 된 기본 router는 아래와 같이 `creste`/`retirieve`/`update`/`destroy` 스타일 작업의 기본 set을 위한 경로를 제공합니다.
```python
class UserViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass
```
라우팅해야 하는 임시 메소드가 있는 경우 `@detail_router``@list_router`데코레이터를 사용하여 라우팅을 요구하는 것으로 표시 할 수 있습니다.
`@detail_router`데코레이터는 URL 패턴에 `pk`를 포함하며 단일 인스턴스가 필요한 메소드용입니다. `@list_router`데코레이터는 객체 목록에서 작동하는 메소드를 대상으로 합니다.
예를 들어:
```python
from django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@detail_route(methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@list_route()
def recent_users(self, request):
recent_users = User.objects.all().order('-last_login')
page = self.paginate_queryset(recent_users)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(recent_users, many=True)
return Response(serializer.data)
```
데코레이터는 라우트 된 뷰에 대해서만 설정 할 추가 인수를 추가로 취할 수 있습니다. 예를 들어..
```python
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
```
이러한 데코레이터는 기본적으로 `GET` request를 라우트하지만 `methods`인수를 사용하여 다른 HTTP 메소드를 채택할 수도 있습니다. 예:
```python
@detail_route(methods=['post', 'delete'])
def unset_password(self, request, pk=None):
...
```
두 개의 작업은 `^users/{pk}/set_password/$``^users/{pk}/unset_password/$`에서 사용 할 수 있습니다.
---
## API Reference
### ViewSet
`ViewSet`클래스는 `APIView`에서 상속받습니다. viewset에 대한 API 정책을 제어하기 위해 `permission_classes`,`authentication_classes`와 같은 표준 속성을 사용할 수 있습니다.
`ViewSet` 클래스는 액션의 구현을 제공하지 않습니다. `ViewSet` 클래스를 사용하려면 클래스를 오버라이트하고 액션 구현을 명시적으로 정의해야합니다.
### GenericViewSet
`GenericViewSet`클래스는 `GenericAPIView`에서 상속되며, `get_object`, `get_queryset`메소드와 그 외 `generic view`의 기본 동작의 기본 set을 제공하지만, 기본적으로 어떤 액션도 포함하지 않습니다.
`GenericViewSet`클래스를 사용하려면 클래스를 재정의하고 필요한 `mixin`클래스를 혼합하거나 액션 구현을 명시적으로 정의하세요.
### ModelViewSet
`ModelViewSet`클래스는 `GenericAPIView`를 상속하며, 다양한 `mixin`클래스의 동작을 혼합하여 다양한 액션에 대한 구현을 포함합니다.
`ModelViewSet`클래스에서 제공하는 작업은 `.list()`, `.retrieve()`, `.create()`, `.update()`, `.partial_update()`, `.destroy()`입니다.
#### Example
`ModelViewSet``GenericAPIView`를 확장하기 때문에 일반적으로 적어도 `queryset``serializer_class` 속성을 제공해야 합니다. 예:
```python
class AccountViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for viewing and editing accounts.
"""
queryset = Account.objects.all()
serializer_class = AccountSerializer
permission_classes = [IsAccountAdminOrReadOnly]
```
`GenericAPIView`가 제공하는 표준 속성이나 메소드 오버라이드를 사용할 수 있습니다. 예를 들어, 작동해야하는 쿼리셋을 동적으로 결정하는 viewset을 사용하려면 다음과 같이 할 수 있습니다.
```python
class AccountViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for viewing and editing the accounts
associated with the user.
"""
serializer_class = AccountSerializer
permission_classes = [IsAccountAdminOrReadOnly]
def get_queryset(self):
return self.request.user.accounts.all()
```
그러나 `ViewSet`에서 `queryset` 속성을 제거하면 연관된 [라우터](http://www.django-rest-framework.org/api-guide/routers/)가 모델의 `base_name`을 자동으로 파생시킬 수 없으므로 [라우터 등록](http://www.django-rest-framework.org/api-guide/routers/)의 일부로 `base_name kwarg`를 지정해야합니다.
또한 이 클래스는 기본적으로 `create`/`list`/`retrieve`/`update`/`destroy` 액션의 전체 set을 제공하지만 표준 권한 클래스를 사용하여 사용 가능한 작업을 제한할 수 있습니다.
### ReadOnlyModelViewSet
`ReadOnlyModelViewSet`클래스 또한 `GenericAPIView`에서 상속받습니다. `ModelViewSet`과 마찬가지로 다양한 액션에 대한 구현도 포함되지만 `ModelViewSet`과 달리 **일기 전용**동작인 `.list()`, `.retrieve()`만 제공됩니다.
#### Example
`ModelViewSet`에서와 같이 일반적으로 적어도 `queryset``serializer_class`속성을 제공해야 합니다. 예:
```python
class AccountViewSet(viewsets.ReadOnlyModelViewSet):
"""
A simple ViewSet for viewing accounts.
"""
queryset = Account.objects.all()
serializer_class = AccountSerializer
```
`ModelViewSet`과 마찬가지로 `GenericAPIView`에서 사용할 수 있는 표준 속성과 메소드 오버라이드를 사용할 수 있습니다.
## Custom ViewSet base classes
`ModelViewSet` 액션의 전체 set이 없거나 다른 방식으로 동작을 사용자 정의하는 custom `ViewSet`클래스를 제공해야 할 수도 있습니다.
### Example
`create`, `list`, `retrieve` 조작을 제공하고, `GenericViewSet`에서 상속하며, 필요한 조치를 `mixin`하는 기본 viewset를 작성하려면 다음을 작성하세요.
```python
class CreateListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
"""
`retrieve`, `create`, `list` actions을 제공하는 viewset입니다.
이것들을 사용하려면 클래스와 `.queryset`
`.serializer_class`의 속성을 오버라이드하세요.
"""
pass
```
고유한 기본 `ViewSet`클래스를 작성하여 API 전반에 걸쳐 여러 viewset에서 재사용 할 수 있는 공통적인 동작을 제공할 수 있습니다.

View File

@ -0,0 +1,156 @@
# Django REST Framework - Views
---
_"Django's class-based views are a welcome departure from the old-style views."_
_"Django의 CBV는 구식 뷰에서 출발하는 것을 환영합니다."_
_— Reinout van Rees_
---
## Class-based Views
REST 프레임워크는 Django의 `View` 클래스를 하위 클래스로 하는 `APIView`클래스를 제공합니다.
`APIView`클래스는 다음과 같은 방식으로 일반 `View`클래스와 다릅니다.
- 핸들러 메서드에 전달 된 `Request`는 Django의 `HttpRequest` 인스턴스가 아닌 REST 프레임워크의 `request`인스턴스가 됩니다.
- 핸들러 메서드는 Django의 `HttpResponse` 대신 REST 프레임워크의 `Response`를 반환 할 수 있습니다. 뷰는 콘텐츠 협상을 관리하고 `response`에서 올바른 렌더러를 설정합니다.
- 모든 `APIException` 예외가 발견되면 적절한 `response`으로 조정됩니다.
- 들어오는 request가 인증이 된 request를 핸들러 메서드에 보내기 전에 적절한 권한과 `/` 또는 `throttle(제한)` 체크를 실행합니다.
`APIView` 클래스를 사용하는 것은 일반 `View`클래스를 사용하는 것과 거의 같습니다. 들어오는 request은 `.get()`이나 `.post()`와 같은 적절한 핸들러 메서드로 전달됩니다. 또한 API 정책의 다양한 측면을 제어하는 여러 속성을 클래스에 설정 할 수 있습니다.
예를 들어:
```python
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
class ListUsers(APIView):
"""
View to list all users in the system.
* 토큰 인증이 필요합니다.
* 관리자만 view에 액서스 할 수 있습니다.
"""
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAdminUser,)
def get(self, request, format=None):
"""
모든 사용자 리스트를 반환합니다.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
```
### API policy attributes(API 정책 속성)
다음 속성들은 API view의 플러그 가능한 부분을 제어합니다.
`.renderer_classes`
`.parser_classes`
`.authentication_classes`
`.throttle_classes`
`.permission_classes`
`.content_negotiation_class`
### API policy instantiation methods(API 정책 인스턴스화 메서드)
다음 메서드들은 REST 프레임워크에서 다양한 플러그가 가능한 API 정책을 인스턴스화하는데 사용됩니다. 일반적으로 이러한 메서드를 재정의 할 필요는 없습니다.
`.get_renderers(self)`
`.get_parsers(self)`
`.get_authenticators(self)`
`.get_throttles(self)`
`.get_permissions(self)`
`.get_content_negotiator(self)`
`.get_exception_handler(self)`
### API policy implementation methods(API 정책 구현 방법)
다음 메서드는 핸들러 메서드에 전달하기 전에 호출됩니다.
`.check_permissions(self, request)`
`.check_throttles(self, request)`
`.perform_content_negotiation(self, request, force=False)`
### Dispatch methods (파견 메서드)
다음 메서드는 뷰의 `.dispatch()`메서드에 의해 직접 호출됩니다. 이 메서드들은 `.get()`, `.post()`, `put()`, `patch()``.delete()`와 같은 핸들러 메서드들을 호출하기 전후에 수행되어야하는 모든 조치들을 수행합니다.
#### `.initial(self, request, *args, **kwargs)`
핸들러 메서드가 호출되기 전에 발생해야하는 모든 작업을 수행합니다. 이 메서드는 사용 권한 및 제한을 적용하고 콘텐츠 협상을 수행하는데 사용됩니다.
일반적으로 이 메서드를 재정의 할 필요는 없습니다.
#### `.handle_exception(self, exc)`
핸들러 메서드에 의해 버려진 예외는 `Resopnse`인스턴스를 반환하거나 예외를 다시 발생시키는 이 메서드로 전달됩니다.
기본 구현에서는 Django의 `Http404``PermissionDenied`예외 뿐만 아니라 `rest_framework.exceptions.APIXeception`의 하위 클래스를 처리하고 적절한 오류 response를 반환합니다.
API에서 반환하는 오류 response를 사용자 정의해야하는 경우 이 메소드를 서브 클래스화해야 합니다.
#### `.initialize_request(self, request, *args, **kwargs)`
핸들러 메소드에 전달 된 request 객체가 일반적인 Django `HttpRequest`가 아닌 `Request`의 인스턴스인지 확인합니다.
일반적으로 이 메서드를 재정의 할 필요는 없습니다.
#### `.finalize_response(self, request, response, *args, **kwargs)`
핸들러 메서드에서 반환 된 모든 `Response`객체가 내용 협상에 의해 결정된 대로 올바른 내용 유형으로 렌더링되도록 합니다.
일반적으로 이 메서드는 재정의 할 필요는 없습니다.
---
### Function Based Views
_"Saying [that class-based views] is always the superior solution is a mistake."_
_"[그 클래스 기반의 견해]가 항상 우월한 해결책은 실수라고 말하는 것입니다."_
_— Nick Coghlan_
REST 프레임워크를 사용하면 일반 FBV로 작업 할 수 있습니다. 그것은 간단한 Django `HttpRequest`가 아닌 `Request`의 인스턴스를 수신하고 Django `HttpResponse` 대신 `response`을 리턴 할 수 있도록 FBV를 래핑하는 간단한 데코레이터 세트를 제공하며, request가 처리됩니다.
### @api_view()
**Signature**: `@api_view(http_method_names=['GET'], exclude_from_schema=False)`
이 기능의 핵심은 `api_view`데코레이터(뷰가 응답해야하는 HTTP 메서드 리스트를 사용함)입니다. 예를 들어, 다음은 몇 가지 데이터를 수동으로 반환하는 아주 간단한 view를 작성하는 방법입니다.
```python
from rest_framework.decorators import api_view
@api_view()
def hello_world(request):
return Response({"message": "Hello, world!"})
```
이 뷰는 [설정](http://www.django-rest-framework.org/api-guide/settings/)에 지정된 기본 렌더러, 파서, 인증 클래스 등을 사용합니다.
기본적으로 `GET`메서드만 허용됩니다. 다른 메서드들은 "405 Method Not Allowed"로 응답합니다. 이 동작을 변경하려면 view에서 허용하는 방법을 지정하세요.
```python
@api_view(['GET', 'POST'])
def hello_world(request):
if request.method == 'POST':
return Response({"message": "Got some data!", "data": request.data})
return Response({"message": "Hello, world!"})
```
`exclude_from_schema`인수를 사용하여 API 뷰를 [자동 생성 스키마(auto-generated schema)](http://www.django-rest-framework.org/api-guide/schemas/)에서 생략된 것으로 표시 할 수도 있습니다.
```python
@api_view(['GET'], exclude_from_schema=True)
def api_docs(request):
...
```
### API policy decorators
기본 설정을 재정의하기 위해 REST 프레임워크는 뷰에 추가 할 수 있는 일련의 추가 데코레이터를 제공합니다. 이들은 `@api_view`데코레이터 다음에 와야합니다. 예를 들어, [`throttle`](http://www.django-rest-framework.org/api-guide/throttling/)을 사용하여 특정 사용자가 하루에 한번만 호출 할 수 있도록 뷰를 만들려면 `@thottle_classes`데코레이터를 사용하여 `throttle` 클래스 목록을 전달하세요.
```python
from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle
class OncePerDayUserThrottle(UserRateThrottle):
rate = '1/day'
@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
return Response({"message": "Hello for today! See you tomorrow!"})
```
이러한 데코레이터는 위에서 설명한 `APIView`하위 클래스에 설정된 특성에 해당합니다. 사용 가능한 데코레이터는 다음과 같습니다.
- `@renderer_classes(...)`
- `@parser_classes(...)`
- `@authentication_classes(...)`
- `@throttle_classes(...)`
- `@permission_classes(...)`
이러한 데코레이터 각각은 클래스의 `list``tuple`인 단일 인수를 취합니다.

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

View File

@ -0,0 +1,35 @@
![](images/logo.png)
# Django REST Framework Docs - 한국어 버전
DRF(Django REST Framework)의 공식문서를 한국어로 번역하였습니다.
## API 가이드
API 가이드는 REST 프레임워크에서 제공하는 모든 기능에 대한 완벽한 설명서입니다.
- [Requests](Requests.md)
- [Responses](Responses.md)
- [Views](Views.md)
- [Generic views](Generic_views.md)
- [Viewsets](ViewSets.md)
- [Routers](Routers.md)
- [Parsers](Parsers.md)
- [Renderers](Renderers.md)
- [Serializers](Serializers.md)
- [Serializer fields](Serializer_fields.md)
- [Serializer relations](Serializer_relations.md)
- [Validators](Validators.md)
- [Authentication](Authentication.md)
- [Permissions](Permissions.md)
- [Throttling](Throttling.md)
- [Filtering](Filtering.md)
- [Pagination](Pagination.md)
- [Versioning](Versioning.md)
- [Content negotiation](Content_negotiation.md)
- [Metadata](Metadata.md)
- [Schemas](Schemas.md)
- [Format suffixes](Format_suffixes.md)
- [Returning URLs](Returning_URLs.md)
- [Exceptions](Exceptions.md)
- [Status codes](Status_Codes.md)
- [Testing](Testing.md)
- [Settings](Settings.md)