Django ORM
Django ORM Cookbook
모델에 연결된 표 이름 지정
- 모델에 연결된 데이터베이스 표의 이름을 직접 지정하지 않으면 장고가 자동으로 표의 이름을 지어 줌
- 자동으로 붙는 데이터베이스 표의 이름은 “앱의 레이블”(manage.py startapp 명령에서 지은 이름)과 모델 클래스의 이름을 밑줄 기호로 연결한 것
- 이름을 직접 붙이려면 모델의
Meta
클래스에 db_table
값을 설정하면 됨
class TempUser(models.Model):
first_name = models.CharField(max_length=100)
. . .
class Meta:
db_table = "temp_user"
데이터베이스 열 이름 지정
- 모델 필드가 가리키는 데이터베이스의 열 이름을 지정하려면 필드 인스턴스의 초기화 매개변수 db_column 에 원하는 이름을 전달하면 됨
- 이 매개변수에 인자를 전달하지 않으면 필드 이름과 동일한 이름이 사용됨
class ColumnName(models.Model):
a = models.CharField(max_length=40,db_column='column1')
column2 = models.CharField(max_length=50)
def __str__(self):
return self.a
db_column
으로 지정한 이름이 필드 이름보다 우선순위가 높음
- 첫 번째 열의 이름이 a가 아니라 column1로 지어졌음
null=True와 blank=True의 차이
null
과 blank
는 둘 다 기본값이 False
- 이 두 설정은 모두 필드(열) 수준에서 동작
- 즉, 필드(열)를 비워두는 것을 허용할 것인지를 설정
null=True
는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용
blank=True
는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용
- 장고 관리자(admin) 및 직접 정의한 폼에도 반영됨
date = models.DateTimeField(null=True)
title = models.CharField(blank=True)
null=True
와 blank=True
를 모두 지정하면 어떤 조건으로든 값을 비워둘 수 있음을 의미
epic = models.ForeignKey(null=True, blank=True)
- 예외적인 경우
- 불리언 필드(
BooleanField
)에 NULL을 입력할 수 있도록 하려면 null=True
를 설정하는 것이 아니라, 널 불리언 필드(NullBooleanField
)를 사용해야 함
기본 키(PK)로 UUID 사용
- 장고에서 모델을 생성하면 ID 필드가 기본 키로 생성됨
- ID 필드의 기본 데이터 유형은 양의 정수
- 양의 정수가 아니라 UUID를 기본 키로 사용하고 싶다면 장고 1.8 버전에서 추가된
UUIDField
를 사용하면 됨
import uuid
from django.db import models
class Event(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
details = models.TextField()
years_ago = models.PositiveIntegerField()
>>> eventobject = Event.objects.all()
>>> eventobject.first().id
'3cd2b4b0c36f43488a93b3bb72029f46'
슬러그 필드 사용
- 슬러그(slug)는 URL의 구성요소로 웹사이트의 특정 페이지를 가리키는, 사람이 읽기 쉬운 형식의 식별자
- 장고에서는 슬러그 필드(
SlugField
)로 슬러그를 지원
from django.utils.text import slugify
class Article(models.Model):
headline = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.headline)
super(Article, self).save(*args, **kwargs)
>>> u1 = User.objects.get(id=1)
>>> from datetime import date
>>> a1 = Article.objects.create(headline="todays market report", pub_date=date(2018, 3, 6), reporter=u1)
>>> a1.save()
>>> a1.slug
'todays-market-report'
- 슬러그의 장점
- 사람이 이해하기 좋음 (
/1/
보다 /blog/
가 좋음)
- 제목과 URL을 동일하게 맞춰 검색엔진 최적화(SEO)에 도움이 됨
여러 개의 데이터베이스 사용
- 데이터베이스의 접속에 관련된 설정은 대부분
settings.py
파일에서 이루어짐
- 장고 프로젝트에 여러 개의 데이터베이스를 추가하려면 해당 파일의
DATABASES
사전에 등록하면 됨
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'users_db': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.postgresql',
'USER': 'postgres_user',
'PASSWORD': 'password'
},
'customers_db': {
'NAME': 'customer_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_cust',
'PASSWORD': 'root'
}
}
- 여러 개의 데이터베이스를 함께 사용하려면 데이터베이스 중계기(database router)에 대해 알아야 함
- 장고의 기본 중계 설정은 데이터베이스를 특정하지 않은 경우 기본(default) 데이터베이스로 중계
DATABASE_ROUTERS
설정의 기본값은 []
임
class DemoRouter:
"""
user_data 앱의 모델에서 수행되는 모든 데이터베이스 연산을 제어하는 중계기
"""
def db_for_read(self, model, **hints):
"""
user_data 앱의 모델을 조회하는 경우 users_db로 중계
"""
if model._meta.app_label == 'user_data':
return 'users_db'
return None
def db_for_write(self, model, **hints):
"""
user_data 앱의 모델을 기록하는 경우 users_db로 중계
"""
if model._meta.app_label == 'user_data':
return 'users_db'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
user_data 앱의 모델과 관련된 관계 접근을 허용
"""
if obj1._meta.app_label == 'user_data' or \
obj2._meta.app_label == 'user_data':
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
user_data 앱의 모델에 대응하는 표가 users_db 데이터베이스에만 생성되도록 함
"""
if app_label == 'user_data':
return db == 'users_db'
return None
- 중계기를 위와 같이 설정해 두었으면, 모델이 서로 다른 데이터베이스를 사용하도록 다음과 같이 정의할 수 있음
class User(models.Model):
username = models.Charfield(ax_length=100)
class Meta:
app_label = 'user_data'
class Customer(models.Model):
name = models.TextField(max_length=100)
class Meta:
app_label = 'customer_data'
- 여러 개의 데이터베이스를 관리할 때 사용하는 마이그레이션 명령
$ ./manage.py migrate --database=users_db