본문 바로가기
Django/Django Vanila

10. Django 데이터베이스 관계

by S.T.Lee 2022. 5. 30.

1. one-to-many

하나가 여러개가 대응이 되는것이다. 하단의 코드를 보자.

Tweet Model의 author는 ForeignKey로써 하나의 유저만이 들어갈 수 있다. 즉, 한 개의 글에는 한 명의 작성자만이 글을 쓸 수 있다. 반대로 한 명의 사용자가 여러개의 글을 작성할 수 있다. 이러한 관계가 one-to-many이다.

class UserModel(AbstractUser):
    class Meta:
        db_table = "my_user"

    bio = models.TextField(max_length=500, blank=True)


class TweetModel(models.Model):
    class Meta:
        db_table = "tweet"

    author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    content = models.CharField(max_length=256)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class TweetComment(models.Model):
    class Meta:
        db_table = "comment"
    tweet = models.ForeignKey(TweetModel, on_delete=models.CASCADE)
    author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    comment = models.CharField(max_length=256)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

 

2. one-to-one

데이터 하나 당 하나의 데이터만 연결이 되는 관계이다. 하단의 코드를 보면 Profile은 UserModel을 하나의 정보로 가지고 있다. 즉, Profile 하나당 딱 하나만의 UserModel 데이터를 가지고 있는 것이다.

class UserModel(AbstractUser):
		...(생략)

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    user_pk = models.IntegerField(blank=True)
    nickname = models.CharField(max_length=200, blank=True)
    point = models.IntegerField(default=0)
    phone = models.CharField(max_length=200, blank=True)

 

3. many-to-many

A모델과 B모델이 있을 때 A가 여러개의 B를 또는 B가 여러개의 A를 가질 수 있는 모델이다. 토핑 중 하나인 치즈는 페페로니 피자, 포테이토 피자, 마르게리따 피자 등 다양한 피자에 들어갈 수 있으며 페페로니 피자에는 올리브, 치즈, 페페로니 등 다양한 토핑이 들어갈 수 있다. 이와 같이 서로 여러개의 다른 데이터를 포함할 수 있는것이 many-to-many이다.

class MyTopping(models.Model):
    topping_name = models.CharField(max_length=100)

class MyPizza(models.Model):
    pizza_name = models.CharField(max_length=100)
    pizza_topping = models.ManyToManyField(MyTopping)

 

4. 실습

1) app 만들기

새로운 app을 하나를 만들어준다.

django-admin startapp restaurant

다음에 project/settings.py/INSTALLED_APPS에 추가해준다.

 

2) 모델 등록하기

#restaurant/models.py
from django.db import models

# Create your models here.

class MyTopping(models.Model):
    class Meta:
        db_table = "my_topping"

    def __str__(self):
        return self.topping_name

    topping_name = models.CharField(max_length=100)


class MyPizza(models.Model):
    class Meta:
        db_table = "my_pizza"

    def __str__(self):
        return self.pizza_name

    pizza_name = models.CharField(max_length=100)
    pizza_topping = models.ManyToManyField(MyTopping)

잊지말고 makemigrations와 migrate를 실행한다.

그러면 db에 my_pizza, my_pizza_pizza_topping, my_topping이 추가 되어 있는것을 볼 수 있다.

 

3) admin 페이지에 추가하기

from django.contrib import admin
from .models import MyPizza,MyTopping
# Register your models here.

admin.site.register(MyPizza)
admin.site.register(MyTopping)

위와 같이 잘 만들어진걸 확인할 수 있다.

 

4) admin 페이지에서 데이터 추가하기

이제 admin 페이지에서 데이터를 추가할 것이다. My toppings에서 ADD MY TOPPING +를 눌러준다.

save를 누르면 짜잔! 에러가 뜬다.

이는 admin계정과 database 사이에 문제가 있는 것인데 db.sqlite3를 삭제해줘야 한다. 그리고 migrations 안에 있는 내용을 __init__.py를 제외하고 전부 지워줘야 한다. 초기화로써 전에 겪어봤던 문제이다.

좀 더 정확히 말하면 기본 Django User모델에서 커스텀 User모델로 바꾸면서 admin과 관련된 정보들이 제대로 세팅되지 않았기 때문이다.

그러다가 혹시나 필수 파일을 지우면 당황하지 말고 alt+shift+c 또는 File/Local History/Show History를 들어가자. 그러면 행적들이 보인다. 후자를 선택할때는 무조건 Projects 최상위 위치를 선택하고 들어가야 된다.

다시 위의 과정을 진행하면

잘 추가가 되는것을 볼 수 있다.

이제 여러가지 토핑들을 추가해주자.

 

이후 My_pizza에서 +Add를 누르고 name을 Pepperoni Pizza로 설정 토핑을 원하는 것을 선택해주고 Save를 해준다.

'Django > Django Vanila' 카테고리의 다른 글

12. Many-To-Many 모델 생성(related_name)  (0) 2022.05.30
11. Django Shell  (0) 2022.05.30
9. Django 게시글 읽기/삭제  (0) 2022.05.27
8. Django 게시글 쓰기  (0) 2022.05.27
7. Django 로그인 이후 기능  (0) 2022.05.27