[Django] Django Model

문지은·2023년 4월 20일
0

Django 기초

목록 보기
5/14
post-thumbnail

Django는 웹 애플리케이션의 데이터를 구조화하고 조작하기 위한 추상적인 계층(Model)을 제공한다.
Model의 핵심 개념과 ORM을 통해 데이터베이스를 조작하는 방법에 대해 알아보자.


Model

  • Django는 Model을 통해 데이터에 접근하고 조작
  • 사용하는 데이터들의 필수적인 필드들과 동작을 포함
  • 지정된 데이터베이스의 구조 (layout)
  • 일반적으로 각각의 모델은 하나의 데이터베이스 테이블에 매핑(mapping)
    • 모델 클래스 1개 == 데이터베이스 테이블 1개
  • Model을 통해 데이터 관리

Model 작성하기

  • Model을 작성하기 위해 프로젝트(crud)를 생성하고 앱(articles)를 작성 및 등록하였다.
$ django-admin startproject crud .
$ python manage.py startapp articles
# settings.py

INSTALLED_APPS = [
		'articles',
		...
]

models.py 작성

  • 모델 클래스를 작성하는 것은 데이터베이스 테이블의 스키마를 정의하는 것이다.
  • 모델 클래스 == 테이블 스키마
  • id 컬럼은 테이블 생성 시 Django가 자동으로 생성된다.
# articles/models.py

class Article(models.Model):
		title = models.CharField(max_length=10)
		content = models.TextField()

Model 이해하기

  • 각 모델은 django.models.Model 클래스의 서브 클래스
    • 즉, 각 모델은 django.db.models 모듈의 Model 클래스를 상속받아 구성됨
    • 클래스 상속 기반 형태의 Django 프레임워크 개발

  • models 모듈을 통해 어떠한 타입의 DB 필드(컬럼)을 정의할 것인지 정의
    • Article에는 어떤 데이터 구조가 필요한지 정의
    • 클래스 변수 title과 content는 DB 필드를 나타냄

Django Model Field

  • Django는 모델 필드를 통해 테이블의 필드(컬럼)에 저장할 데이터 유형(INT, TEXT 등)을 정의
  • 데이터 유형에 따라 다양한 모델 필드를 제공

CharField(max_length=None, **options)

  • 길이의 제한이 있는 문자열을 넣을 때 사용
  • max_length
    • 필드의 최대길이(문자)
    • CharField의 필수 인자
    • 데이터베이스와 Django의 유효성 검사(값을 검증하는 것)에서 활용됨

TextField(**options)

  • 글자의 수가 많을 때 사용
  • max_length 옵션 작성 시 사용자 입력 단계에서는 반영되지만, 모델과 데이터베이스 단계에서는 적용되지 않음 (CharField 를 사용해야 함)
    • 실제로 저장될 때 길이에 대한 유효성을 검증하지 않음

지금까지 작성한 models.py는 데이터베이스 스키마를 정의한 것이다.
이제 이러한 모델의 변경사항을 실제 데이터베이스에 반영하기 위한 과정이 필요하다.

Migrations

Migrations 관련 주요 명령어

makemigrations

  • 모델의 변경사항에 대한 새로운 migration을 만들 때 사용
  • 명령어 실행 후 migrations/0001_initial.py 가 생성된 것을 확인
$ python manage.py makemigrations

migrate

  • makemigrations로 만든 설계도를 실제 데이터베이스에 반영하는 과정 (db.sqlite3 파일에 반영)
  • 결과적으로 모델의 변경사항과 데이터베이스를 동기화
  • 설계도(migration)를 실제 db.sqlite3 DB 파일에 반영
$ python manage.py migrate

[참고] Migrations 기타 명령어

  1. showmigrations

    • migrations 파일들이 migrate 됐는지 안됐는지 여부를 확인하는 용도
    • [ x ] 표시가 있으면 migrate가 완료되었음을 의미
    $ python manage.py showmigrations
  2. sqlmigrate

    • 해당 migrations 파일이 SQL 문으로 어떻게 해석될 지 미리 확인할 수 있음
    $ python manage.py sqlmigrate articles 0001

