Django Models - Introduction to models

in #django7 years ago (edited)


Model

모델은 데이터 정보를 정의한 소스다. 저장 중인 데이터의 필수 필드와 동작들이 포함되어있다. 일반적으로 모델은 데이터베이스 테이블과 매핑된다.

Quick example

아래 예제 모델은 first_name과 last_name을 가진 Person을 정의한다. first_name과 last_name은 모델의 필드다. 각 필드는 클래스 속성으지정되어있고 각 속성은 데이터베이스 컬럼과 매핑된다.


위 Person 모델은 아래와 같은 데이터베이스 테이블을 만든다.

Using models

모델을 정의했다면 Django에게 해당 모델들을 알려줘야 한다. models.py 에 포함된 모듈의 이름을 세팅 파일에 INSTALLED_APPS 에 추가해야 한다.

애플리케이션의 모델이 myapp.models (manage.py startapp 스크립트를 통해 작성된 애플리케이션 패키지 구조) 모듈에 있을 경우 INSTALLED_APPS 해당 부분은 아래와 같을 것이다.

Fields

모델에서 가장이고 유일하게 필수인 부분은 데이터베이스 필드 목록의 정의이다. 필드는 클래스 속성에 의해 지정된다. 필드 이름을 clean, save, delete 등과 같은 모델 API와 충돌하지 않도록 조심해라.

Field types

모델의 각 필드는 해당 Field 클래스의 인스턴스여야 한다. Django는 필드 클래스 타입을 사용하여 몇 가지를 결정한다.

  • 데이터베이스에 저장할 데이터의 종류에 따른 컬럼 타입 (e.g INTEGER, VARCHAR, TEXT).
  • 폼 필드를 렌더링 할 때 사용하기 위한 기본 HTML 위젯 (e.g <input type="text">, <select>).
  • Django 어드민과 자동으로 생성된 폼의 최소(기본적인) 유효성 검사

Django에는 많은 빌트인 필드 타입이 있다. 모델 필드 참조 목록에서 확인할 수 있다.

Field options

각 필드는 특정 필드 관련 인수들이 있다. 예를 들어 CharField (해당 하위 클래스 포함)는 데이터를 저장할 때 VARCHAR 데이터베이스 필드의 크기를 지정하는 max_length 인수가 필요하다.

 또한 모든 필드 타입에서 사용 가능한 일반적인 인수들이 있다. 모두 선택 인수들이다. 모델 필드 참조 문서에 모두 설명되어있지만 아래에 자주 쓰이는 것들을 요약한다.

null
True 라면 Dajngo는 데이터베이스에 빈 값을 NULL로 저장한다. 기본값은 False.

blank
True 라면 해당 필드는 비워둘 수 있다. 기본값은 False.

null과는 다르다. null은 순전히 데이터베이스와 관련되어있는 반면 blank는 유효성 검사와 관련되어있다. 필드에 blank=True 인수가 있다면 폼 유효성 검사 시 빈 값을 허용한다. 필드에 blank=False 인수가 있다면 해당 필드 값은 필수다.

choices
필드의 선택지로 2-tuples 의 iterable을 사용한다. choice 속성이 주어지면 기본 폼 위젯은 표준 텍스트 필드 대신 셀렉트 박스가 되고 선택항목이 해당 iterble로 제한된다.

각 tuple의 첫 번째 요소는 데이터베이스에 저장될 값이다. 두 번째 요소는 필드의 폼 위젯에 보인다.

모델 인스턴에서 get_FOO_dispay()  메서드를 사용해서 선택된 choices 필드의 디스플레이 값에 접근할 수 있다.




default
필드의 기본값이다. 값 또는 callable  객체일 수 있다. callable 일 경우 새로운 객체가 생성될 때마다 호출된다.

help_text
폼 위젯과 함께 보이는 추가 "help" 텍스트다. 필드가 폼에 사용되지 않더라도 문서화 시 유용하다.

primary_key
True 일 경우 이 필드는 모델의 primary key 가 된다.

