[Django] C.R.U.D -1

김가람휘·2022년 2월 13일
0

Django

목록 보기
6/13

작업 진행 순서

1. Django 프로젝트 생성

  • 원하는 위치에서 django 프로젝트 시작
  • Database 생성 및 settings.py 설정
  • 장고 초기 셋팅 완료 후 오류 검증

2. Git 초기화

  • 생성한 django 프로젝트를 git으로 관리할 수 있도록 초기화 한다.
  • 초기셋팅 환료 후 commit 남기기

3. Git Repository 생성 & 로컬 프로젝트와 연동

  • 자신의 github에 repository를 만든다
  • 로컬(내컴퓨터)의 django 프로젝트와 github의 repository 연동
  • 완료된 초기 셋팅 main branch github에 push

4. 새로운 branch 생성 & 과제 진행

  • 새로운 branch를 생성하고 생성한 branch로 이동
  • django app 시작하기
  • app작업 진행하기
  • MySql 데이터 확인하기

5. 완료한 작업 github에 push & pull request(PR) 날리기

  • 작업 완료 후 github에 새로운 브랜치로 push
  • 새로운 branch -> main 으로 pull request를 날린다.

MySQL database에 table 생성하기

# models.py

from django.db import models

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

    class Meta:
        db_table = 'categories'

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

    class Meta:
        db_table = 'menu'  


class Drink(models.Model):
    category = models.ForeignKey('Category', on_delete=models.CASCADE)
    korean_name = models.CharField(max_length=40)
    english_name = models.CharField(max_length=40)
    description = models.TextField()

    class Meta:
        db_table = 'drinks'

class Allergy_Drink(models.Model):
    allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE)
    drink     = models.ForeignKey('Drink', on_delete=models.CASCADE)

    class Meta:
        db_table = 'allergy_drink'

class Allergy(models.Model):
    name     = models.CharField(max_length=40, default="")
    drink_set = models.ManyToManyField(Drink, through=Allergy_Drink)

    class Meta:
        db_table = 'allergy'

class Nutrition(models.Model):
    one_serving_kca = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    sodium_mg = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    saturated_fat_g = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    sugars_g = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    protein_g = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    caffeine_mg = models.DecimalField(max_digits=10, decimal_places=2, null=True)
    drink = models.ForeignKey('Drink', on_delete=models.CASCADE, null=True)
    size = models.ForeignKey('Size', on_delete=models.CASCADE, null=True)

    class Meta:
        db_table = 'nutritions'

class Image(models.Model):
    image_url = models.CharField(max_length=1000)
    drink     = models.ForeignKey('Drink', on_delete=models.CASCADE)

    class Meta:
        db_table = 'images'

class Size(models.Model):
    name     = models.CharField(max_length=40)
    size_ml = models.CharField(max_length=40, null=True)
    size_fluid_ounce = models.CharField(max_length=40, null=True)

    class Meta:
        db_table = 'sizes'




정참조 & 역참조

  • 정참조
    • 내가 참조하는 table에 접근
    • 해당 객체가 접근하려는 객체의 ForeignKey를 가지고 있거나 1:1 관계인 상황에서 참조 하는 경우
    • select_related() 없이 바로 관계를 맺은 객체 정보를 볼 수 있다.
      • select_related()를 사용하는 이유 : Hit(datebase에 query를 요청하는 횟수)를 최소화하여 성능을 높인다.
      • select_related()는 JOIN을 사용하여 foreign-key로 정참조할 때 사용하며 QuerySet을 가져올 때, 미리 related objects까지 불러오는 함수이다.
        -> 비록 쿼리는 복잡해지지만 불러온 data들은 데이터베이스 서버가 종료되기 전까지 cache에 남게되어 매 쿼리마다 DB에 접근하지 않아도 된다.
      • prefetch_related() :select_related()와 같이 data를 cache에 저장하며, 모든 relationships에서 사용이 가능하다.
        -> select_related()은 하나의 Query로 related Objects들을 불러오지만, Prefetch_related()는 main Query가 실행이 된 후 별도의 Query가 실행이 된다. 따라서 리소스 소모가 더 크다.
>>> from products.models import Category, Menu, Drink, Nutrition, Image, Allergy_Drink, Allergy, Size
# 정참조
>>> a = Drink.objects.get(pk=1)
>>> a.category.name
'콜드 브루'

# select_related를 사용한 경우
>>> a = Drink.objects.select_related('category').get(pk=1)
>>> a.category.name
'콜드 브루'
>>> Drink.objects.select_related('category').get(pk=1).category.name
'콜드 브루'

