[Django] 스타벅스 모델 작성하기

앱 생성하기

앱이란?
장고 프로젝트는 여러 개의 앱으로 구성되어 있는데, 앱이란 웹사이트를 기능별로 구분해놓은 것이다.
예를 들어, 홈페이지에서 상품, 결제, 채팅 등의 기능들을 앱으로 구성하는 것이다.

starbucks 프로젝트 아래에 products라는 앱을 생성한다.

cd starbucks
python manage.py startapp products

앱을 생성하면 다음과 같은 파일들이 자동으로 생성이 된다.

앱 등록하기

앱을 생성하면 starbucks/settings.py에 들어가 앱 등록을 해주어야 한다.
그래야 테이블 생성이 가능하다.
INSTALLED_APPS 리스트에 products를 추가한다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products',
]

모델 작성하기

모델이란?
장고에서 모델(model)은 데이터를 관리하는 곳이다.
모델은 각 앱 안의 models.py 모듈에서 정의하게 된다.
models.py 모듈 안에 하나 이상의 모델 클래스를 정의할 수 있으며, 하나의 모델 클래스는 데이타베이스에서 하나의 테이블에 해당된다.

스타벅스 홈페이지의 상품 모델링을 기준으로 장고 모델을 작성해보자.

from django.db import models

class Menu(models.Model):
    name = models.CharField(max_length=20)

    class Meta:
          db_table = 'menus'

class Category(models.Model):
    name = models.CharField(max_length=20)
    menu = models.ForeignKey('Menu', on_delete=models.CASCADE)

    class Meta:
          db_table = 'categories'

class Product(models.Model): 
    name = models.CharField(max_length=50)
    description = models.CharField(max_length=500)
    category = models.ForeignKey('Category', on_delete=models.CASCADE)

    class Meta:
        db_table = 'products'

class ProductAllergy(models.Model):
    allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)

    class Meta:
        db_table = 'product_allergies'


class Allergy(models.Model):
    name = models.CharField(max_length=50)
    products = models.ManyToManyField('Product', through='ProductAllergy')
    class Meta:
        db_table = 'allergies'

class Nutrition(models.Model):
    one_serving_kcal = models.DecimalField(max_digits=10, decimal_places=2)
    sodium_mg = models.DecimalField(max_digits=10, decimal_places=2)
    saturated_fat_g = models.DecimalField(max_digits=10, decimal_places=2)
    sugars_g = models.DecimalField(max_digits=10, decimal_places=2)
    protein_g = models.DecimalField(max_digits=10, decimal_places=2)
    caffeine_mg = models.DecimalField(max_digits=10, decimal_places=2)
    product = models.OneToOneField('Product', on_delete=models.CASCADE)

    class Meta:
        db_table = 'nutritions'

class Image(models.Model):
    image_url = models.URLField(max_length=2000)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)

    class Meta:
        db_table = 'images'

모델 작성시 중요포인트!

Field

  • CharField : 글자 수가 제한된 텍스트를 정의할 때 사용, max_length 지정
  • URLField : URL을 입력해야 할 때는 CharField 대신 사용, max_length 지정
  • DecimalField : max_digits에는 소수점 아래를 포함하여 전체 길이, decimal_places에는 소수점 아래의 길이를 지정
  • BooleanField : true/false 필드, 0 또는 1로 입력가능

이외에도 더 알고싶다면 장고 속성 공식문서를 참고하자.

자동 생성되는 id (=Primary Key)

각 클래스마다 id를 지정하지 않았는데, pk가 지정되어 있지 않으면 장고에서 자동으로 id컬럼을 만들고 pk를 생성한다.

ForeignKey의 컬럼명 작성하기

  • diagram 도식화하였을때는 Foreignkey의 컬럼명 뒤에 _id가 붙었으나, 장고에서는 생략하여야 한다. 왜냐하면 장고에서 자동으로 _id를 붙여 데이터베이스로 넘기기 때문이다.
# menu(O) menu_id(X)
menu = models.ForeignKey('Menu', on_delete=models.CASCADE)

데이터베이스에 저장되는 테이블명 변경하기(Meta)

데이터베이스에 테이블명을 지어주어야 하는데,
아래와 같이 Meta class에 클래스명과 다르게 소문자로 테이블명을 지어주어야 한다.

class Menu(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        db_table = 'menus'

관계설정

Allergy와 Product의 관계 (N:N)

중간테이블을 왜 만들까?
중간 테이블 클래스를 모델에 직접 정의지 않으면 두 테이블 id의 조합 외에 다른 값을 넣기가 힘들다. 따라서 중간 테이블을 만들어서 사용하는 것이 컨트롤하기 좋다.

중간 테이블이 없는 경우

  • 한쪽 테이블에 ManyToManyField를 사용해 관계를 설정한다.
  • 컬럼명을 products처럼 자유롭게 지정할 수 있다.
  • 이렇게 하면 클래스로 중간테이블을 만들지 않더라도 데이터베이스 안에서 자동으로 다대다테이블이 생성된다.
class Allergy(models.Model):
    products = models.ManyToManyField('Product')

중간 테이블이 있는 경우

  • 한쪽 테이블에 ManyToManyField를 사용하는데,through='AllergyProduct'로 중간테이블과 연결해준다.
  • 중간테이블에는 Allergy와 Product 참조하는 ForeignKey를 하나씩 만들어준다.
class Allergy(models.Model):
    products = models.ManyToManyField('Product', through='AllergyProduct')

class AllergyProduct(models.Model):
    allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)

좋은 웹페이지 즐겨찾기