본문 바로가기

인문학도 개발일지/웹프로그래밍

Build a Backend REST API with Python & Django - DB Setup

Django Model이란?

Model : 애플리케이션에 필요한 데이터를 describe하기 위해 필요

각각의 모델은 데이터베이스에 있는 특정한 테이블에 연결된다.

장고는 우리를 대신해서 모델과 데이터베이스 간 상호작용을 다룬다. 그래서 우리는 sql 문장을 쓴다거나 직접 데이터베이스와 상호작용 할 필요가 없다.

 

 

 

 

 

user database model 생성

1. user profile model

- 유저 프로필을 다루기 위해 필요

- 역할: 등록(가입)을 통해 유저를 생성, 로그인할 때 유저의 자격을 확인, 유저 제거

- 장고의 모든 모델은 profiles_api앱 > models.py에 저장된다.

- 장고는 별도의 설치나 구성 없이 사용할 수 있는 고유의 user 모델 'Django Admin'이 있다. 

- 따라서 지금 만들 것은 커스텀 user 모델!

- Substituting custom a user model: 장고에 내장된 유저 모델을 변경, 직접 유저 프로필을 시스템 상에서 컨트롤 할 수 있도록 만들기 위해 사용

- abstract base user: 장고 유저모델의 표준

- abstract base user를 불러와서 이 위에 새로 빌트할 것

- permissions mixin: 유저모델에 특정한 permission을 추가할 수 있는 것을 허용

- model은 class로 생성, UserProfile모델은 AbstractBaseUser 클래스와 PermissionsMixin 클래스 둘 모두를 상속받아 만든다.

- docstring을 작성해서 모델에 대해 정의하고, 다른 개발자와의 협업을 용이하게 한다.

- 장고 모델은 여러개의 필드로 구성된다.

- field: 우리가 객체로부터 모아서 데이터베이스에 저장하고 싶은 data의 조각(일부)

- 장고에서 사용할 수 있는 field 종류

 

Model field reference | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

- 가장 먼저 모을 field는 email 주소

- unique=True: 각각의 유저는 하나의 이메일만 사용할 수 있다.

- max_length: 글자 수 뿐만 아니라 다른 것도 검증할 수 있도록 해준다.

- is_active: 특정 유저가 현재 시스템에서 활성화 된 상태인지 확인, defaul는 True상태

- is_staff: True - 관리자, False - 익명의 사용자 

 

2. Object manager 설정

- user profile을 다루는 또 하나의 클래스- 관리자, 일반 유저 설정

 

3. Helper functions 생성

- get full name- get short name

- __str__(self): object를 string 타입으로 반환하기 위한 함수

 

여기까지 코드

models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin

# Create your models here.


class UserProfile(AbstractBaseUser, PermissionMixin):
    """Represent a "user profile" inside our system."""

    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        """Used to get a users full name"""

        return self.name

    def get_short_name(self):
        """Used to get a users short(first) name."""

        return self.name

    def __str__(self):
        """Django uses this when it needs to convert the object to a string
        """

        return self.email

 

 

 

 

 

user model manager 추가

- user profile을 위한 manager object를 만들어 보자.

- 유저 모델을 커스터마이징 했기 때문에 장고한테 어떻게 돌아가게 할 지 알려줘야 한다.

- profile 모델에 manager object를 만들어줘서 이 기능을 수행하도록 한다.

- 유저 패스워드 설정: set_password 함수를 호출. 상단에서 주어진 패스워드를 패스워드로 설정할 것이다. 상단 user 객체를 만들 때 패스워드를 인자로 함께 부여하지 않은 이유는 set password 함수가 패스워드를 "암호화"해야하기 때문. set password 함수는 기본적으로 패스워드로 주어진 문자열을 데이터베이스에 저장되는 해시로 변환한다. 따라서 유저의 실질적으로 정확한 문자 패스워드는 시스템에 절대 저장되지 않는다. 데이터베이스 관리자가 볼 수 있는 것도 해시값으로 변환된 패스워드이지 실제로 유저가 입력한 명확한 패스워드는 아니다.

 

여기까지 코드

models.py

