试图理解Django源代码和缺少参数TypeError的原因

dvt*_*tan 3 python django boto django-storage

如果您有垂直监视器,我的IDE和Traceback 的屏幕截图(纵向视图)显示此处粘贴的所有代码可能更容易阅读.

上下文:尝试ImageField使用S3BotoStorage 将图像从URL保存到EC2上托管的Django ,并使用S3上的文件.我很困惑,因为所有这些都表明Django仍然像本地存储一样对待它,而它应该是S3.

有问题的行似乎导致了错误:

def get_filename(self, filename):
    return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename)))

def get_valid_name(self, name):
    """
    Returns a filename, based on the provided filename, that's suitable for
    use in the target storage system.
    """
    return get_valid_filename(name)
Run Code Online (Sandbox Code Playgroud)

TypeError异常: get_valid_name() missing 1 required positional argument: 'name'

最后一个本地变量在错误之前跟踪get_valid_name:

filename        'testimagefilename'
self        <django.db.models.fields.files.ImageField: image>
Run Code Online (Sandbox Code Playgroud)

(只有这两个水平分隔线内的东西来自我,其余来自Django 1.9)

image.image.save('testimagefilename', File(temp), save=True)
Run Code Online (Sandbox Code Playgroud)

来自Traceback的本地变量(不确定ValueErroron image,我认为是因为它尚未创建):

File        <class 'django.core.files.base.File'>
image       Error in formatting: ValueError: The 'image' attribute has no file associated with it.
requests        <module 'requests' from '/usr/local/lib/python3.4/site-packages/requests/__init__.py'>
Image       <class 'mcmaster.models.Image'>
NamedTemporaryFile      <function NamedTemporaryFile at 0x7fb0e1bb0510>
temp        <tempfile._TemporaryFileWrapper object at 0x7fb0dd241ef0>
Run Code Online (Sandbox Code Playgroud)

Django源代码的相关片段:

files.py

def save(self, name, content, save=True):
    name = self.field.generate_filename(self.instance, name)

    if func_supports_parameter(self.storage.save, 'max_length'):
        self.name = self.storage.save(name, content, max_length=self.field.max_length)
    else:
        warnings.warn(
            'Backwards compatibility for storage backends without '
            'support for the `max_length` argument in '
            'Storage.save() will be removed in Django 1.10.',
            RemovedInDjango110Warning, stacklevel=2
        )
        self.name = self.storage.save(name, content)

    setattr(self.instance, self.field.name, self.name)

    # Update the filesize cache
    self._size = content.size
    self._committed = True

    # Save the object because it has changed, unless save is False
    if save:
        self.instance.save()
save.alters_data = True

def get_directory_name(self):
    return os.path.normpath(force_text(datetime.datetime.now().strftime(force_str(self.upload_to))))

def get_filename(self, filename):
    return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename)))

def generate_filename(self, instance, filename):
    # If upload_to is a callable, make sure that the path it returns is
    # passed through get_valid_name() of the underlying storage.
    if callable(self.upload_to):
        directory_name, filename = os.path.split(self.upload_to(instance, filename))
        filename = self.storage.get_valid_name(filename)
        return os.path.normpath(os.path.join(directory_name, filename))

    return os.path.join(self.get_directory_name(), self.get_filename(filename))
Run Code Online (Sandbox Code Playgroud)

storage.py

def get_valid_name(self, name):
    """
    Returns a filename, based on the provided filename, that's suitable for
    use in the target storage system.
    """
    return get_valid_filename(name)
Run Code Online (Sandbox Code Playgroud)

text.py

def get_valid_filename(s):
    """
    Returns the given string converted to a string that can be used for a clean
    filename. Specifically, leading and trailing spaces are removed; other
    spaces are converted to underscores; and anything that is not a unicode
    alphanumeric, dash, underscore, or dot, is removed.
    >>> get_valid_filename("john's portrait in 2004.jpg")
    'johns_portrait_in_2004.jpg'
    """
    s = force_text(s).strip().replace(' ', '_')
    return re.sub(r'(?u)[^-\w.]', '', s)
get_valid_filename = allow_lazy(get_valid_filename, six.text_type)
Run Code Online (Sandbox Code Playgroud)

Buf*_*fke 7

我猜你没有实例化Storage类.你是如何设置Django使用自定义存储?如果你在models.py中这样做

image = models.ImageField(storage=MyStorage)

它会像你描述的那样完全失败.它应该是

image = models.ImageField(storage=MyStorage())