【问题标题】:django S3 - trim imagefield filename but not the url pathdjango S3 - 修剪图像字段文件名,但不修剪 url 路径
【发布时间】:2018-06-27 02:47:49
【问题描述】:

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

在我的 Django 应用程序中,有一个图像字段上传到 S3 修剪图像文件路径名后,由于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)
        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

我怎样才能做到这一点?

【问题讨论】:

  • 我不确定这是否是最佳选择 - 如果有人将两张图片上传到 /company_logo/15/certiport_logo.png/company_logo/14/certiport_logo.png 会怎样?/media/certiport_logo.png 会指向什么?
  • 好吧...可以随机化它。这不是问题。问题是网址不正确。我希望它使用实际的 url 指向修剪后的名称。
  • 您是否尝试向您的 CompanySetting 模型添加一个属性,该属性返回一个修剪后的 url 并让 company_logo 字段成为实际的完整 url?
  • 有什么用?问题更多的是链接(url)不正确。目前您可以使用 .url 获取正确的 url。问题是显示并将其链接到正确的网址。不可能吗?

标签: python django amazon-s3 imagefield


【解决方案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)

【讨论】:

    【解决方案2】:

    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" %} />
    

    【讨论】:

      【解决方案3】:

      如果您这样做是为了 Django 管理员,那么它可能会对您有所帮助。 您可以在 Image 字段的名称中保存任何内容,因为它只是用于构建图像 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'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-01
        • 1970-01-01
        • 2012-03-24
        • 2012-10-10
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        相关资源
        最近更新 更多