Django 외부 키 할당 문제 에 대한 자세 한 설명
class Article(models.Model):
title = models.CharField(max_length=1024, default='')
...
def __str__(self):
return 'Article pk:%d %s' % (self.pk, self.title[:30])
class ArticleContent(models.Model):
article = cached_fields.OneToOneField(Article)
...
코드 를 쓸 때 이상 한 현상 을 발 견 했 습 니 다.인 스 턴 스 의 외 키 를 주 었 을 때(로)id 끝)할당(숫자)을 할 때 이 외부 키 에 대응 하 는 intance 의 값 은 변 하지 않 습 니 다.
In [44]: ac = ArticleContent.objects.get(article_id=14269)
In [45]: ac.article_id
Out[45]: 14269
In [46]: ac.article_id = 14266
In [47]: ac.save()
In [48]: ac.article
Out[48]: <Article: Article pk:14266 EC: Russia, Ukraine to Meet in>
In [49]: ac.article.pk
Out[49]: 14266
위의 코드 에서 보 듯 이 답 을 찾기 위해 Django 의 소스 코드 를 뒤 적 였 습 니 다.
django/db/models/fields/related_descriptors.py
def __get__(self, instance, cls=None):
"""
Get the related instance through the forward relation.
With the example above, when getting ``child.parent``:
- ``self`` is the descriptor managing the ``parent`` attribute
- ``instance`` is the ``child`` instance
- ``cls`` is the ``Child`` class (we don't need it)
"""
if instance is None:
return self
# The related instance is loaded from the database and then cached in
# the attribute defined in self.cache_name. It can also be pre-cached
# by the reverse accessor (ReverseOneToOneDescriptor).
try:
rel_obj = getattr(instance, self.cache_name)
except AttributeError:
val = self.field.get_local_related_value(instance)
if None in val:
rel_obj = None
else:
qs = self.get_queryset(instance=instance)
qs = qs.filter(self.field.get_reverse_related_filter(instance))
# Assuming the database enforces foreign keys, this won't fail.
rel_obj = qs.get()
# If this is a one-to-one relation, set the reverse accessor
# cache on the related object to the current instance to avoid
# an extra SQL query if it's accessed later on.
if not self.field.remote_field.multiple:
setattr(rel_obj, self.field.remote_field.get_cache_name(), instance)
setattr(instance, self.cache_name, rel_obj)
if rel_obj is None and not self.field.null:
raise self.RelatedObjectDoesNotExist(
"%s has no %s." % (self.field.model.__name__, self.field.name)
)
else:
return rel_obj
주석 이 매우 잘 되 어 있 습 니 다.우리 가 요청ac.article
할 때 먼저 해당 하 는 cache(여기 서 4567914)를 검사 합 니 다.관심 이 있 으 면_article_cache
의 생 성 규칙 을 볼 수 있 습 니 다.바로 외 키 이름 앞 에 밑줄 을 치고 뒤에 cache 를 추가 하 는 것 입 니 다.존재 하지 않 으 면 데이터 베 이 스 를 요청 하고 요청 이 끝 난 후에 cache 에 저장 합 니 다.다시 보 자
cache_name
.코드 가 너무 길 면 붙 이지 않 는 다__set__
방법 아래 에 있다).외부 키 필드__get__
에 값 을 부여 하 는 것 외 에 도 pk 필드article
,article_id
의 값 을 None 로 설정 하여 다음 요청 시 정확 한 값 을 얻 을 수 있 습 니 다.이상 은 모두 ForeignKey 의 Magic 입 니 다.우리 가
lh_field.attname
에 값 을 부 여 했 을 때 일반적인 attribute 에 값 을 부 여 했 을 뿐,어떠한 magic 도 없 었 습 니 다.외부 키 에 대응 하 는 cache 를 청소 하지 않 았 습 니 다.이때 받 은 intance 는 여전히 cache 에 있 는 원래 의 인 스 턴 스 입 니 다.총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Django의 질문 및 답변 웹사이트환영 친구, 이것은 우리의 새로운 블로그입니다. 이 블로그에서는 , 과 같은 Question-n-Answer 웹사이트를 만들고 있습니다. 이 웹사이트는 회원가입 및 로그인이 가능합니다. 로그인 후 사용자는 사용자의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.