앱이란?
장고 프로젝트는 여러 개의 앱으로 구성되어 있는데, 앱이란 웹사이트를 기능별로 구분해놓은 것이다.
예를 들어, 홈페이지에서 상품, 결제, 채팅 등의 기능들을 앱으로 구성하는 것이다.
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'
이외에도 더 알고싶다면 장고 속성 공식문서를 참고하자.
각 클래스마다 id를 지정하지 않았는데, pk가 지정되어 있지 않으면 장고에서 자동으로 id컬럼을 만들고 pk를 생성한다.
_id
가 붙었으나, 장고에서는 생략하여야 한다. 왜냐하면 장고에서 자동으로 _id
를 붙여 데이터베이스로 넘기기 때문이다.# menu(O) menu_id(X)
menu = models.ForeignKey('Menu', on_delete=models.CASCADE)
데이터베이스에 테이블명을 지어주어야 하는데,
아래와 같이 Meta class
에 클래스명과 다르게 소문자로 테이블명을 지어주어야 한다.
class Menu(models.Model):
name = models.CharField(max_length=50)
class Meta:
db_table = 'menus'
중간테이블을 왜 만들까?
중간 테이블 클래스를 모델에 직접 정의지 않으면 두 테이블 id의 조합 외에 다른 값을 넣기가 힘들다. 따라서 중간 테이블을 만들어서 사용하는 것이 컨트롤하기 좋다.
class Allergy(models.Model):
products = models.ManyToManyField('Product')
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)