❗️API_Server IN Django +3 참고❗️
프로젝트 생성
필요한 의존성 라이브러리(패키지) 설치
Django 프로젝트 생성
Django 애플리케이션 생성
settings.py를 수정해서 기본 설정
확인
from django.db import models
# Create your models here.
class Todo(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
important = models.BooleanField(default=False)
# 디버깅을 위해서 사용 - print로 인스턴스를 출력하면 호출되는 메서드
def __str__(self):
return self.title
(venv) euijoolee@EUIJOOui-MacBookAir ~/PycharmProjects/todoapi/mytodo python manage.py makemigrations
Migrations for 'mytodoapp':
mytodoapp/migrations/0001_initial.py
- Create model Todo
(venv) euijoolee@EUIJOOui-MacBookAir ~/PycharmProjects/todoapi/mytodo python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, mytodoapp, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying mytodoapp.0001_initial... OK
Applying sessions.0001_initial... OK
(venv) euijoolee@EUIJOOui-MacBookAir ~/PycharmProjects/todoapi/mytodo python manage.py createsuperuser
Username (leave blank to use 'euijoolee'): euijoo
Email address: euijoo@naver.com
Password:
Password (again):
The password is too similar to the username.
Bypass password validation and create user anyway? [y/N]: y
from django.contrib import admin
from .models import Todo
admin.site.register(Todo)
# Register your models here.
전제 조회해서 확인할 항목 : id, title, complete, important
전체 조회를 위한 시리얼라이저 생성 - serializers.py
from rest_framework import serializers
from .models import Todo
class TodoSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'complete','important')
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer
class TodoAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos,many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
"""
from django.contrib import admin
from django.urls import path
from django.contrib import admin
from django.urls import path
from mytodoapp.views import TodosAPIView
urlpatterns = [
path('admin/', admin.site.urls),
path('todo', TodosAPIView.as_view()),
]
from rest_framework import serializers
from .models import Todo
class TodoSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'complete','important')
class TodoCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('title', 'description', 'complete','important')
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer, TodoCreateSerializer
class TodoAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos,many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
# url 이 필요없음
def post(self,request):
# 파라미터를 가져와서 serializer를 생성
serializer = TodoCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
기본키를 넘겨받아서 기본키에 해당하는 데이터를 찾아서 리턴
serializers.py 수정
from rest_framework import serializers
from .models import Todo
class TodoSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'complete','important')
class TodoCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('title', 'description', 'complete','important')
class TodoDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'description', 'created', 'complete', 'important')
목록을 리턴하는 함수를 호출하는 경우 일반적으로 반복문으로 처리하는데 반복문에 null을 대입하면 예외가 발생하므로 목록을 리턴할 때는 데이터가 없으면 빈 목록([])를 리턴해줘야 한다
데이터의 존재 여부는 데이터 개수가 0인지로 확인
하나의 데이터를 리턴하는 경우 : 데이터가 존재하지 않으면 Null(null)을 리턴
views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer, TodoCreateSerializer
class TodosAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos, many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
# 파라미터를 가져와서 serializer를 생성
serializer = TodoCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
from .serializers import TodoDetailSerializer
from rest_framework.generics import get_object_or_404
class TodoAPIView(APIView):
def get(self,request,pk):
# id 가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoDetailSerializer(todo)
return Response(serializer.data,status=status.HTTP_200_OK)
"""
from django.contrib import admin
from django.urls import path
from django.contrib import admin
from django.urls import path
from mytodoapp.views import TodosAPIView,TodoAPIView
urlpatterns = [
path('admin/', admin.site.urls),
path('todo', TodosAPIView.as_view()),
path('todo/<int:pk>',TodoAPIView.as_view()),
]
데이터가 존재하는지 확인하고 존재하면 수정
ORM 에서는 데이터 삽입 과 수정이 동일한 방식으로 발생
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer, TodoCreateSerializer
class TodosAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos, many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
# 파라미터를 가져와서 serializer를 생성
serializer = TodoCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
from .serializers import TodoDetailSerializer
from rest_framework.generics import get_object_or_404
class TodoAPIView(APIView):
def get(self, request, pk):
# id 가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoDetailSerializer(todo)
return Response(serializer.data,status=status.HTTP_200_OK)
def put(self, request, pk):
# id가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoCreateSerializer(todo, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer, TodoCreateSerializer
class TodosAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos, many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
# 파라미터를 가져와서 serializer를 생성
serializer = TodoCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
from .serializers import TodoDetailSerializer
from rest_framework.generics import get_object_or_404
class TodoAPIView(APIView):
def get(self, request, pk):
# id 가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoDetailSerializer(todo)
return Response(serializer.data,status=status.HTTP_200_OK)
def put(self, request, pk):
# id가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoCreateSerializer(todo, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
#
class DoneTodosAPIView(APIView):
def get(self, request):
dones = Todo.objects.filter(complete=True)
serializer = TodoSimpleSerializer(dones,many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
# 완료로 수정하기 위한 처리
class DoneTodoAPIView(APIView):
def get(self, request, pk):
done = get_object_or_404(Todo, id=pk)
done.complete = True
done.save()
serializer = TodoDetailSerializer(done)
return Response(serializer.data, status=status.HTTP_200_OK)
"""
from django.contrib import admin
from django.urls import path
from django.contrib import admin
from django.urls import path
from mytodoapp.views import TodosAPIView, TodoAPIView, DoneTodosAPIView, DoneTodoAPIView
urlpatterns = [
path('admin/', admin.site.urls),
path('todo', TodosAPIView.as_view()),
path('todo/<int:pk>',TodoAPIView.as_view()),
path('done', DoneTodosAPIView.as_view()),
path('done/<int:pk>',DoneTodoAPIView.as_view()),
]
Unit Test : 함수 단위(메서드) 단위로 테스트
통합 테스트 : 함수들을 모아서 전체적으로 제대로 구동 되는지 테스트
인수 테스트 : 개발 환경과 운영환경이 다른 경우 개발 환경에서 운영환경으로 이전할 때 수행
블랙 박스 테스트 : 기능 테스트
화이트 박스 테스트 : 구조 테스트
알파 테스트 : 개발자의 장소에서 사용자가 테스트
베타 테스트 : 사용자의 환경에서 사용자가 테스트
구현하려는 기능에 대한 테스트 코드를 작성 - 모양만 생성
테스트 실행 - 실패
테스트를 통과할 수 있는 최소한의 기능을 구현
테스트를 실행시키고 통과시키면 코드를 정리
모든 기능을 구현할 때 까지 이를 반복
Model ➔ Service ➔ Controller ➔ View
from django.test import TestCase
from .models import Book #사실 에러
# Create your tests here.
class ModelTest(TestCase):
# 테스트를 수행하기 전에 호출되는 함수
def setup(self):
self.book_title = 'harry poter'
self.book_author= 'lee'
self.book = Book(
title=self.book_title, author = self.book_author)
# 테스트를 위한 함수
def test_model_can_create_a_bucketlist(self):
old_count = Book.objects.count()
self.book.save()
new_count = Book.objects.count()
self.assertNotEqual(old_count, new_count)
$ python manage.py test
from django.db import models
# Create your models here.
class Todo(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
important = models.BooleanField(default=False)
# 디버깅을 위해서 사용 - print로 인스턴스를 출력하면 호출되는 메서드
def __str__(self):
return self.title
#### Book 클래스
class Book(models.Model):
title = models.CharField(max_length=128)
author = models.CharField(max_length=128)
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py test
from rest_framework import serializers
from .models import Todo
class TodoSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'complete','important')
class TodoCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('title', 'description', 'complete','important')
class TodoDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'description', 'created', 'complete', 'important')
from.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('id','title','author')
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Todo
from .serializers import TodoSimpleSerializer, TodoCreateSerializer
class TodosAPIView(APIView):
def get(self, request):
todos = Todo.objects.filter(complete=False)
serializer = TodoSimpleSerializer(todos, many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
def post(self,request):
# 파라미터를 가져와서 serializer를 생성
serializer = TodoCreateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
from .serializers import TodoDetailSerializer
from rest_framework.generics import get_object_or_404
class TodoAPIView(APIView):
def get(self, request, pk):
# id 가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoDetailSerializer(todo)
return Response(serializer.data,status=status.HTTP_200_OK)
def put(self, request, pk):
# id가 pk 인 데이터를 조회하고 없으면 404 에러 발생
todo = get_object_or_404(Todo, id=pk)
serializer = TodoCreateSerializer(todo, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
#
class DoneTodosAPIView(APIView):
def get(self, request):
dones = Todo.objects.filter(complete=True)
serializer = TodoSimpleSerializer(dones,many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
# 완료로 수정하기 위한 처리
class DoneTodoAPIView(APIView):
def get(self, request, pk):
done = get_object_or_404(Todo, id=pk)
done.complete = True
done.save()
serializer = TodoDetailSerializer(done)
return Response(serializer.data, status=status.HTTP_200_OK)
from .serializers import BookSerializer
from .models import Book
from rest_framework import generics
class CreateView(generics.CreateView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def perform_create(self,serializer):
serializer.save()
"""
from django.contrib import admin
from django.urls import path
from django.contrib import admin
from django.urls import path
from mytodoapp.views import TodosAPIView, TodoAPIView, DoneTodosAPIView, DoneTodoAPIView
from mytodoapp.views import CreateView
urlpatterns = [
path('admin/', admin.site.urls),
path('todo', TodosAPIView.as_view()),
path('todo/<int:pk>',TodoAPIView.as_view()),
path('done', DoneTodosAPIView.as_view()),
path('done/<int:pk>',DoneTodoAPIView.as_view()),
path('api/books/',CreateView.as_view())
]