이전 글에서는 장고의 기본 구조와 프로젝트, 앱 생성에 대해 알아보았다. 장고 웹 프레임워크는 MVC 패턴을 따르고 있는데, 이에 대해 우선 잠시 살펴보겠다.
MVC패턴 그리고 장고의 MTV
MVC(Model-View-Controller) 패턴은 애플리케이션을 3가지로 구분한 디자인 패턴이다. 여기서 Model은 데이터를 관리하고, View는 레이아웃과 화면을, Controller는 모델과 뷰를 잇는 역할을 한다.
장고는 MVC패턴의 각각을 MTV(Model-Template-View)라는 이름으로 구현했다. 즉 Model은 Model 그대로, MVC패턴에서 View의 기능은 장고의 Template에 대응하고. 그리고 MVC의 Controller는 장고의 View에 대응한다.
MVC 패턴 | 장고의 MTV |
Model | Model |
View | Template |
Controller | View |
그렇기에 앞으로 몇 개의 포스트 간 Model, View, Template, 그리고 여기에 더해 Url 기능을 소개하려 한다. 그럼 MTV의 소개가 끝났으니 본격적인 모델로 들어가 보겠다.
모델(Model)
모델은 MVC패턴에서 데이터 저장을 담당하는 부분이다. 즉 뷰에서 바로 DB로 연결할 필요 없게, 모델에서 일괄적으로 DB 접근등 데이터를 담당하는 것이다.
장고에서는 이런 모델을 models.py 파일에서 관리하고 있다.
models.py
장고에서 모델을 작성하는 방법은 models.py에 장고 기능을 이용하여 모델과 필드를 작성하고 이를 migrate 하면, 이 정보를 토대로 장고 ORM이 자동으로 관계형 DB의 테이블과 필드를 작성해 준다.
ORM(Object Relational Mapping), Django ORM
ORM이란 객체와 관계형 DB의 데이터를 자동으로 맵핑해 주는 것이다. 이를 처리해 주는 프로그램으로 Django ORM이라 TypeORM 등이 존재한다. 장고에서는 기본적으로 강제로 Django ORM을 사용하며, ORM으로 자동작성된 것보다 효율적인 쿼리가 필요하면 수동으로 쿼리를 작성할 수도 있다.
장고에서 모델 작성하는 방법
models.py에 모델 작성
모델을 다음과 같은 방식으로 작성한다.
# books/models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(null=True)
class Book(models.Model):
title = models.TextField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)
page_count = models.IntegerField(null=True)
위 코드에서 models.Model을 상속받는 Author과 Book이 모델로, DB에서 테이블과 맵핑된다. 그리고 모델 내부에 선언된 name, age, title, author, page_count 등이 필드로 DB에서 테이블의 필드와 맵핑된다.
각 필드는 데이터 타입에 맞추어 TextField, IntegerField 등 다양한 필드를 사용할 수 있으며, 관계형 DB를 이용하기에 모델 간의 관계를 표현하기 위해 ForeignKey나 ManyToManyField 등을 사용할 수 있다.
위와 같이 모델을 models.py에 정의했다면 이를 실제 DB에 반영해야 할 것이다.
모델 migration 만들기
작성한 모델을 DB에 반영하기 위해서는 작성한 모델에 대한 migration을 만들고, 이를 migrate 해 실제 DB에 반영해야 한다. 그럼 migration을 만드는 방법을 알아보자.
우선 우리의 앱이 settings.py의 INSTALLED_APPS에 제대로 포함이 되었는지 확인해 보자.
# django_basic/settings.py
INSTALLED_APPS = [
...
"books",
]
위와 같이 우리가 생성한 앱이 포함되어 있어야 migration을 받을 수 있다. 이렇게 제대로 포함되어 있는 것을 확인하였으면 다음 명령어를 사용해 books앱의 migration을 만들 수 있다.
python manage.py makemigrations books
# 또는 다음 명령어로 전체 앱의 migration을 생성할 수 있다
python manage.py makemigraions
# Migrations for 'books':
# books/migrations/0001_initial.py
# - Create model Author
# - Create model Book
실제 DB에 migrate 하기
이렇게 모델에 대한 migration 파일이 제작되었다면, 실제 모델에 migrate를 진행할 수 있다. 즉 기본적으로 설정된 장고의 모델은 SQLite인데, SQLIte파일인 db.sqlite3에 실제 migrate가 되는 것이다. migrate는 다음 명령어로 적용할 수 있다.
python manage.py migrate
'''
Operations to perform:
Apply all migrations: admin, auth, books, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying books.0001_initial... OK
Applying sessions.0001_initial... OK
'''
최초 migrate를 하는 것이어서 작성했던 books 외에도 여러 장고 기본앱이 migrate 된 것을 볼 수 있다.
이렇게 migrate를 진행하면 비로소 설정한 모델을 사용할 수 있는 상태가 된다.
여기까지 진행했을 때의 파일 구성: Github
Shell을 이용하여 모델 다루기
이렇게 모델을 생성하고 반영하는 것 까지 마쳤다면, 이제 모델을 활용하여 데이터를 interactive하게 추가해 보는 방법을 알아보자.
장고에서는 다음 명령어를 통해 shell을 실행할 수 있다.
python manage.py shell
그럼 여기서 만들었던 Author 모델을 다시 한번 살펴보자.
class Author(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(null=True)
Author 객체는 이름과 나이 필드를 가지고 있다. 그럼 새로운 작가 모델을 생성하고 모델을 탐색하는 방법을 알아보자.
# 만들었던 Author 모델을 books앱에서 가져 온다
>>> from books.models import Author
# 모든 Author 모델을 가져온다. 이때 아직 생성된게 없으니 빈 쿼리셋이 리턴된다
>>> Author.objects.all()
<QuerySet []>
# 새로운 작가를 생성한다. 이때 create는 생성을 마친후 모델을 반환하는데, 이를 honobu라는 이름으로 작가 객체를 받았다
>>> honobu = Author.objects.create(name="요네자와 호노부", age=45)
# honobu의 내용을 출력한다. 작가 객체를 반환 받은것을 알 수 있다
>>> honobu
<Author: Author object (1)>
# 작가의 정보 데이터를 객체에서 정상적으로 찾을 수 있다
>>> honobu.name
'요네자와 호노부'
# 작가 요네자와 호노부는 처음으로 생성된 작가이기에 id = 1을 할당 자동으로 할당받았다.
# 이를 get()을 이용해 탐색할 수 있고, id뿐만 아니라 name등으로도 탐색 가능하다.
>>> Author.objects.get(id=1)
<Author: Author object (1)>
>>> Author.objects.get(name="요네자와 호노부")
<Author: Author object (1)>
# 존재하지 않는 모델을 탐색하면 오류를 발생한다.
>>> Author.objects.get(id=2)
Traceback (most recent call last):
...
books.models.Author.DoesNotExist: Author matching query does not exist.
# 처음 시도했을 때는 빈 쿼리셋을 반환했으나, 지금은 작가 모델 하나가 추가된 것을 볼 수 있다.
>>> Author.objects.all()
<QuerySet [<Author: Author object (1)>]>
위와 같은 방식으로 모델을 create()로 생성하고, get()으로 탐색하는 방법을 알아보았다.
이때 쿼리셋이란 모델 객체의 목록이다. 이를 자세히 이해하기 위해 아래의 예제를 보자.
# 새로운 작가를 생성한다
>>> Author.objects.create(name="히가시노 게이고", age=45)
<Author: Author object (2)>
# 모든 작가를 탐색한다. 이때 작가 모델들의 리스트인 쿼리셋이 반환된다
>>> Author.objects.all()
<QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
# filter()은 get()과 달리 조건이 맞는 모든 모델을 쿼리셋으로 반환한다
>>> Author.objects.filter(age=45)
<QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
# 이때 조건에 맞는 모델을 여러개라면 오류를 발생시킨다
>>> Author.objects.get(age=45)
Traceback (most recent call last):
...
books.models.Author.MultipleObjectsReturned: get() returned more than one Author -- it returned 2!
# 마지막으로 예시 하나를 더 보인다
>>> Author.objects.get(id=1)
<Author: Author object (1)>
>>> Author.objects.filter(id=1)
<QuerySet [<Author: Author object (1)>]>
>>> Author.objects.filter(id=1)[0]
<Author: Author object (1)>
get()과 달리 all()과 filter()는 쿼리셋을 리턴하는 방식임을 알아보았다.
이번 글에서는 shell을 이용해서 모델을 다루었는데, 나중에 이와 비슷한 방식으로 뷰에서 모델을 다루어볼 예정이다.
'서버(Server) > 장고 (Django)' 카테고리의 다른 글
[Django Basic] 3.1. URL심화 (0) | 2023.07.15 |
---|---|
[Django Basic] 3. URL, urls.py, URLConf, path (0) | 2023.07.15 |
[Django Basic] 1.4. Applications, apps.py, AppConfig (0) | 2023.07.15 |
[Django Basic] 1.3. manage.py, django-admin (0) | 2023.07.15 |
[Django Basic] 1.2. 장고 앱 배포하기 (0) | 2023.07.15 |