TIL 21 | Django CRUD #1

임종성·2021년 7월 18일
1

Django

목록 보기
3/17
post-thumbnail

가상환경을 설정하고 각종 설정과 패키지 설치와 데이터베이스 생성까지 하여 Django Project를 생성하고 초기 개발환경을 구성해봤다. 생성한 프로젝트를 git과 branch로 관리할 수 있도록 github과 연동하고, 주어진 ERD에 따라 models.py에 적절한 클래스를 작성하여 Database Table을 만든 후 Django Shell에서 Queryset API를 통해 C.R.U.D를 실습해보자.

Git Branch 생성 & Django App 생성

초기 개발환경을 구성했지만, 프로젝트를 Git으로 관리할 수 있도록 먼저 초기화를 진행한다.

git init  # 이 작업은 `manage.py`가 있는 디렉토리에서 실행한다.

# 소스를 공유하고 관리하기 위해 git을 사용하지만, 
# 보안을 위해서 올리면 안되는 것들이 존재하기 때문에 
# 깃이 생성된 디렉토리에 `.gitignore`를 이용해 관리한다.

git add .               
git commit -m "메시지"   

# Local의 Django 프로젝트와 Github의 Repository를 연동
git remote add origin "repository 주소"

# 완료된 초기 세팅 main branch를 git hub에 push
git push origin main 

main branch를 github으로 푸시한 후 새로운 branch를 생성하고 django app을 만들어보자.

git branch feature/crud     # 새로운 branch 생성
git checkout feature/crud   # 생성한 branch 이동

python3 manege.py startapp products # products라는 앱 생성

생성한 app을 django가 사용하기 위해서 연동을 해줘야 한다. settings.py의 INSTALLED_APPS에 생성한 app을 추가한다.

Model 생성

Django는 MVT(Model View Template) 구조를 가지고 있다. 그 중 Model은 Database와 ORM(Object Relational Mapping) 개념으로 연동되어 App의 데이터 구조를 파악하고 관리하는 역할을 수행한다. 주어진 ERD 모델로 models.py에 Model Class 작성을 통해 Database의 Table과 맵핑해보자.

각각의 Class는 MySQL Database의 Table과 대응하고, Class안의 변수들은 Table의 Column과 대응한다. 이렇게 맵핑되는 것을 ORM(Object Relational Mapping)이라 한다. 주어진 ERD에 따라 Table들을 생성하고, Column의 데이터타입 또한 CharField, URLField, TextField들을 통해 설정하고 다른 Table을 참조하는 경우 ForeignKey를 이용해 작성해줬다.

def __str__(self)

객체를 나타내는 비공식적인 문자열이지만 객체를 이해하기 쉽게 표현할 수 있는 문자열이며, string type의 문자열을 반환해야 한다.

def __str__(self):
	return self.name

models.py에서 Menu Class는 def __str__(self)을 사용했고 Image Class는 사용하지 않았는데, Django shell에서 Get 명령어를 통해 출력된 결과로 비교해보자.

이처럼 사용자에게 보기 쉬운 문자열을 출력하기에 편의성을 높일 수 있다.

Migration

models.py에 코드를 작성한 후 migration 파일을 생성하여 MySQL Database에 적용시키자.

python3 manage.py makemigrations products   # migration 파일 생성
python3 manage.py migrate products 	    # migration 파일 적용

Queryset API

Migration을 통해 Django Model과 Database를 연동하면, MySQL에서 직접 작업하지 않아도 Django Shell을 이용해 데이터를 C.R.U.D(Create, Read, Update, Delete) 할 수 있다. 실제 스타벅스 Data를 Django Shell을 이용해 Database에 생성해보자.

우선 MySQL에 접속해서 westarbucks Database에 접속한 후 SHOW Tables;을 실행하여 Migration이 제대로 이루어졌는지 확인해보자.

Menu, Category, Product, Nutrition, Image, Allergy, Allergyproduct의 7개 Table이 확실히 생성된 것을 볼 수 있다. 이제 Django Shell에서 Data를 CRUD 해보자.

다양한 Insertion 방법들

  • create()

Table에 Data를 Insert 하는 방법중 하나로, 생성된 Instance를 반환해준다. models.py에서 self.name을 return하도록 코딩했기에 다음과 같이 출력된다.

  • save()

단일 객체에 대해 수행할 때 많이 사용하며, Insertion 또는 Update를 수행하는 method이다.

다음과 같이 Update도 가능하다.

  • bulk_create()

지금까지는 단일객체들을 생성했으나, Create할 Data가 많은 경우 bulk_create()를 사용하면 편리하다.

