고급 Django 모델:Python 개발 개선
이 글에서 우리는 이러한 이념, Django의 핵심 특성, 심지어 일부 라이브러리를 이용하여 우리가 모델을 개선하는 방법을 연구할 것이다.
getter/setter/deleter 속성
파이썬의 2.2 버전 이래의 기능으로서 속성의 사용법은 하나의 속성처럼 보이지만 실제로는 하나의 방법이다.비록 모델에서 속성을 사용하는 것이 그렇게 선진적이지는 않지만, 우리는 파이톤 속성의 일부 충분히 이용되지 않은 특성을 사용하여 우리의 모델을 더욱 강하게 할 수 있다.
Django의 내장 인증을 사용하거나
AbstractBaseUser
사용자 정의 인증을 사용하면 last_login
모델에 정의된 User
필드를 잘 알 수 있습니다. 이것은 사용자가 지난번에 프로그램에 로그인했을 때 저장한 시간 스탬프입니다.last_login
를 사용하고 싶지만 last_seen
라는 필드를 캐시에 더 자주 저장하면 쉽게 할 수 있다.우선, 우리는 Python 속성을 만들어서 캐시에서 값을 찾을 것입니다. 만약 찾지 못하면 데이터베이스에서 값을 되돌려줍니다.
accounts/models.py
from django.contrib.auth.base_user import AbstractBaseUser
from django.core.cache import cache
class User(AbstractBaseUser):
...
@property
def last_seen(self):
"""
Returns the 'last_seen' value from the cache for a User.
"""
last_seen = cache.get('last_seen_{0}'.format(self.pk))
# Check cache result, otherwise return the database value
if last_seen:
return last_seen
return self.last_login
주의: 나는 이미 모델을 간소화했다. 왜냐하면 이 블로그에 단독 강좌 전문 소개customizing the built-in Django user model가 있기 때문이다.위의 속성은 캐시에 있는 사용자의
last_seen
값을 검사합니다. 내용을 찾지 못하면 모델에서 사용자가 저장한 last_login
값을 되돌려줍니다.참고<instance>.last_seen
는 현재 매우 간단한 인터페이스 뒤에 우리 모델에 더욱 맞춤형 속성을 제공한다.값을 속성
some_user.last_seen = some_date_time
에 할당하거나 속성del some_user.last_seen
에서 값을 삭제할 때의 사용자 정의 행동으로 확장할 수 있습니다....
@last_seen.setter
def last_seen(self, value):
"""
Sets the 'last_seen_[uuid]' value in the cache for a User.
"""
now = value
# Save in the cache
cache.set('last_seen_{0}'.format(self.pk), now)
@last_seen.deleter
def last_seen(self):
"""
Removes the 'last_seen' value from the cache.
"""
# Delete the cache key
cache.delete('last_seen_{0}'.format(self.pk))
...
현재, 값이 last_seen
속성에 분배될 때마다, 우리는 그것을 캐시에 저장하고, 값이 del
삭제될 때 캐시에서 삭제합니다.파이썬 문서에는 사용setter
과 deleter
가 기술되어 있지만 Django 모델을 연구할 때 야외에서 보기 드물다.전통적인 데이터베이스에 오래 지속될 필요가 없는 것들을 저장하거나 성능 때문에 전통적인 데이터베이스에 오래 지속되어서는 안 된다는 용례가 있을 수 있습니다.상술한 예시 중의 사용자 정의 속성을 사용하는 것은 좋은 해결 방안이다.
유사한 용례에서
python-social-auth
라이브러리는 제3자 플랫폼(예를 들어 GitHub과 트위터)을 이용하여 사용자의 신분 검증을 관리하는 도구로 사용자가 로그인한 플랫폼의 정보에 따라 데이터베이스에 업데이트된 정보를 만들고 관리한다.어떤 경우, 되돌아오는 정보가 데이터베이스에 있는 필드와 일치하지 않습니다.예를 들어 python-social-auth
라이브러리는 사용자를 만들 때 fullname
키워드 파라미터를 전달한다.만약에 저희 데이터베이스에서 full_name
를 속성명으로 사용한다면 저희는 곤경에 빠질 수 있습니다.이 문제를 해결하는 간단한 방법 중 하나는 위의
getter/setter
모드를 사용하는 것입니다.@property
def fullname(self) -> str:
return self.full_name
@fullname.setter
def fullname(self, value: str):
self.full_name = value
현재 python-social-auth
사용자의 fullname
를 모델 new_user.fullname = 'Some User'
에 저장할 때, 우리는 그것을 캡처하여 데이터베이스 필드 full_name
에 저장할 것입니다.모델 관계식 통과하기
Djangomany-to-many relationships는 복잡한 대상 관계를 간단하게 처리하는 좋은 방법이지만, 이들이 만든
intermediate models
에 사용자 정의 속성을 추가할 수 있는 능력을 제공할 수 없습니다.기본적으로, 이것은 대상을 연결하는 데 사용되는 식별자와 두 개의 외부 키 인용만 포함한다.Django
ManyToManyField through
매개변수를 사용하여 이 중간 모델을 직접 생성하고 필요한 다른 필드를 추가할 수 있습니다.예를 들어 만약에 우리 프로그램이 사용자가 그룹에서 구성원 신분을 가지고 있어야 할 뿐만 아니라 구성원 신분이 언제 시작되는지 추적해야 한다면 우리는 맞춤형 중간 모델을 사용하여 이 점을 실현할 수 있다.
accounts/models.py
import uuid
from django.contrib.auth.base_user import AbstractBaseUser
from django.db import models
from django.utils.timezone import now
class User(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
…
class Group(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
members = models.ManyToManyField(User, through='Membership')
class Membership(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
joined = models.DateTimeField(editable=False, default=now)
위의 예에서 우리는 여전히 ManyToManyField
를 사용하여 사용자와 그룹 간의 관계를 처리하지만 Membership
키워드 매개 변수 전달through
모델을 사용하면 joined
사용자 정의 속성을 모델에 추가하여 구성원의 시작 시간을 추적할 수 있다.이 through
모델은 표준 Django 모델로 하나의 메인 키(우리는 여기서 UUID를 사용)와 두 개의 외부 키만 있으면 대상을 연결할 수 있다.같은 3가지 모델을 사용하여 웹 사이트에 간단한 구독 데이터베이스를 만들 수 있습니다.
import uuid
from django.contrib.auth.base_user import AbstractBaseUser
from django.db import models
from django.utils.timezone import now
class User(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
...
class Plan(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=50, unique=True, default='free')
subscribers = models.ManyToManyField(User, through='Subscription', related_name='subscriptions', related_query_name='subscriptions')
class Subscription(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
created = models.DateTimeField(editable=False, default=now)
updated = models.DateTimeField(auto_now=True)
cancelled = models.DateTimeField(blank=True, null=True)
여기서, 우리는 사용자가 처음으로 구독하는 시간, 그들이 구독을 업데이트하는 시간, 그리고 우리가 코드 경로를 추가하면, 사용자가 언제 우리 프로그램에 대한 구독을 취소했는지 추적할 수 있다.through
모델을 ManyToManyField
와 함께 사용하는 것은 우리의 중간 모델에 더 많은 데이터를 추가하고 사용자에게 더 전면적인 체험을 제공하는 좋은 방법으로 대량의 추가 작업을 할 필요가 없다.에이전트 모델
일반적으로 Django에서 모델의 하위 클래스화(추상 모델 포함)를 새 클래스에 포함할 때 프레임워크는 이 클래스에 새로운 데이터베이스 테이블을 만들고 이를
OneToOneField
해서 부모 데이터베이스 테이블에 연결합니다.Django는 "multi-table inheritance"이라고 하는데 이것은 기존 모델의 필드와 구조를 다시 사용하고 그 안에 자신의 데이터를 추가하는 좋은 방법입니다.Django 디자인 철학이 말한 것처럼 "너 자신을 되풀이하지 마라."다중 테이블 상속 예:
from django.db import models
class Vehicle(models.Model):
model = models.CharField(max_length=50)
manufacturer = models.CharField(max_length=80)
year = models.IntegerField(max_length=4)
class Airplane(Vehicle):
is_cargo = models.BooleanField(default=False)
is_passenger = models.BooleanField(default=True)
이 예는 창설될 것이다...... continue with Proxy Models
자크 클랜시(Zac Clancy)는 전 세계 오물(재난 즉시 응답 팀)의 부회장이다.
Reference
이 문제에 관하여(고급 Django 모델:Python 개발 개선), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kite/advanced-django-models-improve-your-python-development-2i6k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)