daniel7481의 개발일지

[Django] Database & Admin Panel 본문

Django

[Django] Database & Admin Panel

daniel7481 2021. 12. 24. 22:35
반응형

먼저 migration이라는 용어에 대한 검색을 해봤다

migration

-데이터나 소프트웨어를 한 시스템에서 다른 시스템으로 이동하는 것

예시

-애플리케이션 또는 운영 체제(OS) 업그레이드

-데이터를 한 종류의 데이터베이스에서 다른 종류의 데이터베이스로 이동

-하나의 데이터 스토리지 시스템을 다른 데이터 스토리지 시스템으로 교체

-온프레미스 인프라에서 클라우드 인프라로 이동

-모눌리식 애플리케이션을 컨테이너화된 서비스로 교체

출처: https://www.redhat.com/ko/topics/automation/what-is-it-migration

대부분 무슨 말을 하는 것인지는 모르겠지만, 일단 간단하게 하나의 DB에서 다른 DB로 이동하는 것, 혹은 다른 저장장치로 이동하는 것이라고 이해하면 될 것 같다.

현재 python manage.py runserver를 하면 you have 18 unapplied migration이라는 경고문이 뜬다. python manage.py migration을 터미널에 입력하고 runserver를 하면 이러한 경고문이 사라지는 것을 볼 수 있다. 이제 우리가 데이터를 직접 입력하지 않고 DB에서 가지고 올려고 할 때 장고는 이미 settings.py에서 INSTALLED_APPS에 여러가지 테이블을 준비해놨다. 이는 기본값으로 되어있지만 이는 DB에서 쿼리를 이용할때나 데이터를 가져올때 효과적으로 사용할 수 있다.

base예하의 models.py에서 우리는 데이터베이스 모델을 만들 것이다. 간략하게 얘기하자면 Project라는 클래스를 만들고 그 안에 attribute들은 columns가 될 것이다. 이런 RDBMS 모델은 다른 프레임워크에서도 사용된다고 한다. 

먼저 Room이라는 클래스를 만들자(클래스는 암묵적으로 앞글자를 대문자로 나타낸다). 그 안에 attribute으로 host, topic, name, description이 있을 것이다. name = models.CharField(max_length = 200)으로 선언한다. 이름의 최대길이가 200이라는 제한을 걸어두는 것이다. description = models.TextField(null = True, blank = True)로 선언할 것인데, 원래라면 아무런 값도 입력받지 않는 것(NULL)은 불가하다. null = True는 그 값을 비어있어도 된다는 의미이다. 이 뒤에 blank = True는 description에 아무런 값을 넣지 않아도 된다는 것이다. 앞에 null= True는 DB를 위한 명령어다.  CharField와 TextField는 문자열을 받는 메소드지만 대용량의 텍스트를 받을 때에는 TextField를 사용한다. 우리 사이트는 사람들이 description을 넣지 않아도 되는 것을 허용한 것이다. 그 밑으로 participants, updated, created변수를 선언하는데 각 변수가 사용되는 방법은 차후에 설명하겠다. updated은 변화가 있을때마다 자동으로 저장해주는 기능을 하고, created은 이 게시물이 만들어진 시간을 저장하는 것이다. 변수들은 다음과 같다

from django.db import models

class Room(models.Model):
    #host =
    #topic =
    name = models.CharField(max_length=200)
    description = models.TextField(null = True)
    #participants
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

updated과 created의 차이점은 auto_now, auto_now_add인데 전자는 매 순간마다 계속해서 시간을 입력을 받는 것이고 후자는 만들어질때, 혹은 저장이 될때에만 시간을 입력받는것이다. 

