【发布时间】:2014-07-26 22:25:09
【问题描述】:
我在 Django 中实现了custom model field。它是一个图像字段,除了直接分配文件外,还允许分配 URL 字符串以从中加载图像。
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 子句中的打印语句触发 Error fetching upload/to/50e170bf-61b6-4670-90d1-0369a8f9bdb4.png。
我可以缩小从 Django 1.7c1 到 django/db/models/query.py 的调用范围。
def get(self, *args, **kwargs):
"""
Performs the query and returns a single object matching the given
keyword arguments.
"""
clone = self.filter(*args, **kwargs)
if self.query.can_filter():
clone = clone.order_by()
clone = clone[:MAX_GET_RESULTS + 1]
num = len(clone) # This line causes setting of my field
if num == 1:
return clone._result_cache[0]
# ...
为什么导致我的字段的__set__ 被执行的行?我可以验证输入值是一个有效的 URL 来解决这个问题,但我想先知道原因。
【问题讨论】:
-
您能否在错误发生的点(即在您的
except子句中)显示完整的回溯? -
@BrenBarn 这是link to the full traceback。
标签: python django python-3.x descriptor magic-function