21.2.24

커피 내리는 그냥 사람·2021년 2월 24일
0

위코드 pre코스

목록 보기
19/28

<Django CRUD 1>

스타벅스 홈페이지 음료 및 푸드 정보를 통한 데이터베이스와 models.py의 ORM 실습 과제

1. 가상환경 설정

  • miniconda3 설치하기

    가상 환경을 설정하는 이유 : 여러 프로젝트를 하는데 분리 버전 및 패키지를 가지기 위해. 즉 프로젝트를 위해 새 종이를 하나 띄우는 것과 같다.

  1. 먼저 터미널에서 conda를 설치한다.
    설치 과정은 다음과 같다.
    다운로드 홈페이지에서 링크의 url을 가져온 다음 (버전은 3.7을 가져왔다.) wget + url link로 다운로드 받는다.

  2. 가상환경 설정을 위해 conda를 실행한다.

  • 하다가 발생한 오류 : 정상 설치 되었지만 conda를 불러오는 과정에서 route 설정이 오류가 난 상황이었다.
    멘토님과 함께 해결한 결과는 아예 콘다의 경로를 변경하였고 터미널 실행 시 자동으로 실행이 될 수 있도록 설정해두었다. 자세한 방법에 대해서는 알지 못해 추후 비슷한 오류 발생 시 시도해봐야겠다.
  1. 콘다를 활성화 시킨다.
    conda create -n "westarbucks" python=3.7
    conda activate westarbucks
  • 여기서 발생한 문제 : 가상환경 엑티베이트가 안 되어서 구글링 통해 방법 찾아보니 source activate westarbucks로 해결이 가능하였다.
    -> 이 때 가상환경명은 프로젝트의 이름과 같게 해야 한다.
  • 만일 잠깐 가상환경을 종료해야 한다면 conda deactivate를 해주면 된다.
  1. 가상환경이 설정이 완료 되었으면 django 및 mysqlclient를 설치한다.
    방법은 pip install ~로 해준다.
    -> 이 때 꼭 가상환경인 () ~ 이 붙어 있는지 확인한다.

  2. 설치가 완료되었다면
    django-admin startproject westarbucks
    cd westarbucks
    python manage.py startapp products
    로 프로젝트 및 앱을 활성화 시킨다.

  3. DB설정을 해준다.
    mysql -u root -p ; +비밀번호
    create database westarbucks character set utf8mb4 collate utf8mb4_general_ci;
    를 하여 데이터베이스 명을 지정해준다. 여기서 지정해준 데이터베이스 명은 추후 장고 세팅스 파일에서 그대로 써주면 된다.

  • 데이터 베이스 설정을 해주지 않으면 추후에 아무리 작업을 하더라도 되지 않았다.

여기까지가 가상환경 구축이다. 콘다 실행으로 시간이 많이 걸리긴 했으나 확실하게 해주지 않으면 작업 자체가 불가능하다.

2. settings.py 설정

settings.py는 프로젝트의 '뇌' 부분이기 때문에 가장 중요하다. 그 만큼 설정이 까다롭지만 몇몇 지켜야 할 사항만 지킨다면 금방 따라할 수 있다.

  1. IP 허용 : CRUD2 파트이므로 일단 설정해놓는다.
ALLOWED_HOSTS = ['*']
  • westarbucks/urls.py에 urlpatterns부분은 비워둔다.
  1. 주석처리 :
    사용하지 않는 요소를 주석처리 해준다.
  • install에서는 admin과 auth
  • middle에서는 command 밑 2가지
  1. DB파트 : DB 명을 제대로 입력하지 않으면 CRUD가 원활히 이뤄지지 않는다.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'westarbucks',
        'USER': 'root',
        'PASSWORD': 'sql칠 때 쓰던 것',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

3. models.py 세팅

  • 먼저 models.py는 데이터베이스의 내용이 장고와 연동되어 바로 나타나는 부분이다.

