Trying to understand Django source code and cause of missing argument TypeError

让人想犯罪 __ 提交于 2019-12-10 18:45:46

问题


A screenshot (portrait view) of my IDE and Traceback showing all the code pasted here, may be easier to read if you have a vertical monitor.

Context: Trying to save image from a URL to a Django ImageField hosted on EC2 with files on S3 using S3BotoStorage. I'm confused because all of this suggests that Django is still treating it like local storage, while it should S3.

The lines in question that seem to be causing the error:

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)

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

Last Local vars Tracback before error at get_valid_name:

filename        'testimagefilename'
self        <django.db.models.fields.files.ImageField: image>

(Only the stuff inside these two horizontal dividers is from me, the rest is from Django 1.9)

image.image.save('testimagefilename', File(temp), save=True)

Local vars from Traceback at that point (not sure about the ValueError on image, I think it's because it hasn't been created yet):

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>

Relevant snippets of Django source code:

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))

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)

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)

回答1:


I'd make a guess you didn't instantiate the Storage class. How are you setting Django to use the custom storage? If you do this in models.py

image = models.ImageField(storage=MyStorage)

It will fail exactly as you describe. It should be

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



来源:https://stackoverflow.com/questions/34101916/trying-to-understand-django-source-code-and-cause-of-missing-argument-typeerror

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!