모델에 어떤 필드에도 primary_key=True를 지정하지 않는다면, Django는 자동으로 기본키를 보유할 IntegerField를 추가하므로, 기본 primary-key 동작을 재정하는 경우를 제외하면 primary_key=True 설정이 필요 없다.
primary key 필드는 읽기 전용이다. The primary key field is read-only. 기존 객체에 primary key값을 변경하고 저장하면, 이전 객체가 유지되고 새로운 객체가 생성된다.
uniqueTrue 일 경우, 이 필드는 테이블을 통틀어서 유일해야만 한다.


INSTALLED_APPS 에 새로운 애플리케이션을 추가하면 managepy migrate를 실행해야 한다. 마이그레이션 파일을 만들기 위해 manage.py makemigrations를 실행해야 하는 경우도 있다.


Automatic primary key fields

Django는 모델마다 기본으로 아래와 같은 필드를 제공한다.자동으로 증가되는 primary key이다.
사용자 정의 primary key를 지정하려면, 필드 중 하나에 primary_key=True를 지정하면 된다. Django가 당신이 Field.primary_key를  설정했다고 판단하면, 자동으로 id 컬럼을 추가하지 않는다.
각 모델은 primary_key=True(사용자가 지정 또는 자동으로 추가된)를 가진 정확히 하나의 필드만 요구한다.

Verbose field names

ForeignKey, ManyToManyFieldOntToOneField를 제외한 각 필드 타입은 선택적으로 첫 번째 위치의 인수에 verbose name을 가진다. verbose name이 주어지지 않으면 Django는 필드의 속성 이름을 사용해서 밑줄을 공백으로 바꿔 자동으로 생성한다.
아래 예제는 verbose name이 "person's first name"이다.아래 예제는 verbose name이 "first name"이다.
ForeignKey, ManyToManyField, OneToOneField는 첫 번째 인수로 모델 클래스를 요구하기 때문에, verbose_name 키워드 인수를 사용한다.컨변센은 verbose_name에 첫 문자를 대문자로 사용하지 않습니다. DJango가 필요한 곳에서 첫 문자를 자동으로 대문자로  표시해준다.

Relationships

명백히, 관계형 데이터베이스의 힘은 테이블이 서로 관계를 맺는 데 있다. Django는 가장 일반적인 세 가지(many-to-one, many-to-many and one-to-one) 관계에 대해  정의하는 방법을 제공한다.
Many-to-one relationships
다대일 관계 정의는 django.db.models.ForeignKey를 사용한다. 다른 필드 타입과 같이 모델에 클래스 속성으로 포함하여 사용한다.
ForeignKey는 위치 인수가 필요하다. 모델이 인수에 관련된 클래스다.
예를 들면, Car 모델이 Manufacturer를 가지고 있다면 - 즉, Manufacturer는 여러 개의 Car를 만들지만 Car는 하나의 Manufacturer 만을 갖는 경우 - 다음 정의를 사용한다.
또한 재귀 관계와 아직 정의되지 않은 모델과의 관계를 만들 수 있다.
ForeignKey 필드(위 예제에서 manufacturer)의 이름을 모델 이름의 소문자로 권장하지만 필수는 아니다. 물론 원하는 데로 필드를 호출할 수 있다.

Many-to-manu relatioships