ORM에 대해서는 자세히 다루진 않았지만, 아마 장고에서 만든 객체 클래스가 데이터베이스 테이블로 변환되는 과정은 아마 migration 과정에서 일어나지 않을까 조심스레 추측해본다.
멘토님 첨언 : 이 뿐만 아니라 파이썬 쉘에서 하는 일련의 모든 과정들이 다 ORM의 과정.

  • 기본적으로 상속을 바탕으로 한다. 여기선 장고의 모델 속성을 상속받은 클래스들이다.
  • 클래스 하나 하나는 데이터베이스의 테이블이다.
  • 클래스 밑에 적히는 내용들은 컬럼으로 = 로 표기되는 조건과 함께 테이블에 저장된다.
  • 각 조건은 테이블에서 어떻게 표기되는가를 결정하는 요소인데
    Charfield는 SQL에 VARCHAR역할(즉 텍스트),
    DecimalField는 소수점(총 몇 자리까지 표기 + 소수점 몇개까지 표기?)
    마지막으로 ForeignKey가 있다.

포린 키는 데이터베이스 테이블 간의 관계를 나타내며 이 키들은 데이터베이스 형태가 어떻게 연결되어 있냐에 따라 클래스에 표시되는 방식이 다르다.
(아무것도 연결되어 있지 않으면 포린키가 없이 적힐 수도 있다.)

  • 클래스 메타의 경우 내가 데이터베이스 테이블에 저장되는 이름을 통제하고 싶을 때 사용한다. 여기서 띄어쓰기, 탭을 혼용할 경우 인덴트 에러가 나므로 주의해야한다.
from django.db import models


class Menu(models.Model):
    name = models.CharField(max_length=20)
    
    class Meta:
        db_table = "menu"


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

    class Meta:
        db_table = "categories"


class Drink(models.Model):
    korean_name  = models.CharField(max_length=50)
    english_name = models.CharField(max_length=50)
    description  = models.CharField(max_length=100)
    category     = models.ForeignKey('Category', on_delete=models.CASCADE)
    
    class Meta:
        db_table = "drinks"


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

    class Meta:
        db_table = "images"
    

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

    class Meta:
        db_table = "allergies"

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

    class Meta:
        db_table = "allergy_drinks"
    

class Nutrition(models.Model):
    one_serving_kcal = models.DecimalField(max_digits=5, decimal_places=2)
    sodium_mg        = models.DecimalField(max_digits=5, decimal_places=2)
    saturated_fat_g  = models.DecimalField(max_digits=5, decimal_places=2)
    sugars_g         = models.DecimalField(max_digits=5, decimal_places=2)
    protein_g        = models.DecimalField(max_digits=5, decimal_places=2)
    caffeine_mg      = models.DecimalField(max_digits=5, decimal_places=2)
    size_ml          = models.CharField(max_length=50)
    size_fluid_ounce = models.CharField(max_length=50)
    drink            = models.ForeignKey('Drink', on_delete=models.CASCADE)

    class Meta:
        db_table = "nutritions" 

문제에 조건에 따라 (모범 답안) 메뉴, 카테고리, 음료, 알러지 음료, 영양소, 이미지, 알러지로 나뉘어져 있었는데 _id 값에 따라 어떤 값이 어디에 물려있는지 판단하는데 오랜 시간이 걸리는 문제였다. 복습이 필요한 부분이다.

자꾸 빼먹는 부분인데, settings.py install 부분에 꼭 앱이 추가된 것을 추가해줘야 한다.

4. 만들어진 데이터와 Aquery보고 데이터베이스 CRUD해보기

  1. 환경 설정 : 먼저 왼쪽에는 VSC + 터미널 / 오른쪽은 Mysql을 띄워놨다.

  2. 장고 환경에서 수정이 완료되었다면 데이터 베이스로 보내는 작업을 해줘야 한다. 이를

  • 조립과 밀어넣기
    라고 하는데

