해리의 데브로그

Django 04 - Models.py 를 통한 DB 다루기 및 CRUD 구현

|

Django에서 데이터 베이스 다루기

Django 내에서 models.py 라는 파일을 통해 데이터베이스를 어떻게 다루고 활용하는지 살펴보자.

Models.py

  • Django에서는 모델이라는 파이썬 객체를 통해 데이터에 접속하고 관리함
  • 모델: 저장된 데이터의 구조(Schema)를 정의함. ex) 필드타입, 데이터의 최대크기, 기본값 등
  • 모델은 Django 웹 어플리케이션 내 models.py 에서 정의됨. 이들은 django.db.models.Model 를 상속받은 서브(파생) 클래스로 구현되며, 필드, 메서드, 메타데이터등을 포함 할 수 있음.
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

필드(Fields)

  • 데이터 베이스 테이블의 열을 나타냄. 즉, 각각의 필드는 DB 목록(table)에 저장하길 원하는 데이터 열을 나타냄.
  • 위의 예시에서는 titlecontent 라는 두개의 필드를 갖고 있음. title의 경우, CharField 라는 필드타입을 가지고 있음. 필드 타입은 특정한 클래스를 사용하여 등록되며, HTML 양식(즉, 유효값을 구성하는)에서 값을 수신할 때, 사용할 유효성 검증 기준과 함께 데이터베이스에서 데이터를 저장하는 데 사용되는 레코드의 타입을 결정함.
  • 필드타입은 또한 필드가 어떻게 저장되고, 사용될지 지정하는 인수를 사용할 수 있음.
    • 예) max_length=100 : 이 필드에서 값의 최대 길이는 100자라는 것을 알림.
  • 필드 타입의 종류
Field Type 설명
CharField 제한된 문자열 필드 타입. 최대 길이를 max_length 옵션에 지정해야 한다. 문자열의 특별한 용도에 따라 CharField의 파생클래스로서, 이메일 주소를 체크를 하는 EmailField, IP 주소를 체크를 하는 GenericIPAddressField, 콤마로 정수를 분리한 CommaSeparatedIntegerField, 특정 폴더의 파일 패스를 표현하는 FilePathField, URL을 표현하는 URLField 등이 있다.
TextField 대용량 문자열을 갖는 필드
IntegerField 32 비트 정수형 필드. 정수 사이즈에 따라 BigIntegerField, SmallIntegerField 을 사용할 수도 있다.
BooleanField true/false 필드. Null 을 허용하기 위해서는 NullBooleanField를 사용한다.
DateTimeField 날짜와 시간을 갖는 필드. 날짜만 가질 경우는 DateField, 시간만 가질 경우는 TimeField를 사용한다.
DecimalField 소숫점을 갖는 decimal 필드
BinaryField 바이너리 데이타를 저장하는 필드
FileField 파일 업로드 필드
ImageField FileField의 파생클래스로서 이미지 파일인지 체크한다.
UUIDField GUID (UUID)를 저장하는 필드

Migrations

  • Django에서 Model 클래스를 생성하고 난 후, 해당 모델에 상응하는 테이블을 데이터베이스에서 생성할 수 있음. Python 모델 클래스를 DB에 적용하는 과정을 Migration이라고 함.

  • 모델의 변경 내역을 DB Schema(데이터베이스 데이터 구조)로 반영시키는 효율적인 방법을 제공.
    • python manage.py makemigrations : 마이그레이션 파일(초안) 생성
    • python manage.py migrate : 해당 마이그레이션 파일을 실제 데이터 베이스에 반영(적용)
  • 모델 클래스 생성 후, 위의 명령어를 반드시 입력해야, 데이터를 입력하기 위한 Schema가 DB에 반영됨.


Model을 활용한 CRUD 구현 (1)

models.py를 통해 데이터의 구조를 정의하고 DB에 반영을 해보았음. 파이썬 쉘에서 모델 클래스를 활용하여 데이터를 생성, 조작 및 DB에 저장하는 방법을 배워보도록 하자.

  • python manage.py shell : 장고 전용 파이썬 쉘 (Django 에서 동작하는 모든 명령을 대화식 Python 쉘에서 사용 할 수 있게 함)
  • from [어플리케이션명].models import [클래스명] : 파이썬 쉘 내 사용을 위한 클래스 호출

Create

  • post는 Post 모델클래스의 인스턴스객체이며, 변수로 활용가능
  • post.title 또는 post.content 와 같은 접근방식으로 인스턴스의 멤버변수를 호출 할 수 있음.
  • post.save() 를 입력해야 최종적으로 DB에 내용이 저장됨.
>>> post = Post(title='몇번째?', content='인가요?')
>>> post
Post: Post object (None)>
>>> post.save()
>>> post.title
'몇번째?'
>>> post.content
'인가요?'

Read

  • 모델명.objects.all() :해당 모델의 모든 데이터를 갖고옴
  • 모델명.objects.get(id=숫자): 모든 데이터는 그 데이터를 식별하는 고유키(Primary Key)를 갖고 있음. 이를 통해 특정한 데이터에 접근 가능. (pk=1) 같은 방식으로도 접근 가능.
#Read all
>>> Post.objects.all()
<QuerySet [<Post: Post object (2)>, <Post: Post object (3)>]>

#Get one
>>> Post.objects.get(pk=3)
<Post: Post object (3)>
  • 응용: filter / like / order_by / limit & offset
    • offset과 limit은 리스트의 인덱싱과 같은 방식으로 접근 가능
#filter (WHERE)
>>> posts = Post.objects.filter(title='Hello').all()
>>> posts
<QuerySet [<Post: Post object (1)>]> 
#all()로 filter를 쓰면 복수 형으로 결과가 쿼리셋의 형태로 뜸.

>>> posts = Post.objects.filter(title='Hello').first()
>>> posts
<Post: Post object (1)>
    
#like 
>>> posts = Post.objects.filter(title__contains='He').all()
>>> posts
<QuerySet [<Post: Post object (1)>]>

#order by
#title이라는 필드로 오름차순
>>> posts = Post.objects.order_by('title').all()
>>> posts
<QuerySet [<Post: Post object (1)>]>

#내림차순 (필드명 앞에 -붙임)
>>> posts = Post.objects.order_by('-title').all()
>>> posts
<QuerySet [<Post: Post object (1)>]>

#limit & offset
>>> Post.objects.all()[:1]
<QuerySet [<Post: Post object (1)>]>

#offset 1 / limit 2 적용 시
>>> Post.objects.all()[1:2]
<QuerySet [<Post: Post object (2)>]>

Delete

  • Post.objects.get(pk=1) 와 같이 특정 데이터에 접근하여 변수에 저장한 후, delete() 메서드를 통해 DB에 삭제
>>> post = Post.objects.get(pk=1)
>>> post.delete()

Update

  • 마찬가지로 Post.objects.get(pk=2) 의 방법으로 특정데이터에 접근
  • 클래스의 어트리뷰트를 새로 덮어쓰면 update가 가능
  • .save()까지 해야 DB에 업데이트된 내용이 반영됨.
    • .save()를 하지 않을 경우, 파이썬 내 Post라는 클래스의 인스턴스만 수정이 되어 DB에는 반영이 되지 않음.
>>> post = Post.objects.get(pk=2)
>>> post.title
'1번째'
>>> post.title = '2번째로변경'
>>> post.title
'2번째로변경'

>>> post.save()
>>> post = Post.objects.get(pk=2)
>>> post.title
'2번째로변경'

Comments