다대다 관계 정의는 ManyToManyField를 사용한다. 다른 필드 타입과 같이 모델에 클래스 속성으로 포함하여 사용한다.
ManyToManyField는 위치 인수가 필요하다. 모델이 인수에 관련된 클래스다.
예를 들면, Pizza에 여러 개의 Topping객체가 있을 경우 - Topping이 여러 개의 Pizza에 있을 수 있고 Pizza에 여러 개의 Topping이 있을 경우 - 여기에 그 피자를 표현하는 방법이 있다.ForeignKey와 마찬가지로, 재귀 관계와 아직 정의되지 않은 모델과 관계를 만들 수 있다.
ManyToManyField(위 예제에서 toppings)의 이름은 관련된 모델 객체의 세트를 설명하는 복수형으로 권장되지만 필수는 아니다.
ManyToManyField가 어느 모델에 있는지는 중요하지 않지만, 반드시 하나의 모델에 있어야 한다.
일반적으로 ManyToManyField 인스턴스는 폼에서 편집될 객체에 있어야 한다. 위 예제에서, toppingsPizza에 있다. 피자에 토핑이 있다고 생각하는 것이 토핑이 여러 개의 피자에 올라가는 것이 더 자연스럽기 때문이다.
위 설정대로 Pizza 폼을 사용하면 사용자들이 토핑을 선택하게 될 것이다.Extra fields on many-to-many relationships
단지 피자와 토핑을 혼합하고 매치하는 단순한 다대다 관계만을 다룰 때는, 표준 ManyToManyField만 있으면 된다. 하지만 때로는 두 모델 간의 관계와 데이터가 추가로 필요할 수도 있다.
예를 들어, 뮤지션이 소속된 뮤지컬 그룹을 추적하는 애플리케이션의 상황을 생각해보자. 사람과 멤버들이 있는 그룹 간에는 다대다 관계가 있다. 그러므로 이 관계를 표현하는데 ManyToManyField를 사용할 수 있다. 하지만 그룹에 가입한 날짜와 같이 회원에 대해 수집하길 원하는 많은 상세정보가 있다.
Django는 이러한 상황에서  다대다 관계를 관리하는 데 사용될 모델을 지정할 수 있다. 그러고 나서 중간 모델에 추가 필드를 입력할 수 있다. 중간 모델은 중개인 역할을 하는 모델을 가리키는 through 인수를 사용해서 ManyToManyField와 연결된다. 뮤지선 예제 코드는 다음과 같다. 중개 모델을 설정할 때, 다대다 관계에 관여하는 모델들을 위한 외래 키를 명시적으로 지정한다. 이 명시적 선언은 두 모델이 관련되는 방식을 정의한다.
중간 모델에는 몇 가지 제한사항이 있다.중간 모델에는 원본 모델에 대한 외래 키가 하나만 포함되야한다(예제에서 Group). 또는 Django에서 ManyToManyField.through_fields를 사용해서 관계에 사용해야 하는 외래 키를 명시적으로 지정해야 한다. 두 개 이상의 외래 키가 있고 through_fields를 정의하지 않는다면, 유효성 검증 오류가 발생한다. 외래 키에 대한 비슷한 제한사항이 대상 모델(예제에서 Person)에도 적용된다.중개 모델을 통해 다대다 관계를  가지고 있는 모델의 경우 동일한 모델에 대한 두 개의 외래 키가 허용되지만 다대다 관계와는 다른 측면으로 처리된다. 두 개 이상의 외래 키가 있는 경우, 위처럼 through_fields를 지정해야 한다. 그렇지 않으면 유효성 검증 에러가 발생한다.중개 모델을 사용하여 자신의 모델로부터 다대다 관계를  정의할 때는 symmetrical=False를 사용해야 한다. 이제 중개 모델(예제에서 Membership)을 사용하여 ManyToManyField를 설정했으므로 다대다 관계를 만들 준비가 되었다. 중간 모델의 인스턴스를 만들어 실행한다.일반적인 다대다 필드와는 다르게 add(), create(), set()을 사용하여 관계를 만들 수 없다.왜일까? PersonGroup 간의 관계를 만들 수 없다. Membership 모델 관계에 필요한 모든 세부 정보를 지정해야 한다. 간단한 add, create 및 할당 호출은 추가 세부사항을 지정하는 방법을 제공하지 않는다. 결과적으로 중간 모델을 사용한 다대다 관계에서는 비활성화된다. 이런 관계의 유형을 생성하기 위한 유일한 방법은 중간 모델의 인스턴스를 생성하는 것이다.
비슷한 이유로 remove() 메서드가 비활성화된다. 예를 들면, 중간 모델에 의해 정의된 사용자 정의 테이블을 통해 (model1, model2)의 유일성이 적용되지 않은 경우 remove() 호출은 지워야 할 중간 모델 인스턴스에 대한 충분한 정보를 제공하지 않는다.하지만, clear() 메서드를 사용하여 모든 인스턴스에 다대다 관계를 삭제할 수 있다.중간 모델의 인스턴스를 생성하여 다대다 관계를 설정하면 쿼리를 실행할 수 있다. 일반적인 다대다 관계같이 다대다 관계 모델의 속성을 사용하여 쿼리 할 수 있다.중간 모델을 사용할 때 해당 속성에 대해서도 쿼리 할 수 있다.회원의 정보에 접근이 필요할 경우 직접 Membership 모델에 쿼리 하여 수행할 수 있다.같은 정보에 접근하는 다른 방법은 Person 객체에서 다대다 reverse relationship를 쿼리 하는 것이다.One-to-one relationships
일대일 관계는 OneToOneField를 사용해 정의한다. 다른 필드 타입과 같이 모델의 클래스 속성을 포함하여 사용한다.
객체를 어떤 방법으로 다른 객체로 확장할 때 매우 유용하다.
OneToOneField에는 위치 인수가 필요하다. 모델이 관련 클래스이다.
예를 들어, 주소, 전화번호, 기타 등등의 속성이 포함된 "places"의 데이터베이스를 구축한 후 장소위에 레스토랑의 데이터베이스를 구축하길 원한다면 해당 장소의 정보를 복사해서 새로운 레스토랑 데이터베이스를 구축하는 대신에 Restaurant에 OneToOneField(대상은 Place)로 만들 수 있다. 사실 일반적으로 암시적인 일대일 관계가 포함된 상속을 사용한다.
ForeignKey처럼, 재귀 관계가 정의될 수 있고 아직 정의되지 않은 모델도 참조할 수 있다.
OneToOneField는 또한 선택적 인수 parent_link를 제공한다.
OneToOneField 클래스는 모델에서 자동으로 primary key 된다. 원한다면 수동으로 primary_key 인수를 설정할 수 있다. 그리하여 한 모델이 여러 개의 OneToOneField 타입의 필드를 포함할 수 있다.