조립 : python manage.py makemigrations
-> 이렇게 할 경우 이니셜파이라는 스키마가 하나 생긴다. 즉 작업 이력이 저장되는 것이다.
밀어넣기 : python manage.py migrate

  1. 환경설정이 완료되었다면 이제 python shell(장고 쉘)에 들어간다.
    python manage.py shell
    그리고 이번 모델 파이의 전체적인 클래스를 다 가져올 예정이므로 import를 다음과 같이 해준다.
    from products.models import *

단 파이썬 쉘을 나가면 다시 설정해줘야 한다. import를 전체로 한 이유는 아래 내용들이 모두 같은 앱에서 나오므로 조금 더 편하게 하려고 한 것이지 정답은 아니다.

이후 _id 값에 들어갈, 즉 포린 키 값이 필요한 경우는 C를 해줄 때 변수로 미리 만들어주고, 이후 클래스로 테이블을 만들 때 그 자리에 삽입해준다.

  • 변수 만드는 과정 :
m1 = Menu.objects.create(name="음료")
  • 테이블 하나 씩 채워나가는 과정 :
Category.objects.get(name="콜드 브루", menu=m1)
  • 여기서 한 실수 :
    여기서 create로 변수를 만들어 놓고 다음 테이블에서 또 create로 변수를 만들어 표가 4개가 아니라 8개가 된 경우가 생겼다. 즉 만들어지면서 동시에 변수를 선언했는데 그게 필요하다면 get을 쓰면 된다는 것이다.
    get은 요소를 딱 하나만 가져올 때 쓰는데 이 때 적합하게 쓸 수 있다.

제대로 한 예제

>>> from products.models import *
>>> c1 = Category.objects.get(name="콜드 브루")
>>> c2 = Category.objects.get(name="블렌디드")
>>> c3 = Category.objects.get(name="브레드")
>>> c4 = Category.objects.get(name="케이크")
>>> Drink.objects.create(korean_name = "나이크로 바닐라 크림", english_name="Nitro Vanila Cream", description = "부드러운 목넘김의 나이트로 커피와 바닐라 크림의 매력을 한번에 느껴보세요!", category=c1)
<Drink: Drink object (1)>
>>> Drink.objects.create(korean_name = "제주 비자림 콜드브루", english_name="Jeju Forest Cold Brew", description="[제주지역 한정음료] 제주 천년의 숲 비자림을 연상시키는음료로 제주에서 유기농 말차로 만든 파우더와 Cold Brew를 활용한 음료.", category=c1)             <Drink: Drink object (2)>
>>> Drink.objects.create(korean_name = "망고패션후르츠", english_name="Mango Passion Fruit Blended", description="망고 패션 후르츠  주스와 블랙 티가 깔끔하게 어우러진 과일 블렌디드", category=c2)
<Drink: Drink object (3)>
>>> Drink.objects.create(korean_name = "딸기요거트블렌디드", english_name="Strawberry Yogurt Blended", description="딸기와 요거트의 상큼함이 가득 느껴지는 가벼운 과일 블렌디드", category=c2)
  • 물론 그렇다고 방법이 없는 것은 아니다. id값이 조금 변하더라도 내가 설정한 키값이 유효하면 되기 때문에 여기서 수정할 수 있는 방법이 Update와 Delete다.

update :
Class명.objects.filter(age=33;예시).update(job=FireFighter)

delete :

Class명.objects.filter(위동일).delete()

여기서 지우고 싶은 id나 항목 명을 설정하면 그 칸을 통째로 지울 수 있다.

사실 두 번의 create 과정이 없었다면 이 과정을 알 수 없었을 것이다.

모쪼록 이 일련의 과정들을 반복하다보면 결과가 출력된다.

뭐 이런 과정들이었다. 꼭 한 번 다시 해봐야겠다. (다시 해보기 완료)

profile
커피 내리고 향 맡는거 좋아해요. 이것 저것 공부합니다.

0개의 댓글