[Django] Django ORM Cookbook : 7

GreenBean·2021년 9월 30일
0

Django ORM Cookbook

목록 보기
7/8
post-thumbnail

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의 차이

  • nullblank는 둘 다 기본값이 False
    • 이 두 설정은 모두 필드(열) 수준에서 동작
    • 즉, 필드(열)를 비워두는 것을 허용할 것인지를 설정
  • null=True는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용
    • 결국 데이터베이스 열에 관한 설정
  • blank=True는 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용
    • 장고 관리자(admin) 및 직접 정의한 폼에도 반영됨
date = models.DateTimeField(null=True)
title = models.CharField(blank=True)  # 폼에서 비워둘 수 있음. 그러나 데이터베이스에는 ''이 저장됨.
  • null=Trueblank=True를 모두 지정하면 어떤 조건으로든 값을 비워둘 수 있음을 의미
epic = models.ForeignKey(null=True, blank=True)
# 단, CharFields()와 TextFields()에서는 예외
# 장고는 이 경우 NULL을 저장하지 않으며, 빈 값을 빈 문자열('')로 저장
  • 예외적인 경우
    • 불리언 필드(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()

# 슬러그는 자동으로 생성, create 메서드 따로 정의한거 아님
>>> 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
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 댓글