Models across files

모델을 다른 앱의 모델과 관계하는 것도 가능하다. 이것을 하려면 모델이 정의된 파일의 맨 위에 관련된 모델을 import 한다. 그다음 필요한 곳에 다른 모델 클래스를 참조해라.

Field name restrictions

Django는 모델 필드 이름에 두 가지를 제한한다.
파이썬  예약어는 파이썬 구문 오류가 발생하기 때문에 필드 이름이 될 수 없다.필드 이름은 한 행에 두 개 이상의 밑줄이 포함할 수 없다. Django의 쿼리 조회 구문의 동작 방법 같은 두 개의 밑줄은 포함될 수 없다.
필드 이름이 데이터베이스 컬럼 이름과 일치할 필요는 없기 때문에 이러한 제한사항은 해결될 수 있다.
Django는 모든 쿼리에 데이터베이스 테이블 이름과 컬럼 이름을 이스케이프 처리하기 때문에 모델 필드 이름으로 join, where, select와 같은 SQL 예약어를 허용한다.

Custom field types

기존 모델 필드 중 하나가 목적에 맞게 사용될 수 없거나 일반적인 데이터베이스 컬럼이 아닌 경우 자신만의 필드 클래스를 작성 가능하다.

Meta options

다음과 같이 inner class Meta를 사용하여 모델 메타데이터를 전달해라.모델 메타데이터는 정렬 옵션 (ordering), 데이터베이스 테이블 이름 (db_table), 또는 사람이 읽을 수 있는 단수와 복수 이름(verbose_nameverbose_name_plural) 등등처럼 "필드가 아닌 모든 것이다". 아무것도 필수가 아니며 모델의 클래스 메타를 추가하는 것은 완전히 선택사항이다.

