구글 번역기의 도움을 (많이) 받아 장고 공식 문서를 번역하였습니다.
Model instance reference
이 문서는 Model API의 세부 사항을 기술한다. 모델 및 데이터베이스 쿼리 가이드에 제시된 내용을 토대로 작성되었으므로 이 문서를 읽기 전에 해당 문서를 읽고 이해하는 것이 좋다.
이 레퍼런스를 통해 우리는 데이터 베이서 쿼리 가이드에 제시된 Weblog모델을 사용할 것이다.
객체 생성하기
모델의 새 인스턴스를 만들려면 다른 파이썬 클래스 처럼 인스턴스를 생성하면 된다.
class Model(kwargs)**
키워드 인수는 단순히 모델에 정의한 필드의 이름이다. 모델을 인스턴스화 하는 것은 save()를 하지 않는 이상 절대로 데이터베이스를 건드리지 않는다.
Note
__init__메소드를 오버라이드하여 모델을 커스터마이즈 할 수 있다.그러나 그렇게하면 모델 인스턴스의 변경사항이 저장되지 않을 수 있으므로 호출 서명(calling signature)을 변경하지 않도록 주의해야한다. __init__을 오버라이드하는 대신 다음 방법 중 하나를 사용해보자
- 모델 클래스에 클래스메소드를 추가한다.
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
@classmethod
def create(cls, title):
book = cls(title=title)
# do something with the book
return book
book = Book.create("Pride and Prejudice")>
- 커스텀 메니저에 메소드를 추가한다.(일반적으로 선호되는 방법)
class BookManager(models.Manager):
def create_book(self, title):
book = self.create(title=title)
# do something with the book
return book
class Book(models.Model):
title = models.CharField(max_length=100)
objects = BookManager()
book = Book.objects.create_book("Pride and Prejudice")
모델 로딩 커스터마이징
classmethod Model.from_db(db,field_names, values)
from_db() 메소드를 사용하여 데이터베이로부터 로딩할 때 모델 인스턴스 생성을 정의할 수 있다.
db 인수는 모델이 로드된 데이터베이스의 alias를 포함하고 field_names는 로드된 모든 필드의 이름을 포함하고 값은 field_names에 로드된 값을 포함한다. field_names는 값과 동일한 순서로 있다. 모델의 모든 필드가 존재하면, 값은 __init__가 기대하는 순서로 보장된다. 즉, 인스턴스는 cls(*값)에 의해 생성될 수 있다.
필드가 지연되면 field_names에 나타나지 않는다. 이 경우 누락된 각 필드에 django.db.models.DEFERRED 값을 할당하면 된다. 새 모델을 만드는 것 외에도 from_db()메소드는 새 인스턴스의 _state 특성에 추가 및 db 플래그를 설정해야한다. 다음은 데이터베이스에서 로드된 필드의 초기 값을 기록하는 방법을 보여주는 예이다.
from django.db.models import DEFERRED
@classmethod
def from_db(cls, db, field_names, values):
# Default implementation of from_db() (subject to change and could
# be replaced with super()).
if len(values) != len(cls._meta.concrete_fields):
values = list(values)
values.reverse()
values = [
values.pop() if f.attname in field_names else DEFERRED
for f in cls._meta.concrete_fields
]
instance = cls(*values)
instance._state.adding = False
instance._state.db = db
# customization to store the original field values on the instance
instance._loaded_values = dict(zip(field_names, values))
return instance
def save(self, *args, **kwargs):
# Check how the current values differ from ._loaded_values. For example,
# prevent changing the creator_id of the model. (This example doesn't
# support cases where 'creator_id' is deferred).
if not self._state.adding and (
self.creator_id != self._loaded_values['creator_id']):
raise ValueError("Updating the value of creator isn't allowed")
super().save(*args, **kwargs)
위의 예제는 전체 from_db()구현을 보여준다. 이 경우 from_db() 메소드에서 super()호출 만 사용하는 것이 가능하다.
데이터베이스에서 객체 새로고침
모델 인스턴스에서 필드를 삭제하면 다시 액세스하여 데이터베이스에서 값을 다시 로드한다.
>>> obj = MyModel.objects.first()
>>> del obj.field
>>> obj.field # 데이터베이스로부터 필드를 로드함
Model.refresh_form_db(using=None, fields=None)
모델 값을 데이터베이스에서 다시 로드해야하는 경우 refresh_from_db() 메소드를 사용할 수 있다. 인수 없이 이 메소드를 호출하면 다음 작업이 수행된다.
- 모델의 모든 지연되지 않은 필드는 현재 데이터베이스에 있는 값으로 업데이트된다.
- 관계의 값이 더 이상 유효하지 않은 이전에 로드된 관련 인스턴스가 다시 로드된 인스턴스에서 제거된다. 예를 들어, 다시 로드된 인스턴스에서 작성자 이름의 다른 모델로 foreign key가 있는 경우 obj.author_id != obj.author.id, obj.author가 버려지고 다음 액세스 시 obj.author_id의 값이 다시 로드된다.
모델에 필드만 데이터베이스에서 다시 로드된다. 주석과 같은 다른 데이터베이스 종속 값은 다시 로드되지 않는다. 모든 @cached_property 속성은 지워지지 않는다.
리로딩(reloading)은 인스턴스가 로드된 데이터베이스에서 수행되거나 로드되지 않은 경우 기본 데이터베이스에서 수행된다. using인수는 리로딩에 사용된 데이터베이스를 강제로 실행하는 데 사용될 수 있다.
fields 인수를 사용하여 로드할 필드셋을 강제 실행할 수 있다.
예를 들어, update() 호출이 예상된 업데이트를 일으킨다는 것을 테스트하려면 다음과 비슷한 테스트를 작성할 수 있다.
def test_update_result(self):
obj = MyModel.objects.create(val=1)
MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
# At this point obj.val is still 1, but the value in the database
# was updated to 2. The object's updated value needs to be reloaded
# from the database.
obj.refresh_from_db()
self.assertEqual(obj.val, 2)
지연된 필드에 액세스 할 때 지연된 필드의 값을 로딩하는 것은 이 메소드를 통해 발생한다. 따라서 지연 로딩이 발생하는 방식을 사용자 정의할 수 있다.
class ExampleModel(models.Model):
def refresh_from_db(self, using = None, fields = None, **kwargs):
# 필드는 지연 필드의 이름을 포함한다.
# 로드됨
if fields is not None:
fields = set(fields)
deferred_fields = self.get_deferred_fields()
# 만약 지연된 필드가 로드되려 한다면
if fields.intersection(deferred_fields):
# 전부를 로드시킨다
fields = fields.union(deferred_fields)
super().refresh_from_db(using, fields, **kwargs)
Model.get_deferred_fields()
현재 연기되고 있는 모든 필드의 속성이름을 포함한 셋을 모델로 돌려주는 헬퍼 메소드이다.
객체 유효성 검사하기
모델 유효성 검사에는 세 단계가 있다.
- 모델 필드들 유효화하기 - Model.clean_fields()
Comments