我已经在 Django 中实现了一个自定义模型字段。它是一个图像字段,除了直接分配文件外,还允许分配 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 子句中的 print 语句Error fetching upload/to/50e170bf-61b6-4670-90d1-0369a8f9bdb4.png
。
我可以缩小对django/db/models/query.py
Django 1.7c1 的调用范围。
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 来解决这个问题,但我想先知道原因。