이제 admin 인터페이스가 필요하다. 장고에서는 admin 인터페이스를 제공하지만, 나중에는 직접 만들어보도록 하자. 지금으로써는 장고에서 제공하는 서비스를 이용하기로 한다. 먼저 그 전에 python manage.py migrate으로 모든 DB를 ㅡmakemigrations를 해준다. 이러면 base 예하에 migrations 폴더에 새로운 파일이 생성되는데 거기에 migrate되는 모델이 적혀있다. 우리 같은 경우에는 Room이라는 클래스를 migrate했으므로 name = 'Room'이라는 항목이 있을 것이다. 이제 python manage.py migrate으로 migrate을 완료하고 서버 url http://127.0.0.1:8000/admin/으로 들어가서 로그인을 해준다. 계정이 없으므로 python manage.py createsuperuser로 관리자 계정을 만든다. 그 다음 id, email, password를 입력하고 로그인하면 이제 DB를 관리를 할 수 있다. Django administration에는 Groups, Users라는 항목이 있는데 우리가 생성한 Rooms라는 모델은 보이지 않는다. 이를 해결하기 위하여 base 예하에 admin.py를 들어간 후 .models에서 Rooms를 import한 다음에 admin.site.register(Room)을 해준다. 이러면 Rooms 항목이 생기는데 여기서 Add를 해준 후 여러 개의 방을 만들자. 

이제 views.py에서 rooms라는 변수를 선언하고 참조하는 것이 아니라 DB에서 데이터를 가져와서 참조할 것이다. 여기서 일단 views.py에 들어가서 models 모듈에서 Room class를 import해준다. 그 다음 변수 = 모델이름.objects.함수로 불러올 수 있다. 여기서 함수는 all(), .get(), .filter(), .exclude()가 있다. 이제 home함수에서 rooms = Room.object.all()로 모든 Roo의 데이터를 가져오고, room 함수에서는 특정 room의 id와 이름만 필요하므로 room = Room.object.get(id=pk)를 해준다. 이제 DB에 접근해서 데이터를 쿼리할 수 있다. 이제 새로운 모델을 만들어보자. 

class Message(models.Model):
    #user =
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    body = models.TextField()
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

각 room에 대하여 나타낼 Message 클라스를 만들었다. 여기서 1대N, N대1 관계형 모델의 개념이 필요한데, 한 사람이 여러 개의 글을 포스트하면 그 사람(Primary Key)을 참조하여 같은 키를 공유할 수 있다. 여기서 room이 Room모델에서 가져온 외래키이다.  뒤에 delete=models.CASCADE는 만약 참조하는 외래키가 삭제되었을 시, 이 모델또한 삭제된다는 것이다(연쇄 삭제). 장고에서는 기본적으로 제공하는 몇가지 attribute가 있다. 그 중 User를 사용할 것인데, from.django.contrib.auth.models에서 User를 import해준다. 이제 Message 클라스에서 User attribute을 외래키로 가져온다. 위에서 Room클라스를 만들 때 host와 topic을 주석 처리하였는데, host는 User에서 외래키를 참조하고 topic은 Topic이라는 클라스를 만들어서 name이라는 attribute을 CharField로 생성한 후에 참조해 준다. 클라스를 다 만든 모습은 다음과 같다.

from django.db import models
from django.contrib.auth.models import User


class Topic(models.Models):
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name


class Room(models.Model):
    host = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, null=True)
    name = models.CharField(max_length=200)
    description = models.TextField(null = True)
    #participants
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.name)


class Message(models.Model):
    #user =
    user = models.Foreignkey(User, on_delete = models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    body = models.TextField()
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.body[0:50]

자 이제 모든 모델이 완료되었으니 적용만 하면 된다. 위 내용을 저장한 후에 localhost의 admin페이지에 들어가면 이제 ㄲoom뿐만 아니라 Topic, Message도 생긴 것을 볼 수 있다. 이제 User에 들어간 후 새로운 계정을 하나 만들고, Room에 Topic과 User를 정해주자. ForeignKey로 관계를 정해주었기 때문에 User, Topic등이 나타난 것을 볼 수 있다. 이제 Message에 들어가서 각 글에 대하여 답글을 달 수도 있다. 이제 html에 나타내줘야 하는데, home.html을 다음과 같이 바꿔주자

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>
    {% extends 'main.html' %}
    {% block content %}
    <h1>Home Template</h1>
    <div>
        <div>
        {% for room in rooms %}
            <div>
                <span>{{room.host.username}}</span>
                <h5>{{room.id}} -- <a href="/room/{{room.id}}">{{room.name}}</a></h5>
                <small>{{room.topic.name}}</small>
                <hr>
            </div>
        {% endfor %}
        </div>
    </div>
    {% endblock %}
</body>
</html>

이제 작성한 사람, 제목, topic이 차례대로 나열되는 것을 알 수 있다.

반응형

'Django' 카테고리의 다른 글

[Django] Getting started  (0) 2021.12.24