Skip to content

Commit

Permalink
Merge pull request #2 from phin09/feature/api-documentation
Browse files Browse the repository at this point in the history
CREATE: API document with endpoint /swagger
  • Loading branch information
phin09 committed Apr 25, 2021
2 parents e481083 + 1ab3944 commit 1662016
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 31 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
- models.py에 맞게 ERD 수정.
2. 4/24
- [drf-yasg](https://github.com/axnsan12/drf-yasg)를 사용해 API 문서화 시도.
3. 4.25
- [drf-yasg](https://github.com/axnsan12/drf-yasg)를 사용해 Swagger UI 기반 기존 API 문서화 완료. 엔드포인트 '/swagger'

## Reference
> 이 프로젝트는 스타일쉐어 사이트를 참조하여 학습목적으로 만들었습니다.
Expand Down
22 changes: 18 additions & 4 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
# Application definition

INSTALLED_APPS = [
# 'django.contrib.admin',
# 'django.contrib.auth',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'drf_yasg',
'corsheaders',
'user',
'feed',
Expand All @@ -38,8 +40,8 @@
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
Expand Down Expand Up @@ -136,3 +138,15 @@
'x-csrftoken',
'x-requested-with',
)

# drf-yasg
# let swagger authorization accepts token
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'API Token': {
'type': 'apiKey',
'in': 'header',
'name': 'Authorization'
}
},
}
29 changes: 26 additions & 3 deletions config/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
from django.urls import path, include
from django.conf.urls import url

from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

urlpatterns = [
path('user', include('user.urls')),
path('feed', include('feed.urls')),
path('product', include('product.urls'))
path('user', include('user.urls')),
path('feed', include('feed.urls')),
path('product', include('product.urls')),
]

# api documentation: drf-yasg 사용.
# 이를 위해 settings.py INSTALLED_APPS에 rest_framework와 drf_yasg를 추가하고
# django.contrib.admin와 django.contrib.auth 주석을 해제함.
schema_view = get_schema_view(
openapi.Info(
title="style-we API",
default_version='v1.0.0',
description="style-we project API document",
),
validators=['flex'],
public=True,
permission_classes=[permissions.AllowAny],
)

urlpatterns += [
url(r'^swagger$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]
38 changes: 28 additions & 10 deletions feed/views.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import json, jwt
from json.decoder import JSONDecodeError
import json
import jwt
from json.decoder import JSONDecodeError

from django.views import View
from django.http import JsonResponse
from django.views import View
from django.http import JsonResponse

from user.utils import login_decorator, get_current_user_id
from user.models import User
from feed.models import Feed, ImageUrl, Comment
from product.models import Product, ProductImageUrl
from rest_framework.views import APIView
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema

class FeedView(View):
from user.utils import login_decorator, get_current_user_id
from user.models import User
from feed.models import Feed, ImageUrl, Comment
from product.models import Product, ProductImageUrl


class FeedView(APIView):
def get(self, request):
try:
MAXIMUM_COMMENT = 2
Expand Down Expand Up @@ -65,7 +71,8 @@ def get(self, request):
except User.DoesNotExist:
return JsonResponse({'MESSAGE' : 'INVALID_USER'}, status=404)

class FeedDetailView(View):

class FeedDetailView(APIView):
def get(self, request, feed_id):
try:
feed_data = Feed.objects.get(id=feed_id)
Expand Down Expand Up @@ -116,6 +123,7 @@ def get(self, request, feed_id):
'feed_image_data' : [{'url' : item.image_url} for item in feed_data.imageurl_set.all()],
}, status=200)

#
except ValueError:
return JsonResponse({'MESSAGE' : 'INVALID_VALUE_TYPE'}, status=400)

Expand All @@ -128,6 +136,16 @@ def get(self, request, feed_id):
except Product.DoesNotExist:
return JsonResponse({'MESSAGE' : 'INVALID_PRODUCT_ID'}, status=404)