# prefetch_related를 사용한 경우
>>> Drink.objects.prefetch_related('category').get(id=1).category.name
'콜드 브루'
  • 역참조
    • 나를 참조하는 table 접근
    • 다른 객체가 ForeignKey를 가지고 있거나 N:N 관계인 상황, 해당 객체를 참조하고 있는 다른 객체를 참조하려는 경우
# 역참조
>>> a = Category.objects.get(id=1)
>>> b = a.drink_set.all()
>>> b
<QuerySet [<Drink: Drink object (1)>, <Drink: Drink object (2)>]>
>>> b[0].korean_name
'나이트로 바닐라 크림'

# prefetch_related()를 사용한 경우
>>> a=Category.objects.prefetch_related('drink_set').get(id=1)
>>> b=a.drink_set.all()
>>> b
<QuerySet [<Drink: Drink object (1)>, <Drink: Drink object (2)>]>
>>> b[0].korean_name
'나이트로 바닐라 크림'

>>> Category.objects.prefetch_related('drink_set').get(id=1).drink_set.values()
<QuerySet [{'id': 1, 'category_id': 1, 'korean_name': '나이트로 바닐라 크림', 'english_name': 'Nitro Vanilla Cream', 
'description': '부드러운 목넘김의 나이트로 커피와 바닐라 크림의 매력을 한번에 느껴보세요!'},
{'id': 2, 'category_id': 1, 'korean_name': '나이트로 콜드 브루', 'english_name': 'Nitro Cold Brew', 
'description': '나이트로 커피 정통의 캐스케이딩과 부드러운 콜드 크레마! 부드러운 목 넘김과 완벽한 밸런스에 커피 본연의 단맛을 경험할 수 있습니다.'}]>

# many-to-many 관계 역참조
>>> Allergy.objects.get(id=1).drink_set.values()
<QuerySet [{'id': 5, 'category_id': 4, 'korean_name': '트리플 미니 스콘', 'english_name': 'Triple Mini Scone',
'description': '헤이즐넛 초콜릿, 치즈, 크랜베리 세 가지 맛의 스콘이 각각 들어있는 미니 사이즈의 스콘입니다.'},
{'id': 8, 'category_id': 5, 'korean_name': '티라미수 타르트', 'english_name': 'Tiramisu Tart',
'description': '촉촉한 초콜릿 브라우니 타르트 위에 달콤한 밀크 가나슈를 넣은 마스카포네 크림 무스를 올린 티라미수 타르트입 니다.'}]>

# prefetch_related()를 사용하여 many-to-many 관계를 대상으로 참조할때 data를 참조 대상까지 cache에 저장한다.
>>> Allergy.objects.prefetch_related('drink_set').get(id=1).drink_set.values()
<QuerySet [{'id': 5, 'category_id': 4, 'korean_name': '트리플 미니 스콘', 'english_name': 'Triple Mini Scone', 
'description': '헤이즐넛 초콜릿, 치즈, 크랜베리 세 가지 맛의 스콘이 각각 들어있는  미니 사이즈의 스콘입니다.'},
{'id': 8, 'category_id': 5, 'korean_name': '티라미수 타르트', 'english_name': 'Tiramisu Tart',
'description': '촉촉한 초콜릿 브라우니 타르트 위에 달콤한 밀크 가나슈를 넣은 마스카포네 크림 무스를 올린 티라미수 타르트입니다.'}]>
  • ManyToManyField를 쓰는 이유
    • Foriegn Key로만 관계를 설정하면 연결되어 있는 다른 테이블과의 작업을 하려면 중간 테이블을 거치는 방법 밖에 없습니다.
      -> 값을 넣거나 불러올 때도 중간 테이블을 통해서만 저장해주거나 불러올 수 있습니다.
# allergy, drink는 각자의 테이블에서 생성한 객체를 넣어준 변수이다.
>>> connect = Allergy_Drink(allergy_id = allergy, drink_id = drink)
>>> connect.save()

>>> Allergy_Drink.objects.create(allergy_id=1, drink_id=1)
  • ManyToManyField 사용시 위에 있는 예시들과 같이 중간 테이블을 거치지 않고도 값을 추가하거나 불러올 수 있습니다.
>>> a = Drink.objects.create(id=9, category_id=1, korean_name="아이스 아메리카노", english_name="ice americano", description="아이스 아메리카노")
>>> a.save()

>>> b = Allergy.objects.create(name="사과")
>>> b.save()

>>> a.allergy_set.add(b)
# b.drink_set.add(a)도 가능
# allergy_drink 테이블에 allergy_id=7(사과), drink_id=9 row가 추가됨

0개의 댓글