반드시 기억해야할 migration 3단계

  1. models.py에서 변경사항이 발생하면
  2. migration 생성 makemigrations
  3. DB 반영 (모델과 DB의 동기화) migrate

이제 ORM을 통해 DB를 객체로 조작하는 방법에 대해 알아보자.

ORM

  • Object-Relational-Mapping
  • 객체지향 프로그래밍 언어를 사용하여 호환되지 않는 유형의 시스템 간에 (Django ↔ DB) 데이터를 변환하는 프로그래밍 기술
  • 객체 지향 프로그래밍에서 데이터베이스를 연동할 때, 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법
  • Django 는 내장 Django ORM을 사용
  • 한마디로 SQL을 사용하지 않고 데이터베이스를 조작할 수 있게 만들어주는 매개체

QuerySet API

Database API

  • Django가 제공하는 ORM을 사용해 데이터베이스를 조작하는 방법
  • Model을 정의하면 데이터를 만들고 읽고 수정하고 지울 수 있는 API 제공
  • [Model class].[Manager].[Queryset API]

Object manager

  • Django 모델이 데이터베이스 쿼리 작업을 가능하게 하는 인터페이스
  • Django는 기본적으로 모든 Django 모델 클래스에 대해 objects 라는 Manager 객체를 자동으로 추가함
  • 이 Manager를 통해 특정 데이터를 조작할 수 있다.
  • DB를 Python class로 조작할 수 있도록 여러 메서드를 제공하는 manager

Query

  • 데이터베이스에 특정한 데이터를 보여달라는 요청
  • 파이썬으로 작성한 코드가 ORM에 의해 SQL로 변환되어 데이터베이스에 전달되며, 데이터베이스의 응답 데이터를 ORM이 QureySet 이라는 자료 형태로 변환하여 우리에게 전달

QuerySet

  • 데이터베이스에게서 전달 받은 객체 목록(데이터 모음)
    • 순회가 가능한 데이터로써 1개 이상의 데이터를 불러와 사용할 수 있음
  • Django ORM을 통해 만들어진 자료형이며, 필터를 걸거나 정렬 등을 수행할 수 있음
  • objects manager를 사용하여 복수의 데이터를 가져오는 queryset method를 사용할 때 반환되는 객체
  • 단, 데이터베이스가 단일한 객체를 반환할 때는 QuerySet이 아닌 모델(Class)의 인스턴스로 반환됨

QuerySet API

  • QuerySet 과 상호작용하기 위해 사용하는 도구 (메서드, 연산자 등)

CRUD

  • Create / Read / Update / Delete
    • 생성 / 조회 / 수정 / 삭제
  • 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능 4가지를 묶어서 일컫는 말

CREATE

데이터 객체 만드는 방법 1 - article = Article()

  • 클래스를 통한 인스턴스 생성
# 특정 테이블에 새로운 행을 추가하여 데이터 추가 
>>> article = Article()  # Article(class)로부터 article(instance)
>>> article
<Article: Article object (None)>

>>> article.title = 'first'  # 인스턴스 변수(title)에 값을 할당
>>> article.content = 'django!'  # 인스턴스 변수(content)에 값을 할당

# save 를 하지 않으면 아직 DB에 값 저장되지 않음
>>> article
<Article: Article object (None)>

>>> Article.objects.all()
<QuerySet []>
  • save 메서드를 호출해야 비로소 DB에 데이터가 저장됨 (레코드 생성)
# save를 하고 확인하면 저장된 것 확인할 수 있다. 

>>> article.save()

>>> article
<Article: Article object (1)>

>>> article.id
1

# DB 테이블의 컬럼 이름이 id임에도 pk를 사용할 수 있는 이유는 Django가 제공하는 shortcut이기 때문
>>> article.pk
1

>>> Article.objects.all()
<QuerySet [<Article: Article object (1)>]>
# 인스턴스인 article을 활용하여 변수에 접근하기

>>> article.title
'first'

>>> article.content
'django!'

데이터 객체 만드는 방법 2 - article.title

  • 클래스 변수명과 같은 이름의 인스턴스 변수를 생성 후 값 할당
