Django
모델
수색…
소개
기본 경우 모델은 단일 데이터베이스 테이블에 매핑되는 Python 클래스입니다. 클래스의 속성은 테이블의 열에 매핑되고 클래스의 인스턴스는 데이터베이스 테이블의 행을 나타냅니다. 이 모델은 django.db.models.Model
에서 상속 django.db.models.Model
데이터베이스에서 결과를 추가하고 필터링 할 수있는 풍부한 API를 제공합니다.
첫 번째 모델 만들기
모델은 일반적으로 응용 프로그램 서브 디렉토리 아래의 models.py
파일에 정의됩니다. django.db.models
모듈의 Model
클래스는 모델을 확장하는 좋은 시작 클래스입니다. 예 :
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey('Author', on_delete=models.CASCADE, related_name='authored_books')
publish_date = models.DateField(null=True, blank=True)
def __str__(self): # __unicode__ in python 2.*
return self.title
모델의 각 속성은 데이터베이스의 열을 나타냅니다.
-
title
은 최대 길이가 100자인 텍스트입니다. -
author
는 다른 모델 / 테이블 (이 경우Author
과의 관계를 나타내는ForeignKey
입니다 (예제 용도로만 사용됨).on_delete
는 관련 객체 (Author
)를 삭제해야 할 경우 데이터베이스에서 객체와 함께 수행 할 작업을 지시합니다. (django 1.9on_delete
는 두 번째 위치 인수로 사용할 수 있으므로 django 2 에서는 필수 인수 이므로 즉시 처리해야합니다. 이전 버전에서는 기본적으로CASCADE
됩니다.) -
publish_date
는publish_date
저장합니다.null
와blank
필드 모두 필수 필드가 아님을 나타 내기 위해True
로 설정됩니다 (즉, 나중에 필드를 추가하거나 비워 둘 수 있음).
우리가 정의한 속성들과 함께 __str__
메소드는 책의 제목을 반환하는데, 책의 제목은 기본값이 아닌 필요한 경우 string
표현으로 사용됩니다.
데이터베이스에 변경 사항 적용 (마이그레이션)
새 모델을 작성하거나 기존 모델을 수정 한 후에는 변경 사항에 대한 마이그레이션을 생성 한 다음 지정된 데이터베이스에 마이그레이션을 적용해야합니다. 이것은 Django에 내장 된 마이그레이션 시스템을 사용하여 수행 할 수 있습니다. 프로젝트 루트 디렉토리에있을 때 manage.py
유틸리티 사용 :
python manage.py makemigrations <appname>
위의 명령은 응용 프로그램의 migrations
서브 디렉토리 아래에 필요한 이주 스크립트를 작성합니다. <appname>
매개 변수를 생략하면 settings.py
의 INSTALLED_APPS
인수에 정의 된 모든 응용 프로그램이 처리됩니다. 필요한 경우 마이그레이션을 편집 할 수 있습니다.
실제로 마이그레이션을 생성하지 않고 필요한 마이그레이션을 확인할 수 있습니다. 예를 들어 --dry-run 옵션을 사용하십시오.
python manage.py makemigrations --dry-run
마이그레이션을 적용하려면 다음을 수행하십시오.
python manage.py migrate <appname>
위의 명령은 첫 번째 단계에서 생성 된 마이그레이션 스크립트를 실행하고 물리적으로 데이터베이스를 업데이트합니다.
기존 데이터베이스의 모델이 변경되면 필요한 변경을 수행하려면 다음 명령이 필요합니다.
python manage.py migrate --run-syncdb
Django는 기본적으로 <appname>_<classname>
이라는 이름으로 테이블을 생성합니다. 언젠가 당신은 그것을 사용하고 싶지 않습니다. 기본 이름을 변경하려면 Meta
클래스의 db_table
을 설정하여 테이블 이름을 알릴 수 있습니다.
from django.db import models
class YourModel(models.Model):
parms = models.CharField()
class Meta:
db_table = "custom_table_name"
특정 마이 그 레이션에 의해 실행될 SQL 코드를 보려면 다음 명령을 실행하십시오.
python manage.py sqlmigrate <app_label> <migration_number>
장고> 1.10
새로운 makemigrations --check
옵션은 마이그레이션없이 모델 변경이 감지 될 때 명령이 0이 아닌 상태로 종료되도록합니다.
마이그레이션에 대한 자세한 내용은 마이그레이션 을 참조하십시오.
관계가있는 모델 만들기
다 대일 관계
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=50)
#Book has a foreignkey (many to one) relationship with author
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
publish_date = models.DateField()
가장 일반적인 옵션. 관계를 나타낼 수있는 모든 곳에서 사용할 수 있습니다.
다 대다 관계
class Topping(models.Model):
name = models.CharField(max_length=50)
# One pizza can have many toppings and same topping can be on many pizzas
class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)
내부적으로 이것은 다른 테이블을 통해 표현됩니다. 그리고 ManyToManyField
는 양식에서 편집 할 모델에 배치해야합니다. 예 : Appointment
에는 Customer
라고하는 ManyToManyField
, Pizza
에는 Toppings
등이 있습니다.
클래스를 통한 다 대다 관계
class Service(models.Model):
name = models.CharField(max_length=35)
class Client(models.Model):
name = models.CharField(max_length=35)
age = models.IntegerField()
services = models.ManyToManyField(Service, through='Subscription')
class Subscription(models.Model):
client = models.ForeignKey(Client)
service = models.ForeignKey(Service)
subscription_type = models.CharField(max_length=1, choices=SUBSCRIPTION_TYPES)
created_at = models.DateTimeField(default=timezone.now)
이렇게하면 두 엔티티 간의 관계에 대한 메타 데이터를 실제로 유지할 수 있습니다. 알 수 있듯이 클라이언트는 여러 구독 유형을 통해 여러 서비스에 가입 할 수 있습니다. 이 경우의 유일한 차이점은 M2M 릴레이션에 새 인스턴스를 추가하는 경우 바로 가기 메소드 pizza.toppings.add(topping)
사용할 수 없으며 대신에 through 클래스의 새 객체를 만들어야한다는 것입니다. Subscription.objects.create(client=client, service=service, subscription_type='p')
through tables
다른 언어에서는JoinColumn
,Intersection table
또는mapping table
JoinColumn
mapping table
일대일 관계
class Employee(models.Model):
name = models.CharField(max_length=50)
age = models.IntegerField()
spouse = models.OneToOneField(Spouse)
class Spouse(models.Model):
name = models.CharField(max_length=50)
두 필드 사이에 구성 관계 만있을 때이 필드를 사용하십시오.
기본 Django DB 쿼리
Django ORM은 SQL 쿼리를 직접 작성하지 않고 데이터베이스에서 데이터를 저장하고 검색 할 수있는 강력한 추상화입니다.
다음 모델을 가정 해 보겠습니다.
class Author(models.Model):
name = models.CharField(max_length=50)
class Book(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey(Author)
django 응용 프로그램에 위의 코드를 추가하고 migrate
명령을 실행하여 (데이터베이스가 만들어 지도록) 가정합니다. Django 쉘을 시작하십시오.
python manage.py shell
이렇게하면 표준 파이썬 셸이 시작되지만 관련 장고 라이브러리가 가져와 져서 중요한 부분에 직접 집중할 수 있습니다.
방금 정의한 모델을 가져 오기 시작하십시오 (이 작업은 models.py
파일에서 수행됩니다)
from .models import Book, Author
첫 번째 선택 쿼리 실행 :
>>> Author.objects.all()
[]
>>> Book.objects.all()
[]
저자와 도서 개체를 만들 수 있습니다.
>>> hawking = Author(name="Stephen hawking")
>>> hawking.save()
>>> history_of_time = Book(name="history of time", author=hawking)
>>> history_of_time.save()
create function을 사용하여 모델 객체를 생성하고 하나의 라인 코드로 저장
>>> wings_of_fire = Book.objects.create(name="Wings of Fire", author="APJ Abdul Kalam")
이제 쿼리를 실행할 수 있습니다.
>>> Book.objects.all()
[<Book: Book object>]
>>> book = Book.objects.first() #getting the first book object
>>> book.name
u'history of time'
select 쿼리에 where 절을 추가합시다.
>>> Book.objects.filter(name='nothing')
[]
>>> Author.objects.filter(name__startswith='Ste')
[<Author: Author object>]
주어진 책의 저자에 대한 세부 정보를 얻으려면
>>> book = Book.objects.first() #getting the first book object
>>> book.author.name # lookup on related model
u'Stephen hawking'
스티븐 호킹 (저자에 의한 조회 도서)에 의해 출판 된 모든 도서를 얻으려면,
>>> hawking.book_set.all()
[<Book: Book object>]
_set
은 "역방향 조회"에 사용되는 표기법입니다. 즉, 조회 필드가 Book 모델에있는 동안 author 객체에서 book_set
을 사용하여 모든 책을 가져올 수 있습니다.
기본 관리되지 않는 테이블
장고를 사용할 때, 이미 생성 된 테이블이나 데이터베이스 뷰와 상호 작용하고 싶을 수도 있습니다. 이 경우 Django가 마이그레이션을 통해 테이블을 관리하는 것을 원하지 않을 것입니다. 이를 설정하려면 모델의 Meta
클래스에 하나의 변수 만 추가해야합니다 ( managed = False
.
다음은 데이터베이스 뷰와 상호 작용할 관리되지 않는 모델을 작성하는 방법의 예입니다.
class Dummy(models.Model):
something = models.IntegerField()
class Meta:
managed = False
이것은 다음과 같이 SQL에 정의 된 뷰에 맵핑 될 수 있습니다.
CREATE VIEW myapp_dummy AS
SELECT id, something FROM complicated_table
WHERE some_complicated_condition = True
이 모델을 만든 후에는 다른 모델처럼 사용할 수 있습니다.
>>> Dummy.objects.all()
[<Dummy: Dummy object>, <Dummy: Dummy object>, <Dummy: Dummy object>]
>>> Dummy.objects.filter(something=42)
[<Dummy: Dummy object>]
고급 모델
모델은 객체에 대한 데이터보다 훨씬 많은 정보를 제공 할 수 있습니다. 예제를 보면서 다음과 같이 유용한 예제로 나누십시오.
from django.db import models
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Book(models.Model):
slug = models.SlugField()
title = models.CharField(max_length=128)
publish_date = models.DateField()
def get_absolute_url(self):
return reverse('library:book', kwargs={'pk':self.pk})
def __str__(self):
return self.title
class Meta:
ordering = ['publish_date', 'title']
자동 기본 키
get_absolute_url
메소드에서 self.pk
를 사용할 수 있습니다. pk
필드는 모델의 기본 키에 대한 별칭입니다. 또한 django는 기본 키가 없으면 자동으로 추가합니다. 걱정하지 않아도되고 외장형 키를 모든 모델에 설정하고 쉽게 가져올 수 있습니다.
절대 URL
정의 된 첫 x 째 기능은 get_absolute_url
입니다. 이렇게하면 책이 있다면 url 태그, 해결, 속성 등을 사용하지 않고도 책에 대한 링크를 얻을 수 있습니다. 간단히 book.get_absolute_url
호출하면 올바른 링크를 얻을 수 있습니다. 보너스로 django 관리자의 객체는 "사이트에서보기"버튼을 얻을 것입니다.
문자열 표현
__str__
메서드를 사용하면 개체를 표시해야 할 때 사용할 수 있습니다. 예를 들어 이전 방법을 사용하면 템플릿에 책에 대한 링크를 추가하는 것이 <a href="{{ book.get_absolute_url }}">{{ book }}</a>
과 같이 간단합니다. 바로 그 지점으로. 이 방법은 또한 admin 드롭 다운에 표시되는 내용 (예 : 외래 키)을 제어합니다.
클래스 데코레이터를 사용하면 파이썬 2에서 __str__
및 __unicode__
에 대해 메서드를 한 번 정의 할 수 있으며 파이썬 3에서는 문제가 발생하지 않습니다. 응용 프로그램이 두 버전 모두에서 실행될 것으로 예상되는 경우 가야합니다.
민달팽이 장
슬러그 필드는 char 필드와 비슷하지만 더 적은 심볼을 허용합니다. 기본적으로 문자, 숫자, 밑줄 또는 하이픈 만 사용하십시오. 예를 들어 URL에서 멋진 표현을 사용하여 객체를 식별하려는 경우 유용합니다.
메타 클래스
Meta
클래스를 사용하면 전체 항목 컬렉션에 대해 더 많은 정보를 정의 할 수 있습니다. 여기서 기본 순서 만 설정됩니다. 예를 들어, ListView 객체에서 유용합니다. 그것은 정렬에 사용할 필드의 이상적인 짧은리스트를 취합니다. 여기서 책은 발행 날짜별로 먼저 정렬되고 날짜가 동일하면 제목순으로 정렬됩니다.
다른 빈도 속성은 verbose_name
및 verbose_name_plural
입니다. 기본적으로 모델의 이름에서 생성되며 정상이어야합니다. 그러나 복수형은 단순한 것에 's'를 덧붙여서 순진하다. 어떤 경우에는 명시 적으로 설정하려고 할 수도있다.
계산 된 값
모델 객체를 가져 오면 완전히 실현 된 클래스 인스턴스가됩니다. 따라서 폼과 시리얼 라이저 (Django Rest Framework와 같은)에서 추가 메서드에 액세스 할 수 있습니다.
파이썬 속성을 사용하면 다양한 상황으로 인해 데이터베이스에 저장되지 않은 추가 값을 표현할 수 있습니다.
def expire():
return timezone.now() + timezone.timedelta(days=7)
class Coupon(models.Model):
expiration_date = models.DateField(default=expire)
@property
def is_expired(self):
return timezone.now() > self.expiration_date
대부분의 경우 쿼리 세트의 주석으로 데이터를 보완 할 수 있지만 모델 속성으로 계산 된 값은 쿼리 범위 내에서 간단하게 계산할 수없는 계산에 이상적입니다.
또한 속성은 스키마의 일부가 아닌 python 클래스에서 선언되므로 쿼리에 사용할 수 없습니다.
모델의 문자열 표현 추가
인간이 읽을 수있는 모델 객체의 프리젠 테이션을 만들려면 Model.__str__()
메소드 (또는 Model.__unicode__()
를 구현해야한다. 이 메소드는 모델의 인스턴스에서 str()
을 호출 할 때마다 호출됩니다 str()
예 : 모델이 템플릿에서 사용될 때 포함). 다음은 그 예입니다.
책 모델을 만듭니다.
# your_app/models.py from django.db import models class Book(models.Model): name = models.CharField(max_length=50) author = models.CharField(max_length=50)
모델의 인스턴스를 만들고 데이터베이스에 저장합니다.
>>> himu_book = Book(name='Himu Mama', author='Humayun Ahmed') >>> himu_book.save()
인스턴스에서
print()
를 실행합니다 :>>> print(himu_book) <Book: Book object>
<Book : Book object> 는 기본 출력물로서 우리에게 도움이되지 않습니다. 이 문제를 해결하려면 __str__
메서드를 추가하십시오.
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Book(models.Model):
name = models.CharField(max_length=50)
author = models.CharField(max_length=50)
def __str__(self):
return '{} by {}'.format(self.name, self.author)
python_2_unicode_compatible
데코레이터는 코드가 파이썬 2와 호환되도록하려는 경우에만 필요합니다.이 데코레이터는 __str__
메소드를 복사하여 __unicode__
메소드를 작성합니다. django.utils.encoding
에서 가져 오기.
이제 우리가 print 함수를 book 인스턴스를 다시 호출하면 :
>>> print(himu_book)
Himu Mama by Humayun Ahmed
훨씬 낫다!
문자열 표현은 모델이 ForeignKeyField
및 ManyToManyField
필드에 대한 ModelForm
에서 사용될 때도 사용됩니다.
모델 믹스
같은 경우 다른 모델은 제품 수명주기에서 동일한 필드와 동일한 절차를 가질 수 있습니다. 코드 반복 상속없이 이러한 유사성을 처리 할 수 있습니다. 믹스 인 디자인 패턴은 전체 클래스를 상속하는 대신 일부 메소드와 속성을 상속 ( 또는 일부 포함 )합니다. 예를 보자.
class PostableMixin(models.Model):
class Meta:
abstract=True
sender_name = models.CharField(max_length=128)
sender_address = models.CharField(max_length=255)
receiver_name = models.CharField(max_length=128)
receiver_address = models.CharField(max_length=255)
post_datetime = models.DateTimeField(auto_now_add=True)
delivery_datetime = models.DateTimeField(null=True)
notes = models.TextField(max_length=500)
class Envelope(PostableMixin):
ENVELOPE_COMMERCIAL = 1
ENVELOPE_BOOKLET = 2
ENVELOPE_CATALOG = 3
ENVELOPE_TYPES = (
(ENVELOPE_COMMERCIAL, 'Commercial'),
(ENVELOPE_BOOKLET, 'Booklet'),
(ENVELOPE_CATALOG, 'Catalog'),
)
envelope_type = models.PositiveSmallIntegerField(choices=ENVELOPE_TYPES)
class Package(PostableMixin):
weight = models.DecimalField(max_digits=6, decimal_places=2)
width = models.DecimalField(max_digits=5, decimal_places=2)
height = models.DecimalField(max_digits=5, decimal_places=2)
depth = models.DecimalField(max_digits=5, decimal_places=2)
모델을 추상 클래스로 변환하려면 내부 Meta
클래스에서 abstract=True
를 언급해야합니다. Django는 데이터베이스의 추상 모델에 대한 테이블을 생성하지 않습니다. 그러나 Envelope
and Package
모델의 경우 해당 테이블이 데이터베이스에 작성됩니다.
또한 여러 모델에서 여러 모델 방법이 필요합니다. 따라서 이러한 방법은 코드 반복을 방지하기 위해 믹스 인에 추가 될 수 있습니다. 예를 들어 배달 날짜를 PostableMixin
으로 설정하는 메소드를 만들면 두 자식 모두로부터 액세스 할 수 있습니다.
class PostableMixin(models.Model):
class Meta:
abstract=True
...
...
def set_delivery_datetime(self, dt=None):
if dt is None:
from django.utils.timezone import now
dt = now()
self.delivery_datetime = dt
self.save()
이 메서드는 자식에서 다음과 같이 사용할 수 있습니다.
>> envelope = Envelope.objects.get(pk=1)
>> envelope.set_delivery_datetime()
>> pack = Package.objects.get(pk=1)
>> pack.set_delivery_datetime()
UUID 기본 키
모델은 기본적으로 자동 증가 (정수) 기본 키를 사용합니다. 이렇게하면 일련의 키 1, 2, 3이 제공됩니다.
모델에 대한 작은 변경으로 모델에 다른 기본 키 유형을 설정할 수 있습니다.
UUID 는 보편적으로 고유 한 식별자이며 ID로 사용할 수있는 32 자의 임의의 식별자입니다. 이것은 순차적 ID가 데이터베이스의 레코드에 할당되는 것을 원하지 않을 때 사용하는 좋은 옵션입니다. PostgreSQL에서 사용할 때 이것은 uuid 데이터 유형에 저장하고, 그렇지 않으면 char (32)에 저장합니다.
import uuid
from django.db import models
class ModelUsingUUID(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
생성 된 키는 7778c552-73fc-4bc4-8bf9-5a2f6f7b7f47
형식입니다.
계승
모델 간의 상속은 두 가지 방법으로 수행 할 수 있습니다.
- 공통의 추상 클래스 ( 「모델 믹스」의 예를 참조)
- 여러 테이블이있는 공통 모델
다중 테이블 상속은 공통 필드에 대한 하나의 테이블과 자식 모델 당 하나의 테이블을 생성합니다.
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
두 테이블, 하나 만듭니다 Place
와 하나의 Restaurant
숨겨진와 OneToOne
수 필드 Place
일반 필드를.
식당 객체를 가져올 때마다 장소 테이블에 대한 추가 쿼리가 필요합니다.