www.youtube.com/watch?v=wIPHER2UBB4&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=6
이 포스팅은 다음과 같은 youtube 영상을 따라하면서 배운 내용과 학습 내용을 담은 것이다:
- Dennis Ivy - Database Relationships | One to Many & Many to Many | Getting Started | Django Framework (3.0) Crash Course Tutorials (pt 6)
현재 Django Version 3.1.2 를 쓰고 있다. Django는 파이썬을 쓰는 오픈소스 웹 프레임워크이다. 웹사이트 만들때 주로 쓰며, 간단한 것이 큰 특징이다.
1. Many to Many Relationships 이란?
Many to Many Relationship이란, 이름에서 말을 해주듯이, 다수에서 다수로의 관계를 짓는 것이다. 예를들어 '물'이라는 것은 '필수품' '음료' 라는 카테고리들과 연결이 될 수 있음과 동시에, A라는 사람이 '물'을 주문하고, B라는 사람이 '물'을 주문하는 것이다. 그렇게 된다면 위의 사진에 나온 것처럼 비슷하게 Many to Many Relationship이 형성이 된다.
이 Many to Many Relationship은, 우리가 이번에 Models.py를 수정하면서 구현해볼 것이다.
2. Many to Many Relationships Django에서 구현하기
우선, 저번에 포스팅 했던 내용에 다음과 같이 models.py가 짜여있다고 했다:
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
CATEGORY = (
('Indoor', 'Indoor'),
('Out Door', 'Out Door'),
)
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
description = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered'),
)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
이제는 다음과 같이 이 models.py의 class Order 부분에 추가를 해준다:
...
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
...
추가된 이것이 무엇인지 설명하기 전에, 이 class Order 안에 두개의 object를 추가했는지 설명하도록 하겠다.
우리가 지금 구현하고 있는것이 product를 customer가 order하는 것인데, order를 받았을 때, 어떤 customer이 어떤 product를 주문했는지 자동적으로 기입해주고 싶다. 이렇게 자동적으로 기입을 해주는 것을 구현하기 위해 customer과 product object를 Order class에 추가하게 된것이다.
ForeginKey는 many to many relationship을 만들기 위해 사용한다. 따라서 (Custmer, null=True, on delete=models.SET_NULL) 에서 Customer를 자신과 many to many 관계 있는 object를 부여를 해준다.
on_delete=models.SET_NULL은 이 customer object가 없어질 경우 (삭제될 경우), customer section은 없음 상태로 처리하고 order는 유지하게 된다. (단순히 Dennis Ivy가 교육용으로 제시한 방법일 뿐이며, 방법은 on_delete=models.CASCADE 와 같이 여러개 더 있다.)
이를 product와 customer에 둘 다 같이 추가해준다.
이제는 class Product에 다음과 같은 object를 추가해준다:
class Tag(models.Model):
name = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
...
class Product(models.Model):
...
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.name
...
class Tag는 Tag라는 class를 만들기 위해 단순히 추가해준 것이고, class Product에 tags = models.ManyToManyField(Tag)는 Tag라는 것이 중간매체인 product class를 거쳐간다는 것을 보여준다. 사진1에 보이는 것 처럼, Tag들은 Intermediary Table을 거쳐서 Products로 넘어간다. 우리가 짠 이 코드에서는 Tag가 Product를 거쳐 Orders로 넘어간다.
def __str__(self)의 경우, admin panel에서 Product의 이름으로 보이게끔 하기 위해 넣었다.
마지막으로는 Tag라는 새로운 class를 추가했기 때문에 admin.py도 변형시켜주고, 다음과 같은 command line도 실행시켜준다:
admin.py
...
admin.site.register(Tag)
#-------------------------
python manage.py makemigrations
...
python manage.py migrate
항상 class를 추가하거나 삭제했을 경우에는 새로운 migration을 진행해줘야 하는 것을 잊으면 안된다.
3. Admin Panel 확인하기
Order의 경우, admin panel에서 다음과 같이 나타난다:
Products의 경우에는 다음과 같이 나타난다:
Name, price는 입력하고, Category는 저번 포스트에서 설명했던 것 처럼 Indoor Outdoor 중에서 선택할 수 있다. Description칸의 경우 원래는 무엇이라도 써야된다. (지금의 경우, 쓸 필요가 없으므로 models.py의 products > description에 blank=True를 넣는다. null=True 같은 경우는 form submition에 사용하는 것이므로, description의 경우는 blank를 써줘야 한다.)
Tags는 다음과 같다:
Tag는 단순히 추가하는 것이므로, 사실상 Product class에서의 쓰임을 위해 만들어진 것이다. 나중에 이런 Tags를 이용해 Kitchen의 tag를 가진 Product의 매출, 재고 등등을 파악하는데 사용할 수 있을 것이다.