지난 글에서는 URL 설정을 통해 트리거할 views.py을 간단히 작성해보았습니다. 이번에는 데이터 처리를 위해 models.py를 작성하고 views.py와 연결해보도록 하겠습니다. 목차는 다음과 같습니다.
- 장고 모델 작업(데이터 구조 생성)
- MySQL 연결과 마이그레이션
- 터미널을 통한 CRUD
- HTTP 요청과 응답을 통한 CRUD
1. 장고 모델 작업
모델의 역할은 애플리케이션과 함께 작동할 데이터의 청사진을 그리는 것입니다. 작업은 각 앱 내 models.py에서 진행합니다(참고: 앱 생성 방법). 아래와 같이 Class를 통해 모델을 생성할 수 있습니다.
# humans/models.py
from django.db import models
class Human(models.Model):
email = models.EmailField(max_length=300, unique=True)
age = models.PositiveIntegerField(null=True)
name = models.CharField(max_length=45)
class Meta:
db_table = 'humans'
def __str__(self):
return f"{self.name, self.email, self.age}"
# dogs/models.py
class Dog(models.Model):
name = models.CharField(max_length=20)
age = models.PositiveIntegerField(null=True)
human = models.ForeignKey('humans.Human', on_delete = models.CASCADE)
class Meta:
db_table = 'dogs'
def __str__(self):
return f"{self.name, self.age}"
Dog Class
내 humans.Human
부분은 ForeignKey를 통해 Humans 클래스를 참조하고 있습니다.
모델 작업을 모두 마쳤으면 settings.py INSTALLED_APPS
에 작업한 앱 이름 추가하여 연동합니다.
# settings. py
INSTALLED_APPS = [
'humans',
'dogs',
#'django.contrib.admin',
#'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
2. MySQL 연결과 마이그레이션
MySQL 데이터 베이스 생성 및 연결 방법은 다음과 같습니다.
mysql -u root -p # mysql 로그인
show databases; # 데이터베이스 목록 확인
create databases human_and_dog; # 데이터베이스 생성
use human_and_dog; # 데이터베이스 사용
show tables; # 데이터베이스 내 테이블 확인
Models.py 마이그레이션을 진행합니다.
python manage.py makemigraitions
python manage.py migrate
MySQL에서 생성된 데이터를 확인하려면 아래와 같이 입력합니다. 현재는 입력된 데이터가 없어 비어있을 것입니다.
show tables; # 마이그레이트된 테이블 확인 가능
3. 터미널을 통한 C.R.U.D
터미널에서 다음과 같이 CRUD를 진행할 수 있습니다.
python3 manage.py shell
from humans.models import Human
Human.objects.create(name= "사람") # C
Human.objects.all() # R
h1 = Human.objects.all()[0] # U
h1.name ="사람2"
h1.delete() # D
4. HTTP 요청과 응답을 통한 C.R.U.D
4-1. views.py 설정
이번에는 외부 HTTP 요청을 통해 CRUD를 진행해보도록 하겠습니다. HTTP POST/GET 메소드는 각 앱의 views.py에 구현합니다. HTTP post
메소드를 아래와 같이 추가해보겠습니다.
# humans/views.py
# built-in module
import json #데이터를 json 형태로 처리
# 3rd-party module
from django.views import View
from django.http import JsonResponse
# user set module
from humans.models import Human
class HumanView(View):
def post(self, request):
data = json.loads(request.body)
human = Human.objects.create(
name=data["name"],
email=data["email"],
age=data["age"]
)
return JsonResponse({"message": "SUCCESS"}, status=201)
마찬가지로 dogs/views.py도 설정해보겠습니다.
# dogs/views.py
import json
from django.views import View
from django.http import JsonResponse
from .models import Dog
class DogView(View):
def post(self, request):
data = json.loads(request.body)
dog = Dog.objects.create(
name=data["name"],
age=data["age"],
human_id=data["human_id"]
)
return JsonResponse({"message": "SUCCESS"}, status=201)
4-2. URLconf 처리
상위 urls.py을 수정하고 각 앱의 urls.py에 경로 및 클래스를 추가하여 연동된 views.py가 제대로 작동할 수 있게 합니다.
# human_and_dog/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('humans/', include('humans.urls')),
path('dogs/', include('dogs.urls'))
]
# humans/urls.py
from django.urls import path
from .views import HumanView
urlpatterns = [
path('', HumanView.as_view())
]
# dogs/urls.py
from django.urls import path
from .views import DogView
urlpatterns = [
path('', DogView.as_view())
]
4-3. HTTP 요청과 응답
실제 요청을 진행해겠습니다. HTTP Request를 위한 Httpie 설치를 진행합니다.
brew install httpie
HTTP POST 요청을 확인해봅니다.
http -v POST 127.0.0.1:8000/humans/ name="사람1" email="human1@gmail.com" age=30
mysql table을 확인하면 정상적으로 데이터가 추가된 것을 확인할 수 있습니다.
이번에는 HTTP POST 요청으로 개 데이터를 추가해보겠습니다.
HTTP -v POST 127.0.0.1:8000/dogs/ name="개2" age=2 human_id=2
4-4. GET 메소드 추가
이제 기존의 메소드에 get
메소드를 추가해보겠습니다.
# humans/views.py
import json
from django.views import View
from django.http import JsonResponse
from .models import Human
class HumanView(View):
def get(self, request):
humans = Human.objects.all()
humanList = []
for human in humans:
humanList.append(
{
"name": human.name,
"email": human.email,
"age": human.age,
}
)
return JsonResponse({"humans": humanList}, status=200)
def post(self, request):
data = json.loads(request.body)
human = Human.objects.create(
name=data["name"],
email=data["email"],
age=data["age"]
)
return JsonResponse({"message": "SUCCESS"}, status=201)
HTTP GET 요청을 확인해봅니다.
http -v GET http://127.0.0.1:8000/humans/
마찬가지로 dogs/view.py에도 메소드를 추가하여 GET 요청을 처리합니다.
# dogs/views.py
import json
from django.views import View
from django.http import JsonResponse
from .models import Dog
class DogView(View):
def get(self, request):
dogs = Dog.objects.all()
dogList = []
for dog in dogs:
dogList.append(
{
"name": dog.name,
"dog": dog.age,
}
)
return JsonResponse({"dogs": dogList}, status=200)
def post(self, request):
data = json.loads(request.body)
dog = Dog.objects.create(
name=data["name"],
age=data["age"],
human_id=data["human_id"]
)
return JsonResponse({"message": "SUCCESS"}, status=201)
4-5. SQL 테이블 확인
MySQL 테이블을 확인하려면 커맨드 라인에서 다음을 입력합니다.
select * from dogs;
select * from humans;
4-6. (추가 구현): FK 테이블에서 PK 테이블 참조하기
개의 정보에 관련된 사람의 정보를 출력하려면 어떻게 해야 할까요?
DogView
클래스의 get
메소드를 수정해보겠습니다. Human
클래스 접근하여 dog__id = dog.id
를 가져와주면 DogView
에서 Human
클래스의 사람 정보에 접근할 수 있습니다.
#dogs/views.py
class DogView(View):
def get(self, request):
dogs = Dog.objects.all()
dogList = []
for dog in dogs:
human = Human.objects.get(dog__id = dog.id)
dogList.append(
{
"name": dog.name,
"dog": dog.age,
"humanMate": {
"name": human.name,
"id": human.id
}
}
)
return JsonResponse({"dogs": dogList}, status=200)
그러나 dog__id
를 사용하지 않고, 다음과 같은 방식으로 보다 간단하게 구현할 수도 있습니다.
#dogs/views.py
class DogView(View):
def get(self, request):
dogs = Dog.objects.all()
dogList = []
for dog in dogs:
dogList.append(
{
"name": dog.name,
"dog": dog.age,
"humanMate": {
"name": dog.human.name,
"id": dog.human.id
}
}
)
4-7. (추가 구현): PK 테이블에서 FK 테이블 참조하기
사람의 veiws.py에서 개의 정보를 출력하려면 어떻게 할 수 있을까요? 즉, PK 테이블에서 FK 테이블을 역으로 참조하려면 어떻게 할까요? 가장 간단한 방법은 다음과 같이 List Comprehension을 활용하는 것입니다.
class HumanView(View):
def get(self, request):
humans = Human.objects.all()
humanList = []
for human in humans:
humanList.append(
{
"name": human.name,
"email": human.email,
"age": human.age,
"dogs": [{"id": dog.id, "name": dog.name} for dog in human.dog_set.all()]
}
)
return JsonResponse({"humans": humanList}, status=200)
human.dog_set.all()
을 자세히 살펴보겠습니다. dog_set
에서 dog
는 참조하고 있는 Dog
클래스를 의미하며(소문자로 참조), 여기에 _set
을 붙이면 PK 테이블에서 FK 테이블을 역참조할 수 있게 됩니다.
'Django' 카테고리의 다른 글
장고 암호화 인증 인가 처리: bcrypt, JWT 사용 방법 (0) | 2022.01.19 |
---|---|
장고 HTTP 리퀘스트 유효성 검사 및 에러 메시지 작성 방법 (0) | 2022.01.16 |
장고 URL 추가 및 Views에서 URLconf 요청 응답 처리 방법 (0) | 2022.01.10 |
장고 URL과 Views의 개념 및 역할 (0) | 2022.01.10 |
장고의 작동 방식과 MVT 패턴 (0) | 2022.01.10 |