2014-07-26 5 views
0

장고에 custom model field을 구현했습니다. 파일을 직접 할당하는 것 외에도 URL 문자열에서 이미지를로드 할 수 있도록 허용하는 이미지 필드입니다.왜 len()이 내 클래스의 __set__을 실행합니까?

import uuid 
import urllib.request 

from django.core.files.base import ContentFile 
from django.db import models 
from django.db.models.fields.files import ImageFileDescriptor 


class UrlImageFileDescriptor(ImageFileDescriptor): 
    def __set__(self, instance, value): 
     # If a string is used for assignment, it is used as URL 
     # to fetch an image from and store it on the server. 
     if isinstance(value, str): 
      try: 
       response = urllib.request.urlopen(value) 
       image = response.read() 
       name = str(uuid.uuid4()) + '.png' 
       value = ContentFile(image, name) 
      except: 
       print('Error fetching', value) 
       pass 
     super().__set__(instance, value) 


class UrlImageField(models.ImageField): 
    descriptor_class = UrlImageFileDescriptor 

일반적으로 필드가 작동합니다. 그러나 어떤 이유로 Django 자체는 문자열 값을 내부적으로 할당합니다. 필드를 사용하는 모델의 쿼리 집합이 필터링 될 때마다 __set__이 문자열과 함께 호출되므로 except 절의 print 문은 Error fetching upload/to/50e170bf-61b6-4670-90d1-0369a8f9bdb4.png을 발생시킵니다.

Django 1.7c1에서 django/db/models/query.py으로 전화를 협상 할 수 있습니다.

왜 내 필드의 __set__이 실행되는 줄이 있습니까? 입력 값을 유효 URL로 확인하여이 문제를 해결할 수는 있지만 그 이유를 먼저 알고 싶습니다.

+0

오류가 발생한 지점 (즉, except 절 내)에서 전체 추적을 표시 할 수 있습니까? – BrenBarn

+0

@BrenBarn 다음은 [전체 추적에 대한 링크]입니다 (http://pastebin.com/D27CA2QP). – danijar

답변

4

이야기가 추적 기록에 있습니다.

File "C:\repository\virtualenv\lib\site-packages\django\db\models\query.py" in get 
    350.   num = len(clone) 

그것은 목록에 모든 쿼리 결과를 가져옵니다 : 각 쿼리 결과에 대한

File "C:\repository\virtualenv\lib\site-packages\django\db\models\query.py" in __len__ 
    122.   self._fetch_all() 
File "C:\repository\virtualenv\lib\site-packages\django\db\models\query.py" in _fetch_all 
    966.    self._result_cache = list(self.iterator()) 

이는 DB의 데이터를 사용하여 모델 객체를 생성 : 쿼리의 길이를 얻으려면

File "C:\repository\virtualenv\lib\site-packages\django\db\models\base.py" in __init__ 
    383.     setattr(self, field.attname, val) 
:
File "C:\repository\virtualenv\lib\site-packages\django\db\models\query.py" in iterator 
    275.      obj = model(*row_data) 

모델 객체를 생성하려면,이 모델의 각 필드를 설정합니다 사용자 정의 모델 필드에 __set__를 호출하는 바람이 0

:

File "C:\repository\invoicepad\apps\customer\fields.py" in __set__ 
    18.       response = urllib.request.urlopen(value) 

내가 장고에 대해 내가 돈 때문에 그 잘 모른다 모두 있기 때문에,이 뒤에 더 큰 규모의 이유에 대한 자세한 말을하기 어렵다 DB 구조가 어떤 것인지 알 수 없습니다. 그러나 기본적으로 설명자를 구현 한 방법에 대해 실제로 유효하지 않은 데이터가 데이터베이스 필드에 채워지는 것처럼 보이게됩니다 (UriImageField). (예를 들어, 오류로 판단하면 db에는 'upload/to/50e170bf-61b6-4670-90d1-0369a8f9bdb4.png'이 있지만 실제로는 그런 파일은 없습니다.)

+0

감사! 이 경로는 장고가 파일 필드에 대해 데이터베이스에 저장하는 경로입니다. 장고가 파일 필드에 평범한 문자열을 먼저 할당하는 것을 나는 몰랐다. 해당 경로에 파일이 있지만 동일한 서버의 미디어 루트와 관련이 있으므로 URL로 가져 오기가 실패합니다. – danijar