django S3 - 修剪图像文件名但不是网址路径

时间:2018-01-18 05:25:57

标签: python django amazon-s3 imagefield

这是我的问题的后续问题:ImageField / FileField Django form Currently unable to trim the path to filename

在我的Django应用程序中,有一个上传到S3的图像字段 修剪图像文件路径名后,无法访问该图像,因为该网址已被修剪。如何修剪显示但不修剪路径?

我设法修剪显示文件名的显示器

class CustomClearableFileInput(ClearableFileInput):

    def get_context(self, name, value, attrs):
        logging.debug("%s",name)
        logging.debug("%s",value)
        value.name = path.basename(value.name)
        context = super().get_context(name, value, attrs)       
        return context

    class CompanySettingEdit(forms.ModelForm):
       company_logo = forms.ImageField(widget=CustomClearableFileInput)

这是输出:

https://imgur.com/a/M42Mz <-- display correct
https://bucketname.s3.amazonaws.com/media/certiport_logo.png <-- invalid url

如果我不修剪它:

class CustomClearableFileInput(ClearableFileInput):

    def get_context(self, name, value, attrs):
        logging.debug("%s",name)
        logging.debug("%s",value)
        # value.name = path.basename(value.name) <-- remove this
        context = super().get_context(name, value, attrs)       
        return context

    class CompanySettingEdit(forms.ModelForm):
       company_logo = forms.ImageField(widget=CustomClearableFileInput)

这是输出:

https://imgur.com/a/rGi8f <-- display incorrect
https://bucketname.s3.amazonaws.com/media/company_logo/15/certiport_logo.png <--valid url

我的目标是:

display: certiport_logo.png
url: https://bucketname.s3.amazonaws.com/media/company_logo/15/certiport_logo.png

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:0)

FileField / ImageField的url属性是动态的:它取决于name属性,就像str()在调用它时所做的那样。相反,让我们写一些除name以外的内容并更改模板以使用它:

class CustomClearableFileInput(ClearableFileInput):
    template_name = 'path/to/clearable_file_input.html'
    # less confusing place than get_context...
    def format_value(self, value):
        if self.is_initial(value):
            value.basename = path.basename(value.name)
            return value

对于模板(从django源修改和漂亮打印)

{% if widget.is_initial %}
    {{ widget.initial_text }}: 
    <a href="{{ widget.value.url }}">
        {{ widget.value.basename }} {# <== CHANGE #}
    </a>
    {% if not widget.required %}
        <input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}" />
        <label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>
    {% endif %}
    <br /> {{ widget.input_text }}:
{% endif %}
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %} />

答案 1 :(得分:0)

如果您是出于Django管理员的目的这样做,则可能会对您有所帮助。 您可以将任何内容保存在“图像”字段的名称中,因为它只是用于构建图像URL的名称。

现在,当您打开其中包含Image字段的Django admin时,表单将调用settings.py中定义为DEFAULT_FILE_STORAGE的Storage类。

DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'

现在,此FileSystemStorage类负责为映像创建URL,当您在管理员中单击映像名称时,该URL将打开。

现在满足您的需求。由于您要求图像名称仅为certiport_logo.png,因此可以将此名称保存到图像字段并覆盖FileSystemStorage类的url函数来创建URL。这是例子

from django.core.files.storage import FileSystemStorage


class CustomStorage(FileSystemStorage):
    """
    Override django default storage class to build urls
    """
    def url(self, name):
        return "https://bucketname.s3.amazonaws.com/media/company_logo/15/{}".format(name)

根据您对不同Django模型的需要覆盖url函数,即使使用正确的图像URL,也将仅显示图像名称。 确保将新的类路径设置为settings.py

DEFAULT_FILE_STORAGE = 'apps.commons.custom_storage.CustomStorage'

答案 2 :(得分:-1)

在您的情况下,我建议JSONField而不是ImageField。通过这种方式,你可以拥有:

obj.my_image_field = {'display': 'certiport_logo.png', 'url': 'your_S3_url'}
obj.save()

类示例:

class MyModel(models.Model):
    my_image_field = JSONField()

    def get_image_display(self):
        return self.my_image_field.get('display', None)

    def get_image_url(self):
        return self.my_image_field.get('url', None)