REST API
API
응용 프로그램에서 사용할 수 있도록, 운영체제나 프로그래밍 언어가 제공하는 기능 을 제어할수있게만든 것
프로그램과 다른 프로그램이 제공하는 기능이나 데이터를 사용하기 위한 수단
우체국 우편을 보내기 위해서는 '올바른 주소'
API == 우체국 우편 서비스 ( 어떻게 보내는지는 알필요없다.)
API 명세
API를 사용한다.
Queryset 도 API 이다.
HTTP Method 복습하기
자원 URL 구성
http(s)://api.example.com/articles/
RESTful API
GET/articles/1/
1번 게시글 검색
POST 생성
POST/users/1/
1번유저가있다라는 뜻 말이 안된다.
0427 수업 시작
python -m venv venv
activate
pip install django django_seed djangorestframework
pip freeze > requirements.txt
django-admin startproject config .
python manage.py startapp articles
config > settings.py
INSTALLED_APPS = [
'articles',
'django_seed',
'rest_framework',
]
article > models.py
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=100)
content =models.TextField()
python manage.py makemigrations
python manage.py migrate
python manage.py seed articles --number=100
config > urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('articles.urls')),
# http://ww.kakao.com/api/url 일떄 안붙여준다
]
articles > urls.py (생성)
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
]
views.py
from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.decorators import api_viewfrom .models import Articlefrom .serializers import ArticleSerializer# Create your views here.@api_view()def article_list(request): # HttpRequest(Django 내부적으로 사용하는 객체) # HttpRequest + a => api_view #1. 모든 게시글 가져오고 articles = Article.objects.all() #QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입 #python 기본 타입 => JSON # 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers # ModelSerializer #2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.) # python api 를 json 으로 변환시키는것을 직렬화라고한다. serializer = ArticleSerializer(articles, many=True) #3. 직렬화된 데이터를 응답 # python 기본 타입 => JSON return Response(data = serializer.data)
articles > serializers.py (생성)
https://www.django-rest-framework.org/api-guide/serializers/#modelserializer
from rest_framework import serializersfrom .models import Articleclass ArticleSerializer(serializers.ModelSerializer): ''' articles 전용 모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트 ''' class Meta: model = Article fields = ('id', 'title')
page not found 뜰경우
Dealing with multiple objects 확인
https://www.django-rest-framework.org/api-guide/serializers/#dealing-with-multiple-objects
api guide views의 [Function Based Views]로 이동
https://www.django-rest-framework.org/api-guide/views/
views
from django.shortcuts import render, get_object_or_404from rest_framework.response import Responsefrom rest_framework.decorators import api_viewfrom .models import Articlefrom .serializers import ArticleSerializer, ArticleListSerializer# Create your views here.@api_view()def article_list(request): # HttpRequest(Django 내부적으로 사용하는 객체) # HttpRequest + a => api_view #1. 모든 게시글 가져오고 articles = Article.objects.all() #QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입 #python 기본 타입 => JSON # 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers # ModelSerializer #2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.) # python api 를 json 으로 변환시키는것을 직렬화라고한다. serializer = ArticleListSerializer(articles, many=True) #3. 직렬화된 데이터를 응답 # python 기본 타입 => JSON return Response(data = serializer.data) @api_view() def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) serializer = ArticleSerializer(articles, many=True) return Response(data=serializer.data)
serializer
from rest_framework import serializersfrom .models import Articleclass ArticleSerializer(serializers.ModelSerializer): ''' articles 전용 모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트 ''' class Meta: model = Article fields = ('id', 'title')class ArticleSerializer(serializers.ModelSerializer): ''' 개별 articles 전용 모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트 ''' class Meta: model = Article fields = ('id', 'title')
url.py
from django.urls import pathfrom . import viewsurlpatterns = [ path('articles/', views.article_list), path('articles/<int:article_id>/', views.article_detail),]
views.py
from django.shortcuts import render, get_object_or_404from rest_framework.response import Responsefrom rest_framework.decorators import api_viewfrom .models import Articlefrom .serializers import ArticleSerializer, ArticleListSerializer# Create your views here.@api_view(['GET', 'POST'])def article_list(request): if request.method == 'GET': # HttpRequest(Django 내부적으로 사용하는 객체) # HttpRequest + a => api_view #1. 모든 게시글 가져오고 articles = Article.objects.all() #QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입 #python 기본 타입 => JSON # 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers # ModelSerializer #2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.) # python api 를 json 으로 변환시키는것을 직렬화라고한다. serializer = ArticleListSerializer(articles, many=True) #3. 직렬화된 데이터를 응답 # python 기본 타입 => JSON return Response(data = serializer.data) elif request.method == 'POST': serializer = ArticleListSerializer(request.data) if serializer.is_valid(): serializer = serializer.save() return Response(data=serializer.data)@api_view()def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) serializer = ArticleSerializer(article) return Response(data=serializer.data)
postman 설치하기
가입안하고
get 을 post 로 바꾸고 주소입력http://localhost:8000/api/v1/articles/
이때
elif request.method == 'POST': serializer = ArticleListSerializer(request.data) if serializer.is_valid(): serializer.save() return Response(data=serializer.data)
serializer 에서 content 추가
from rest_framework import serializersfrom .models import Articleclass ArticleSerializer(serializers.ModelSerializer): ''' articles 전용 모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트 ''' class Meta: model = Article fields = ('id', 'title', 'content')class ArticleListSerializer(serializers.ModelSerializer): ''' 개별 articles 전용 모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트 ''' class Meta: model = Article fields = ('id', 'title', 'content')
EORROR 띄우기
https://www.django-rest-framework.org/api-guide/status-codes/
에서 400 번대 에러 메세지를 띄우는 곳을 확인한다
또한 잘된다면? successful 200번대를 띄워준다.
views.py
elif request.method == 'POST': serializer = ArticleListSerializer(data = request.data) if serializer.is_valid(): serializer.save() return Response(data=serializer.data, status=status.HTTP_201_CREATED)#<<<< return Response( data=serializer.errors, status=status.HTTP_400_BAD_REQUEST #<<<<<<<< )
더 좋은 옵션을 봅시다.
https://www.django-rest-framework.org/api-guide/serializers/ 에서
raise_exception 를 찾아준다.
# Return a 400 response if the data was invalid.serializer.is_valid(raise_exception=True)
@api_view(['GET', 'POST'])def article_list(request): if request.method == 'GET': # HttpRequest(Django 내부적으로 사용하는 객체) # HttpRequest + a => api_view #1. 모든 게시글 가져오고 articles = Article.objects.all() #QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입 #python 기본 타입 => JSON # 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers # ModelSerializer #2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.) # python api 를 json 으로 변환시키는것을 직렬화라고한다. serializer = ArticleListSerializer(articles, many=True) #3. 직렬화된 데이터를 응답 # python 기본 타입 => JSON return Response(data = serializer.data) elif request.method == 'POST': serializer = ArticleListSerializer(data = request.data) if serializer.is_valid(raise_exception=True): #<<<<<<<<<<<<<<<<<<<<< serializer.save() return Response(data=serializer.data, status=status.HTTP_201_CREATED) return Response( data=serializer.errors, status=status.HTTP_400_BAD_REQUEST )
특정 게시글 삭제
일반적으로 삭제된후에는 상태로 HTTP_204_NO_CONTENT를 해줌
https://www.django-rest-framework.org/api-guide/status-codes/
@api_view()def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) if request.method == 'GET': # 넘겨도 상관x 구분해서하라 요청 로직 다르다. # 단일 객체 many x serializer = ArticleSerializer(article) return Response(data=serializer.data) elif request.method == 'DELETE': article = article.delete() data = { 'message':f'{article}이 삭제되었습니다.' } return Response(data=data, status=status.HTTP_204_NO_CONTENT)
수정하기
models.py
from django.db import models# Create your models here.class Article(models.Model): title = models.CharField(max_length=100) content =models.TextField()class Comment(models.Model): article = models.ForeignKey(Article, on_delete=models.CASCADE) content = models.CharField(max_length=100)
urls.py
from django.urls import pathfrom . import viewsurlpatterns = [ path('articles/', views.article_list), path('articles/<int:article_id>/', views.article_detail), path('comments/',views.comment_list), # ]
views.py
from rest_framework.response import Responsefrom rest_framework.decorators import api_viewfrom rest_framework import statusfrom django.shortcuts import render, get_object_or_404from .models import Article, Commentfrom .serializers import ( ArticleSerializer, ArticleListSerializer, CommentSerializer,)# Create your views here.@api_view(['GET', 'POST'])def article_list(request): if request.method == 'GET': # HttpRequest(Django 내부적으로 사용하는 객체) # HttpRequest + a => api_view #1. 모든 게시글 가져오고 articles = Article.objects.all() #QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입 #python 기본 타입 => JSON # 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers # ModelSerializer #2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.) # python api 를 json 으로 변환시키는것을 직렬화라고한다. serializer = ArticleListSerializer(articles, many=True) #3. 직렬화된 데이터를 응답 # python 기본 타입 => JSON return Response(data = serializer.data) elif request.method == 'POST': serializer = ArticleListSerializer(data = request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(data=serializer.data, status=status.HTTP_201_CREATED) return Response( data=serializer.errors, status=status.HTTP_400_BAD_REQUEST ) @api_view(['GET', 'DELETE','PUT'])def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) if request.method == 'GET': # 넘겨도 상관x 구분해서하라 요청 로직 다르다. # 단일 객체 many x serializer = ArticleSerializer(article) return Response(data=serializer.data) elif request.method == 'DELETE': article = article.delete() data = { 'message': f'{article}이 삭제되었습니다.' } return Response(data=data, status=status.HTTP_204_NO_CONTENT) elif request.method == 'PUT': serializer = ArticleSerializer(data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(data=serializer.data)@api_view()def comment_list(request): comments = Comment.objects.all() serializer = CommentSerializer(comments, many = True) return Response(data=serializer.data)
postman 들어가서 확인하기
article > urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_id>/', views.article_detail),
path('comments/',views.comment_list),
path('articles/<int:article_id>/comments/', views.create_comment)# 댓글 생성
#
]
views.py
(serializer 는 commit 이 없습니다.) https://www.django-rest-framework.org/api-guide/serializers/#passing-additional-attributes-to-save
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import render, get_object_or_404
from .models import Article, Comment
from .serializers import (
ArticleSerializer,
ArticleListSerializer,
CommentSerializer,
)
# Create your views here.
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# HttpRequest(Django 내부적으로 사용하는 객체)
# HttpRequest + a => api_view
#1. 모든 게시글 가져오고
articles = Article.objects.all()
#QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입
#python 기본 타입 => JSON
# 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers
# ModelSerializer
#2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.)
# python api 를 json 으로 변환시키는것을 직렬화라고한다.
serializer = ArticleListSerializer(articles, many=True)
#3. 직렬화된 데이터를 응답
# python 기본 타입 => JSON
return Response(data = serializer.data)
elif request.method == 'POST':
serializer = ArticleListSerializer(data = request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(
data=serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
@api_view(['GET', 'DELETE','PUT'])
def article_detail(request, article_id):
article = get_object_or_404(Article, pk=article_id)
if request.method == 'GET':
# 넘겨도 상관x 구분해서하라 요청 로직 다르다.
# 단일 객체 many x
serializer = ArticleSerializer(article)
return Response(data=serializer.data)
elif request.method == 'DELETE':
article = article.delete()
data = {
'message': f'{article}이 삭제되었습니다.'
}
return Response(data=data, status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data=serializer.data)
@api_view()
def comment_list(request):
comments = Comment.objects.all()
serializer = CommentSerializer(comments, many = True)
return Response(data=serializer.data)
@api_view(['POST'])
def create_comment(request, article_id):
article = get_object_or_404(Article, pk=article_id)
#일단 바인딩 >
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=article) # 게시글 설정
return Response(data=serializer.data)
모든 댓글 보기
GET http://localhost:8000/api/v1/comments/ 모든 커멘트 확인하기
https://www.django-rest-framework.org/api-guide/serializers/#specifying-read-only-fields
serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'content', 'article')
read_only_fields = ['account_name'] #<<<<<<<<< 추가
게시글에서 댓글을 전부가져오고싶을떄
https://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations
serializers.py 수정
from rest_framework import serializers
from .models import Article, Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'content', 'article')
# fields에 작성된 필드들은
# 유효성 검사의 대상이 됩니다.
# (== is_valid()를 호출했을 때의 검사 대상)
read_only_fields = ['article']
class ArticleSerializer(serializers.ModelSerializer):
'''
articles 전용
모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트
'''
# 커멘트를 위로보내주자.
comment_set = CommentSerializer(many=True, read_only=True)
class Meta:
model = Article
fields = ('id', 'title', 'comment_set')
class ArticleListSerializer(serializers.ModelSerializer):
'''
개별 articles 전용
모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트
'''
class Meta:
model = Article
fields = ('id', 'title', 'content')
댓글 필드에 숫자 적인 필드를 담고싶을떄
comment_count = serializers.IntegerField() #추가해주기
from rest_framework import serializers
from .models import Article, Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'content', 'article')
# fields에 작성된 필드들은
# 유효성 검사의 대상이 됩니다.
# (== is_valid()를 호출했을 때의 검사 대상)
read_only_fields = ['article']
class ArticleSerializer(serializers.ModelSerializer):
'''
articles 전용
모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트
'''
# 커멘트를 위로보내주자.
comment_set = CommentSerializer(many=True, read_only=True)
#커스텀 필드, 필요한 정보는 저눕 넣을수있다.
#총 몇개의 정보를 담을수있을까?
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
class Meta:
model = Article
fields = ('id', 'title', 'comment_set', 'comment_count')
class ArticleListSerializer(serializers.ModelSerializer):
'''
개별 articles 전용
모델을 어떻게 직렬화할 것인지 설정하는 것이 포인트
'''
class Meta:
model = Article
fields = ('id', 'title', 'content')
글수정하기
put
http://localhost:8000/api/v1/articles/10/
리드온리 트루가없으면 수정할떄 비어있다고떠서 에러가뜹니다.
COmment Detail 부분
댓글 삭제하기
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import render, get_object_or_404
from .models import Article, Comment
from .serializers import (
ArticleSerializer,
ArticleListSerializer,
CommentSerializer,
)
# Create your views here.
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# HttpRequest(Django 내부적으로 사용하는 객체)
# HttpRequest + a => api_view
#1. 모든 게시글 가져오고
articles = Article.objects.all()
#QuerySet ( 장고가 만든 하나의 타입 ) => python 기본 타입
#python 기본 타입 => JSON
# 공식문서(https://www.django-rest-framework.org/) > API CUIDE > Serializers
# ModelSerializer
#2. 직렬화 ( 파이선 api 와 자바 api 서로 데이터 통신하기위해 규격이필요하는데 그것이 json, xml 이다.)
# python api 를 json 으로 변환시키는것을 직렬화라고한다.
serializer = ArticleListSerializer(articles, many=True)
#3. 직렬화된 데이터를 응답
# python 기본 타입 => JSON
return Response(data = serializer.data)
elif request.method == 'POST':
serializer = ArticleListSerializer(data = request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(
data=serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
@api_view(['GET', 'DELETE','PUT'])
def article_detail(request, article_id):
article = get_object_or_404(Article, pk=article_id)
if request.method == 'GET':
# 넘겨도 상관x 구분해서하라 요청 로직 다르다.
# 단일 객체 many x
serializer = ArticleSerializer(article)
return Response(data=serializer.data)
elif request.method == 'DELETE':
article = article.delete()
data = {
'message': f'{article}이 삭제되었습니다.'
}
return Response(data=data, status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data=serializer.data)
@api_view()
def comment_list(request):
comments = Comment.objects.all()
serializer = CommentSerializer(comments, many = True)
return Response(data=serializer.data)
@api_view(['POST'])
def create_comment(request, article_id):
article = get_object_or_404(Article, pk=article_id)
#일단 바인딩 >
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=article) # 게시글 설정
return Response(data=serializer.data)
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_id):
'''
생성(POST)는 안된다
http://localhost:8000/api/v1/comments/<int:comment_id>/
'''
comment = get_object_or_404(Comment, pk=comment_id)
if request.method == 'GET':
#커멘트시리얼라이즈에서 반환
serializer = CommentSerializer(comment)
return Response(data = serializer.data)
elif request.method == 'DELETE':
comment.delete()
data = {
'message': '성공적으로 삭제되었습니다.'
}
return Response(data=data, status= status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(data=serializer.data)
'SSAFY > Django' 카테고리의 다른 글
[Django] Dom (0) | 2021.04.28 |
---|---|
[Django] swagger (0) | 2021.04.27 |
[Django] 좋아요, follow, hashtag 간단 코딩 (0) | 2021.04.01 |
[Django] 로그인한 사용자 판별하기 (0) | 2021.03.27 |
[Django] 댓글 삭제 (0) | 2021.03.26 |