TIL17. 모델 작성과 ORM

Byoungju Park·2021년 7월 19일
0
post-thumbnail
post-custom-banner

스타벅스 웹페이지 모델링한 것을 토대로 모델을 작성하고 데이터를 생성해 볼 것이다.

1. 장고 기본 세팅

스타벅스 프로젝트를 생성하고 기본 환경설정을 해준다.

1-1 장고 초기 세팅

  • 데이터베이스 생성 : MySQL에 들어가 새로운 데이터베이스를 생성한다.
  • 파이썬 패키지 설치 : 가상환경에서 django, mysqlclient를 설치한다.
  • 프로젝트 생성 : 스타벅스 프로젝트를 생성하고 해당 디렉토리로 이동한다.
  • settings.py 설정 : INSTALLED_APPS, MIDDLEWARE 에서 필요없는 것들은 주석처리 해준다. 데이터베이스와 시크릿키는 중요한 정보로 따로 관리해주는 것이 좋다.
  • my_settings.py 생성과 설정 : manage.py와 같은 경로에서 my_settings.py를 만들어주고 여기에 데이터베이스와 시크릿키를 입력한다. settings.py에서는 my_settings.py의 데이터베이스와 시크릿키를 연결해준다.
  • corsheaders 설치 : 설치 후 INSTALLED_APPS에 추가한다.

서버가 잘 동작하는지 체크해본다.

1-2 깃헙 연동

깃헙에 올리기 전에 중요하거나 불필요한 파일들은 .gitignore에 입력해준다. my_settings.py 도 추가한다. 프로젝트를 로컬 레퍼지토리에 올린다. 깃헙 레퍼지토리를 생성 후 로컬 레퍼지토리와 연동시킨다.

  • git branch -M main : 초기 branch가 master 라면 main 으로 변경해준다.

이제 main branch에서의 작업은 끝났다. 다른 기능을 추가하고 싶다면 새로운 branch에서 작업하는 것이 좋다.

2. 모델 작성

스타벅스 메뉴에 대한 브랜치 featrue/crud 와 앱 products를 새로 생성한다. 앱이 추가된 것을 장고에게 알리기 위해, INSTALLED_APPSproducts를 추가한다. 이후 products/models.py에서 모델링한 내용을 작성한다.

각각의 테이블은 클래스로 작성한다. 클래스가 어떻게 MySQL에서 테이블로 변환되는 것일까? 둘의 관계를 연동시키는 작업을 ORM 이라고 하고, 장고에서는 이를 자동으로 처리하여 우리가 할 작업을 줄여준다.

ORM Object Relational Mapping
객체와 테이블의 관계를 연결시켜주는 작업

ORM 참조
https://www.fullstackpython.com/object-relational-mappers-orms.html

2-1 테이블 작성

모든 테이블을 설명하지 않고, 테이블 관계를 중점으로 몇가지 테이블만 살펴보자.

1:1 관계

음료와 영양소. 1개의 음료 당 1개의 영양소가 존재한다. 서로 하나에만 연결되는 관계이다. 1:1 관계에서는 OneToOneField 속성을 사용한다. 둘 중 한 클래스에만 적용하면 된다. on_delete=models.CASCADE는 참조하는 데이터가 삭제될 경우에 대한 옵션이다. 이 경우는 참조하는Products 데이터가 삭제되면 이와 연관된 Nutritions 데이터도 삭제된다.

1:N 관계

메뉴와 카테고리. 1개의 메뉴에 대해 여러 개의 카테고리가 존재한다. 1:N 관계에서는 참조하는 클래스에서 ForienKey 속성을 적용한다.

N:N 관계

음료와 알러지. 1개의 음료에 여러 개의 알러지가 있고, 여러 개의 음료에 1개의 알러지가 해당할 수 있다. N:N 관계를 정의하는 것은 2가지 방법이 있다.

1. 중간 테이블 생성
둘 중 한 클래스에 ManyToManyField 속성을 적용하고, through에 중간 클래스 이름을 넣는다.
중간 클래스의 이름은 보통 클래스1_클래스2 로 정의한다. 그리고 연결될 2개의 클래스에 대해 각각 ForeignKey 를 적용한다.

2. 중간 테이블 없음
중간 테이블 없이 N:N 관계를 정의하려면, 한 클래스에 ManyToManyField 속성을 적용하고 다른 클래스 이름을 넣는다. 실제 데이터를 생성할 때에 그들의 관계가 실질적으로 연결된다.

# 음료와 알러지 테이블 정의
class Products(models.Model):
    name = models.CharField(max_length=45)
    .
    .
    
class Allergies(models.Model):
    name = models.CharField(max_length=45)
    product = models.ManyToManyField(Products)
    .
    .
    
# django shell에서 음료와 알러지 데이터에 대해 변수와 save를 사용하여 생성한다.

p1 = Products(name="콜드 브루")
p1.save()
p2 = Products(name="카페 라떼")
p2.save()

a1 = Allergies(name="우유")
a1.save()

# 알러지 데이터 a1에 대해 음료 데이터 p1, p2를 다음과 같이 연결시킨다.
a1.products.add(p1)
a1.products.add(p2)

3. 모델 작성하며 발생한 오류

데이터베이스 migration 이후 모델을 수정해야 할 때

  • 수정 사항
  1. 자잘한 오타나 null 여부
  2. 참조하는 필드의 이름에 _id를 붙이지 않아도 된다는 점. 처음에는 product_id 로 이름을 설정하였는데, 데이터베이스에는 product_id_id로 중복되어 나타남. ORM 시 자동으로 붙여준다는 것을 알게 되고 필드명 다시 수정

이러한 수정 사항을 반영한 후 다시 makemigrations를 하니 모든 필드에 default 값을 입력하라는 메세지가 나왔다. 모델에 직접 작성하지 않은 id도 입력해야 한다 해서, 마이그레이션 자체를 삭제하기로 결정했다.

나의 경우, 데이터베이스는 그대로 놔두고 테이블만 삭제하고 싶어서 MySQL에 다음과 같은 명령어를 입력했다.

SET @tables = NULL;
SELECT GROUP_CONCAT(table_schema, '.', table_name) INTO @tables
FROM information_schema.tables
WHERE table_schema = 'DB이름 입력'

SET @tables = CONCAT('DROP TABLE ', @tables);
PREPARE stmt FROM @tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

데이터가 없는 빈 테이블이었기 때문에 가능했지만, defalut값을 입력하지 않고 마이그레이션을 수정할 수 있는 방법을 모색하는 것이 좋을 듯하다.

profile
wanna be good programmer
post-custom-banner

0개의 댓글