그 외 get() 등 method들을 사용했는데, Query Method들에 대해 다음에 한 번 정리해볼 생각이다.

Data를 입력해주고 MySQL에서 출력한 결과는 다음과 같다!

예시에서 적용된 결과들은 빠져있지만 제대로 DATABASE가 적용된 것을 확인할 수 있다. 직접 shell을 이용해 MySQL Database에서 출력되는 결과를 보니 ORM에 대한 이해가 확실해진 것 같다!

Github Push

우리가 생성한 이 Database는 사실 feature/crud branch에서 적용된 것이고, github에 push된 main branch에는 이 Database가 존재하지 않는다. 따라서 결과를 merge하기 위해 github에 feature/crud branch를 푸시해주자!

git add .
git commit -m "feature/crud branch Push"
git push origin feature/crud

그 후 github의 westarbucks repository에서 feature/crud 브랜치에서 main 브랜치로 Pull Request를 날려주고 Merge하여 생성한 Databse가 Github을 통해 공유될 수 있도록 했다!


과정을 수행하면서 생긴 문제들

models.py의 Field를 수정하고 Migrate하여도 MySQL에 적용되지 않는 문제

Nutrition Table의 Data들을 입력하면서 오류가 나기에 확인해보니 size_mlsize_oz가 존재하지 않는것을 깨달았다. 제대로 migrate가 안되었다고 생각하고models.py를 확인하니 분명히 필드가 입력이 되어있음에도 MySQL에서 desc nutritions를 실행하니 필드가 적용되지 않음을 확인했다.

생각해보니 처음 feature/crud branch를 생성할때는 size_mlsize_oz 필드를 만들지 않은 상태로 main branch를 push 했었기에 그것이 원인이라고 생각했었다. 이후에도 계속 models.py를 수정하고 migrate 하는데도 MySQL에는 적용되지 않기에 어떻게 해야 해결되는지 답답했다. migration된 기록을 모두 삭제하는 것도 방법이라는데 그렇게 하면 지금껏 입력한 데이터들이 사라져서 다른 방법을 찾아봤다..

그러다 검색을 통해 간단한 해결방법을 찾았다.

  1. python3 manage.py dbshell 을 통해 sql 접속
  2. ALTER TABLE table명 ADD column명 int; 를 통해 직접 sql에 컬럼 추가
  3. models.py에서 추가하고자 한 field 주석처리 후 migrate
  4. models.py에서 주석처리한 field 주석 제거 후 migrate

이 과정을 거치니 바로 MySQL에 size_mlsize_ozmodels.py에 작성한 그대로 적용된 것을 확인할 수 있었다.. 아직 정확한 원인이나 해결된 프로세스가 이해는 잘 안가지만 천천히 알아가야겠다.

feature/crud branch Pull Request 중 Conflict 발생

feature/crud brnach를 push하고 PR을 하려니 Conflict가 발생하여 굉장히 당황했다. 문제가 뭘까 하고 찾아보니 github에서 친절하게 settings.py에서 conflict가 발생한다고 알려주었다.

찾아보니 pull request에서 나오는 충돌은 대체적으로 아래와 같은 상황에서 발생한다고 한다.

  • master 브랜치에서 feature_xfeature_y 브랜치를 동시에 생성
  • feature_x는 README.md를 수정하여 master에 merge가 완료됨
  • feature_y가 README.md를 수정하여 master에 pull request하는 순간 conflict 발생

이번에도 곰곰히 생각을 해보니.. main branch를 push하고 제출하는 과제가 있었는데, settings.py에 제대로 입력하지 않은 코드들이 몇 개 있어서 피드백을 받고 수정하여 다시 push한 기억이 떠올랐다. 그리고 feature/crud branch는 수정하지 않은 채 생성하고 다음에 또 수정을 했었다! 아마 각 branch의 settings.py를 수정하는 과정에서 분명 조금 다르게 수정한 부분이 있을거라 생각했고, 실제로 main branch의 settings.pyfeature/crud branch와 비교해 동일하게 수정하고 push하니 Conflict가 사라진 것을 확인할 수 있었다!


🐼 문제가 발생할때마다 곰곰히 원인을 생각하고 검색을 통해 혼자 힘으로 해결하니 성취감이 생각보다 컸다. 아쉬운 점은 실제론 위의 사례보다 에러가 몇 개는 더 발생했지만 순간순간의 에러와 상황을 제대로 기록하지 않으니 나중에 정리할 때 제대로 생각이 안났다는 점이다. 잎으로는 문제가 발생하면 그때그때 상황을 캡쳐하고 잘 기록해서 정리하는 습관을 가져야겠다.

profile
어디를 가든 마음을 다해 가자

0개의 댓글