django-admin startapp user
settings.py
rest_framework와 user(app이름)를 추가해준다.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # 추가
'user', # 추가
]
일단 database에 저장하고 가져다 쓸 데이터의 model(schema)을 만들어야한다. 기본적으로 schema안에는 무조건 primary key가 있어야 하기 때문에 간단하게 id를 primary key로 해서 만들 예정이다.
# models.py
from django.db import models
class User(models.Model):
id = models.AutoField(primary_key=True,null=False)
name = models.CharField(null=False,max_length=20)
tel=models.CharField(null=False,max_length=20)
id가 겹치지 않도록 AutoField로 구성했다.
serializer는 간단하게 말하자면, queryset, model의 instance과 같은 복잡한 데이터를 json,xml과 같은 유형으로 바꾸어 주는 어댑터라고 보면 된다.
serializer.py를 생성하고 코드를 넣어준다.
from rest_framework import serializers
from .models import User
# serializer.py
class userSerializer(serializers.ModelSerializer):
class Meta:
model=User
fields='__all__'
# ("id","name","tel")
Meta에 들어가는 model은 변환할 model, fields는 저장하거나 사용할때 필요한 필드들을 저장하면 된다.
일단 간단한 api이기 때문에 class보다 함수형으로 api를 작성하는 것이 보기 편하기 때문에 함수형으로 작성할 예정이다.
api_view라는 decorator를 사용해서 어떤 method가 들어갈 수 있는지 미리 정해줄 수 있다.
from rest_framework.decorators import api_view
.objects.all()로 database에 있는 모든 데이터를 들고온 다음, 미리 만들어 놓은 serializer로 queryset을 json형태로 바꾸어서 Response해주는 방식으로 진행한다.
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .serializers import userSerializer
from .models import User
@api_view(['GET'])
def getUser(request):
queryset = User.objects.all()
serializer = userSerializer(queryset,many=True)
return Response(serializer.data)
post는 애초에 request가 json형태로 들어오기 때문에 request.data를 serializer를 통해서 instance형식으로 바꾸어준다. 그리고 is_valid()로 instance의 유효성을 판단한 후에, database에 데이터를 저장해주는 방식으로 진행한다.
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .serializers import userSerializer
from .models import User
@api_view(['POST'])
def postUser(request):
user = userSerializer(data=request.data)
if user.is_valid():
user.save()
return Response(user.data)
return Response(user.errors,status=status.HTTP_400_BAD_REQUEST)
update는 특정한 하나의 데이터를 수정하는 방식으로 진행해야 하기 때문에, id와 같이 각 데이터를 구분할 수 있는 key가 url이나 request에 존재해야 구현이 가능하다. 일단 나는 /{id}의 형식으로 url을 입력하면 update되도록 구현했다.
@api_view(['PUT'])
def update(request,id)
try:
query = User.objects.get(id=id)
except User.DoesNotExist:
return Response({'error' : {
'code' : 404,
'message' : "User not found!"
}}, status = status.HTTP_404_NOT_FOUND)
user = userSerializer(query,data=request.data)
if user.is_valid():
user.save()
return Response(user.data)
return Response(user.errors,status=status.HTTP_400_BAD_REQUEST)
아래의 코드를 보면 post와 코드가 비슷한데, 이것은 .save()가 데이터가 없을 때는 post를, 있을 때는 put을 알아서 인식해서 수행해주기 때문이다.
delete는 모든 데이터를 없애는 방법과, 하나의 데이터를 없애는 방법 2가지가 존재하는데, 이것은 queryset을 바꾸어서 넣어주면 된다.
# 전체 삭제
@api_view(['DELETE'])
def delete(request,id)
query=User.objects.all()
query.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
# id별 삭제
@api_view(['DELETE'])
def deleteById(request,id)
try:
query = User.objects.get(id=id)
except User.DoesNotExist:
return Response({'error' : {
'code' : 404,
'message' : "User not found!"
}}, status = status.HTTP_404_NOT_FOUND)
query.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
url에 맞게 api를 연결해준다. project쪽의 urls도 연결해줘야 하기 때문에, include()를 사용해서 app을 project에 연결한다.
# user/urls.py
from django.contrib import admin
from django.urls import path
from .views import getUser, postUser,update,delete,deleteById
urlpatterns = [
path('get/', getUser),
path('post/', postUser),
path('update/<int:id>/', update),
path('delete/',delete)
path('delete/<int:id>/',deleteById)
#project/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('user/',include('user.urls'))
]
주소값 하나에 한 api만 넣어놓는 경우에는 url에 너무 복잡해질 수 있기 때문에, id가 필요한 api와 필요없는 api 2개로만 나누어서 api를 리팩토링 해야한다.
# user/views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .serializers import userSerializer
from .models import User
# Create your views here.
@api_view(['GET','POST'])
def getUser(request):
if request.method == 'GET':
query = User.objects.all()
serializer = userSerializer(query,many=True)
return Response(serializer.data)
elif request.method == 'POST':
user = userSerializer(data=request.data)
if user.is_valid():
user.save()
return Response(user.data)
return Response(user.errors,status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET','PUT','DELETE'])
def getUserForId(request,id):
try:
query = User.objects.get(id=id)
except User.DoesNotExist:
return Response({'error' : {
'code' : 404,
'message' : "Article not found!"
}}, status = status.HTTP_404_NOT_FOUND)
if request.method == "GET":
serializer = userSerializer(query)
return Response(serializer.data)
elif request.method=='PUT':
user = userSerializer(query,data=request.data)
if user.is_valid():
user.save()
return Response(user.data)
return Response(user.errors,status=status.HTTP_400_BAD_REQUEST)
elif request.method=='DELETE':
query.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
# user/urls.py
from django.contrib import admin
from django.urls import path
from .views import getUser, getUserForId
urlpatterns = [
path('', getUser),
path('<int:id>/', getUserForId)
]
보는거와 같이 urls.py에 코드가 훨씬 깔끔해진 것을 확인 할 수 있다.