Model attributes

objects모델의 속성 중에 가장 중요한 것이 Manager이다. Django 모델에 대해 데이터베이스 쿼리 작업이 제공되고 데이터베이스에서 인스턴스를 조회하는 데 사용되는 인터페이스다. 사용자 정의 Manager를 정의하지 않으면 기본 이름이 objects이다. 매니저는 모델 인스턴스가 아닌 모델 클래스를 통해서만 접근할 수 있다.

Model methods

모델에 사용자 메서드를 정의하여 객체의 "row-level" 기능을 추가한다. Manager 메서드는 "table-wide"의 일을 처리하기 위함이지만 모델 메서드는 특정 모델 인스턴스에서 동작해야 한다.
모델 메서드는 비즈니스 로직을 한 곳(모델)에서 유지하게 해주는 중요한 기술이다.
사용자 지정 메서드가 있는 모델 예제예제에서 마지막 메서드는 property다.
각 모델에 자동으로 부여된 메서드들이 있고 재정의 가능하다. 하지만 대부분 아래 두 가지 메서드의 재정의를 한다.
__str__()모든 객체의 문자 표현을 리턴하는 파이썬 "magic method". 파이썬과 Django에서 모델 인스턴스를 강제로 문자열로 표시되어야 할 경우 사용된다. 특히 대화형 콘솔 또는 관리자 화면에서 객체를 보여줄 때 발생한다.
매번 이 메서드 정의를 원할 것이다. 기본 메서드는 전혀 도움되지 않는다.
get_absolute_url()Django는 객체의 URL을 계산하는 방법을 제공한다. Django 관리자 인터페이스에서 이것을 사용하고 언제든 객체의 URL을 찾을 필요가 있다.
고유하게 식별할 URL을 가진 객체는 이 메서드를 정의해야 한다.

Overring predefined model methods

사용자 정의할  데이터베이스 동작들을 캡슐화하는 다른 모델 메서드 집합이 있다. 특히 save()delete() 동작 변경을 원하는 경우가 많다.
동작을 변경하기 위해 이 메서드들을 자유롭게 재정의할 수 있다.
내장 메서드를 재정의하는 고전적인 사용 사례는 객체가 저장될 때마다 무언가를 원하는 경우다.저장하는 것을 막을 수도 있다.객체가 항상 안전하게 저장되는 위해 superclass 메서드를 호출하는 것을 기억하는 것이 중요하다. superclass 메서드 호출하는 것을 잊으면, 기본 동작과 데이터베이스를 손대지 않는다.
또한 모델 메서드에 전달할 수 있는 인수들을 전달하는 것이 중요하다. - *args, **kwargs. Django는 수시로 내장 모델 메서드의 기능을 확장하고 새로운 인수를 추가한다. 메서드 정의에서 *args, **kwargs를 사용한다면 코드가 추가될 때 자동으로 해당 인수들을 지원하는 것을 보장받는다.
Overridden model methods are not called on bulk operations
QuerySet을 사용해서 대량으로 객체를 삭제하거나 cascading 삭제의 결과로 해당 객체의 delete() 메서드가 반드시 호출되지는 않는다. 안전한 사용자 정의 로직을 위해서는 pre_deletepost_delete signal을 사용한다. 불행하게도, 객체를 대량으로 만들거나 수정할 때는 save(), pre_save, post_save가 호출되지 않기 때문에 해결방법이 없다.

Executing custom SQL

또 다른 일반적인 패턴은 모델 메서드와 모듈 수준의 메서드에 사용자 정의 SQL문을 작성하는 것이다.

Model inheritance

Sort:  

Congratulations @ddangdol! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

Click here to view your Board

Support SteemitBoard's project! Vote for its witness and get one more award!

Congratulations @ddangdol! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.18
TRX 0.15
JST 0.031
BTC 60970.88
ETH 2634.17
USDT 1.00
SBD 2.59