@swagger_auto_schema(
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['description'],
properties={
'description': openapi.Schema(type=openapi.TYPE_STRING)
},
),
operation_description='update the feed with the new description'
)
@login_decorator
def patch(self, request, feed_id):
try:
Expand Down
13 changes: 8 additions & 5 deletions product/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import json
from operator import itemgetter

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views import View
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views import View

from product.models import Product
from rest_framework.views import APIView

class ProductView(View):
from product.models import Product


class ProductView(APIView):
def get(self, request, product_id):
if not Product.objects.filter(id=product_id).exists():
return JsonResponse({'message': 'PRODUCT_NOT_EXIST'}, status=404)
Expand Down
24 changes: 24 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,36 @@ asgiref==3.3.1
bcrypt==3.2.0
certifi==2020.12.5
cffi==1.14.5
chardet==4.0.0
click==7.1.2
coreapi==2.3.3
coreschema==0.0.4
Django==3.1.6
django-cors-headers==3.7.0
django-countries==7.0
djangorestframework==3.12.4
drf-yasg==1.20.0
flex==6.14.1
idna==2.10
inflection==0.5.1
itypes==1.2.0
Jinja2==2.11.3
jsonpointer==2.1
MarkupSafe==1.1.1
mysqlclient==2.0.3
packaging==20.9
pycparser==2.20
PyJWT==2.0.1
pyparsing==2.4.7
pytz==2021.1
PyYAML==5.4.1
requests==2.25.1
rfc3987==1.3.8
ruamel.yaml==0.17.4
ruamel.yaml.clib==0.2.2
six==1.15.0
sqlparse==0.4.1
strict-rfc3339==0.7
uritemplate==3.0.1
urllib3==1.26.4
validate-email==1.3
61 changes: 52 additions & 9 deletions user/views.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import json, bcrypt, jwt
import json
import bcrypt
import jwt

from django.shortcuts import render
from django.views import View
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.views import View
from django.http import JsonResponse, HttpResponse

from my_settings import SECRET_KEY,ALGORITHM
from user.models import User
from user.utils import login_decorator
from rest_framework.views import APIView
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema

class SignInView(View):
from my_settings import SECRET_KEY,ALGORITHM
from user.models import User
from user.utils import login_decorator


class SignInView(APIView):
@swagger_auto_schema(
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['user_name', 'password'],
properties={
'user_name': openapi.Schema(type=openapi.TYPE_STRING),
'password': openapi.Schema(type=openapi.TYPE_STRING),
},
),
operation_description='sign in with existing username and password'
)
def post(self, request):
data = json.loads(request.body)

Expand All @@ -34,7 +52,20 @@ def post(self, request):
USER_NAME_MIN_LENGTH = 3
USER_NAME_MAX_LENGTH = 32

class UserView(View):
class UserView(APIView):
@swagger_auto_schema(
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['user_name', 'password', 'nickname', 'email'],
properties={
'user_name': openapi.Schema(type=openapi.TYPE_STRING),
'password': openapi.Schema(type=openapi.TYPE_STRING),
'nickname': openapi.Schema(type=openapi.TYPE_STRING),
'email': openapi.Schema(type=openapi.TYPE_STRING, format=openapi.FORMAT_EMAIL),
},
),
operation_description='sign up to make a new account'
)
def post(self, request):
data = json.loads(request.body)

Expand Down Expand Up @@ -70,6 +101,18 @@ def post(self, request):
except KeyError:
return JsonResponse({'MESSAGE':'INVALID_KEYS'}, status=400)

@swagger_auto_schema(
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['birth', 'website', 'about'],
properties={
'birth': openapi.Schema(type=openapi.TYPE_STRING, format=openapi.FORMAT_DATE),
'website': openapi.Schema(type=openapi.TYPE_STRING, format=openapi.FORMAT_URI),
'about': openapi.Schema(type=openapi.TYPE_STRING),
},
),
operation_description='sign up to make a new account'
)
@login_decorator
def patch(self, request):
print(request)
Expand Down

0 comments on commit 1662016

Please sign in to comment.