[django] C.R.U.D 2 (1) 주인과 강아지
지난번 models.py에 이어서, views.py와 urlConf 까지 작성해서 django 전체를 완성해보자.
URLconf: 클라이언트로부터 들어온 요청을 분석 및 라우팅하는 모듈
VIEW: 클라이언트 요청 처리를 위해 필요한 로직을 구현하는 모듈
MODEL: DB 생성(테이블 생성, 맵핑) 모듈
DATABASE: raw data의 집합체
0
추가 settings: client 준비
우선, http 통신을 위해서 API test program인 postman
을 다운받았다.
과제 가이드에서는 httpie
를 다운받으라고 되어 있었는데, postman
이 더 좋다는 멘토님 말 참고함.
brew update # Fetch latest version of homebrew and formula.
brew tap homebrew/cask # Tap the Homebrew/Cask repository from Github using HTTPS.
brew search postman # Searches all known Casks for a partial or exact match.
brew info --cask postman # Displays information about the given Cask
brew install --cask postman # Install the given cask.
brew cleanup # Remove any older versions from the cellar.
1
초기셋팅
과제 디렉토리 생성 > 가상환경 설정 > 데이터베이스 설정 > github repo 생성
장고 설정 > settings.py 설정 완료 후 > git first commit > push (main)
그리고 각 과제는 별도의 branch에 생성하므로, branch를 만들고 프로젝트에 app을 추가해 git commit & push 완료 한다.
아래와 같이,
featuer/onwer
branch에 checkout 한 상태에서 owners
라는 app을 디렉토리에 추가하고, weanimal_db
라는 데이터베이스를 만들어놓고 shell을 켰다.
그리고 migrate도 미리해서 DB와 연결이 잘 되었는지 확인하는 것이 좋다.
makemigrations 작업 없이도 가능한 이유는, django 자체에서 생성하는 테이블들이 존재하기 때문.
- django_content_type: 프로젝트에 있는 app과 model 기록
- django_migrations: migration 적용 기록
- django_session: 세션(정보교환) 정보 기록
2
models.py 작성
models.py
작성 후, migrate 작업을 한다.
python manage.py makemigrations owners(app name)
python manage.py migrate
그리고 shell에서 database import 하기
from app이름.models import Owner,Dog
migrate가 중요한게, models.py/views.py 등 다 건드려놓고 migrate를 제대로 하지 않으면 오류가 뜬다.
3
views.py 작성
POST 작성할 때, 처음 작성했던 내용은 아래와 같았다.
그리고 postman을 통해 body를 보냈으나 바로 age는 null값이 될 수 없다고 에러 뜸.
class OwnersView(View):
def post(self, request):
data = json.loads(request.body)
name = Owner.objects.create(name=data['name'])
email = Owner.objects.create(email=data['email'])
age = Owner.objects.create(age=data['age'])
Owner.objects.create(
name = name,
email = email,
age = age
)
return JsonResponse({"message":"created"}, status=201)
# Column 'age' cannot be null
처음엔 이것도 이유를 찾는답시고 database 지우고 다시 셋팅하고, migrate 다시 했으나 계속 같은 오류.
오류난 이유는, models.py
에서 Owners를 정의할 때 name
/email
/age
는 무조건 값이 들어가야 하도록 작성했다.
그러다 보니, views.py
를 위와 같이 작성해 버리면 name=Onwer.objects.create(name['data'])
에서 name
만 create되고 나머지 값들은 null처리가 되기 때문에 에러가 뜨는 것. name=Onwer.objects.create(name['data'])
앞뒤로 print(1)
와 print(2)
를 작성해서 돌리면 1을 찍고 바로 에러 난다. 이렇게 에러를 찾는 방법도 있음을 배웠다.
아래와 같이 수정.
class OwnersView(View):
def post(self, request):
data = json.loads(request.body)
Owner.objects.create(
name = data['name'],
email = data['email'],
age = data['age']
)
return JsonResponse({"message":"created"}, status=201)
이 상태에서 다시 데이터 send 하면 아래와 같이 완료.
데이터베이스를 불러오면 아래와 같이 업데이트됨.
dogs테이블 데이터도 처리해줄 Dogsview 작성하고,
발생할 수 있는 error 3가지: KeyError, DoesNotExist, MultipleObjectReturned 까지 예외처리 추가했다.
shell에서 get()
은 아래 특징을 갖기 때문임:
- 반드시 해당 DB에 있어야 한다.
- 1개만 return 한다.
- return 형태는 객체다. (QuerySet이 아님)
(전쟁에서 진 장수는 용서해도 경계에 실패한 장수는 용서하지 않는다...)
#OwnerView
class OwnerView(View):
def post(self,request):
try:
data = json.loads(request.body)
Owner.objects.create(
name = data['name'],
email = data['email'],
age = data['age']
)
return JsonResponse({'message':'success'},status=200)
except KeyError:
return JsonResponse({'error':'KEYERROR'},status=400)
#DogView
class DogView(View):
def post(self,request):
try:
data = json.loads(request.body)
owner = Owner.objects.get(name=data['owner'])
Dog.objects.create(
name = data['name'],
age = data['age'],
owner = owner.id #Owner.object(1)의 id값
)
return JsonResponse({"message":'created'},status=200)
except KeyError:
return JsonResponse({'error':'KEYERROR'},status=400)
except Owner.DoesNotExist:
return JsonResponse({'error':'specified owner does not exist'},status=404)
except Owner.MultipleObjectsReturned:
return JsonResponse({'error':'multiple objects returned'},status=400)
get
메소드는 아래와 같이 작성. for문은 list comprehension으로 바꿨다.
#OwnerView
class OwnerView(View):
def get(self,request):
result = [{
'name' : owner.name,
'email' : owner.email,
'age' : owner.age,
'dog_info' : [{
'name' : dog.name,
'age' : dog.age
} for dog in owner.dog_set.all()]} for owner in Owner.objects.all()]
#dog name/age는 dog테이블로 역참조해서 갖고 온다
#Owner:Dog=1:N, 1-> N의 형태는 역참조임
return JsonResponse({'result':result},status=201)
#DogView
class DogView(View):
def get(self,request):
result = [{'name':dog.name,'age':dog.age,'host_name':dog.owner.name} for dog in Dog.objects.all()]
#dog.owner.name: 해당 dog 데이터의 owner(owner_id)의 이름
return JsonResponse({"message":result},status=201)
urls.py
는 아래와 같이 바꿔줬다.
#owners > urls.py
from django.urls import path
from owners.views import DogsView, OwnersView
urlpatterns = [
path('/owners',OwnersView.as_view()),
path('/dogs',DogsView.as_view())
]
참고 자료:
https://www.javanibble.com/how-to-install-postman-on-macos-using-homebrew/
https://stackoverflow.com/questions/36895063/why-is-django-migrations-table-in-all-databases
https://tech.toktokhan.dev/2021/06/16/django-session/
https://stackoverflow.com/a/20637325
Author And Source
이 문제에 관하여([django] C.R.U.D 2 (1) 주인과 강아지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mquat/django-C.R.U.D-2-1-주인과-강아지저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)