from django.contrib.auth.models import BaseUserManager

class UserProfileManager(BaseUserManager):
    """Helps Django work with our custom user model.
    """

    def create_user(self, email, name, password=None):
        """Creates a new user profile object.""" 

        # check email address
        if not email:    # doesn't exist
            raise ValueError('존재하지 않는 계정입니다.')

        # normalize email address
        email = self.normalize_email(email)
        user = self.model(email=email, name=name)

        user.set_password(password)
        user.save(using=self._db)    # _db: use the same db that we created with the user profile manager

        return user

 

 

 

 

 

 

super user 생성 함수

- 패스워드 default가 None이 아니다. 왜냐하면 super user를 위한 패스워드가 필요하기 때문

def create_superuser(self, email, name, password):
        """Creates and saves a new superuser with given details.
        """

        user = self.create_user(email, name, password)

        user.is_superuser = True
        user.is_staff = True

        user.save(using=self._db)

        return user

 

 

 

 

 

models.py 전체 코드 확인

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager

# Create your models here.


class UserProfileManager(BaseUserManager):
    """Helps Django work with our custom user model.
    """

    def create_user(self, email, name, password=None):
        """Creates a new user profile object."""

        # check email address
        if not email:    # doesn't exist
            raise ValueError('존재하지 않는 계정입니다.')

        # normalize email address
        email = self.normalize_email(email)
        user = self.model(email=email, name=name)

        user.set_password(password)
        # _db: use the same db that we created with the user profile manager
        user.save(using=self._db)

        return user

    def create_superuser(self, email, name, password):
        """Creates and saves a new superuser with given details.
        """

        user = self.create_user(email, name, password)

        user.is_superuser = True
        user.is_staff = True

        user.save(using=self._db)

        return user


class UserProfile(AbstractBaseUser, PermissionsMixin):
    """Represent a "user profile" inside our system."""

    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        """Used to get a users full name"""

        return self.name

    def get_short_name(self):
        """Used to get a users short(first) name."""

        return self.name

    def __str__(self):
        """Django uses this when it needs to convert the object to a string
        """

        return self.email

 

 

 

 

 

커스텀 user model 세팅

profiles_project>settings.py

가장 하단에 아래 코드를 추가해서 장고에게 우리가 기본값이 아닌 커스터마이징한 유저 모델을 사용할 것이란 것을 알려준다.

models.py에 모든 모델이 저장되는 것이 기본이기 때문에 어떤 애플리케이션의 어떤 모델인지만 설정하면 된다.

AUTH_USER_MODEL = 'profiles_api.UserProfile'

 

 

 

 

 

migrations 생성, DB 연동

Database migrations: 자동으로 우리가 모델에서 변경한 것을 기반으로 데이터베이스를 생성, 변경하기 위해 사용될 수 있다. 현재의 데이터베이스와 모델의 상태를 살펴보고 무엇이 달라졌는지 확인한다. 장고는 이 모든 것을 백그라운드에서 작동시킴으로써 우리의 작업 시간을 단축시켜준다.

 

gitbash vagrant 서버 접속 후, 가상환경 내 프로젝트 위치에서 아래 명령어 입력

python manage.py makemigrations

→ 우리가 위에서 만든 모델과 데이터베이스를 체크하고 우리가 모델에서 변경한 데이터베이스 내에서의 모든 변경사항을 담고 있는 migration파일을 생성한다. 첫 마이그레이션이기 때문에 현재는 데이터베이스가 존재하지 않는다. 따라서 장고는 자동적으로 처음 데이터베이스를 설정할 마이그레이션을 생성한다.

- Create model UserProfile 확인앱 내에 migrations 폴더와 지금까지 우리가 만든 변경 사항을 담은 첫 마이그레이션 파일이 생긴다. 마이그레이션 파일은 장고에게 어떻게 우리의 데이터베이스를 설정할 것인지 알려주는 역할을 한다.

 

 

데이터베이스 생성을 위한 마이그레이션 실행

python manage.py migrate

이 명령을 통해 모든 데이터베이스 마이그레이션을 거치고 데이터베이스에서 그 데이터베이스 마이그레이션을 실행한다.