# 인스턴스 생성시 초기값을 함께 작성하여 생성

>>> article = Article(title='second', content='django!')

# 아직 저장되어 있지 않음
>>> article
<Article: Article object (None)>

# save 호출해야 저장
>>> article.save()

>>> article
<Article: Article object (2)>

>>> Article.objects.all()
<QuerySet [<Article: Article object (1)>, <Article: Article object (2)>]>
# 값 확인

>>> article.pk
2

>>> article.title
'second'

>>> article.content
'django!'

데이터 객체 만드는 방법 3 - article.save()

  • 인스턴스로 save 메서드 호출
  • QuerySet API 중 create() 메서드 활옹
# 위 2가지 방식과는 다르게 바로 생성된 데이터가 반환된다.

>>> Article.objects.create(title='third', content='django!')
<Article: Article object (3)>
  • 세 방법 모두 실행한 결과

.save()

  • 객체를 데이터베이스에 저장함
  • 데이터 생성 시 save를 호출하기 전에는 객체의 id 값은 None
    • id 값은 Django가 아니라 데이터베이스에서 계산되기 때문
  • 단순히 모델 클래스를 통해 인스턴스를 생성하는 것은 DB에 영향을 미치지 않기 때문에 반드시 save를 호출해야 테이블에 레코드가 생성됨

READ

  • QuerySet API method를 사용해 데이터를 다양하게 조회하기
  • QuerySet API method는 크게 2가지로 분류
    1. Methods that “return new querysets”
    2. Methods that “do not return querysets”

all()

  • QuerySet return
  • 전체 데이터 조회
>>> Article.objects.all()
<QuerySet [<Article: Article object (1)>, <Article: Article object (2)>, <Article: Article object (3)>]>

get()

  • 단일 데이터 조회
  • 객체를 찾을 수 없으면 DoesNotExist 예외를 발생시키고, 둘 이상의 객체를 찾으면 MultipleObjectsReturned 예외를 발생시킴
  • 위와 같은 특징을 가지고 있기 때문에 primary key와 같이 고유성(uniqueness)을 보장하는 조회에서 사용해야 함
>>> Article.objects.get(pk=1)
<Article: Article object (1)>

>>> Article.objects.get(pk=100)
DoesNotExist: Article matching query does not exist.

>>> Article.objects.get(content='django!')
MultipleObjectsReturned: get() returned more than one Article -- it returned 3!

Filter

  • 지정된 조회 매개 변수와 일치하는 객체를 포함하는 새 QuerySet 을 반환
  • 조회된 객체가 없거나 1개여도 QuerySet을 반환
>>> Article.objects.filter(content='django!')
<QuerySet [<Article: Article object (1)>, <Article: Article object (2)>, <Article: Article object (3)>]>

>>> Article.objects.filter(title='ssafy')
<QuerySet []>

In [35]: Article.objects.filter(title='first')
<QuerySet [<Article: Article object (1)>]>

Field lookups

# Field lookups 예시

# content 칼럼에 'dj'가 포함된 모든 데이터 조회
>>> Article.objects.filter(content__contains='dj')
<QuerySet [<Article: Article object (1)>, <Article: Article object (2)>, <Article: Article object (3)>]>

Update

  1. 수정하고자 하는 article 인스턴스 객체를 조회 후 반환 값을 저장
  2. article 인스턴스 객체의 인스턴스 변수 값을 새로운 값으로 할당
  3. save() 인스턴스 메서드 호출
>>> article = Article.objects.get(pk=1)

# 인스턴스 변수 변경
>>> article.title = 'byebye'
    
# 저장
>>> article.save()
    
# 정상적으로 변경 된 것 확인
>>> article.title
>>> 'byebye'

Delete

  1. 삭제하고자 하는 article 인스턴스 객체를 조회 후 반환 값을 저장
  2. delete() 인스턴스 메서드 호출
>>> article = Article.objects.get(pk=1)
    
# delete 메서드 호출
>>> article.delete()
(1, {'articles.Article': 1})
    
# 1번 데이터는 이제 조회할 수 없음
>>> Article.objects.get(pk=1)
DoesNotExist: Article matching query does not exist.

profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글