python - 我应该将图像上传到 Django 中的静态目录吗?

标签 python django file-upload permissions static-files

我有一个包含图像字段的模型。

from django.db import models
from django.contrib.auth.models import User


class Customer(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=127)
    logo = models.ImageField(upload_to='customer/logo', null=True, blank=True)

    def __str__(self):
        return self.name

在我看来,我从指定的 url 下载图像并将其存储在图像字段中。为了进行测试,我使用测试用户作为外键。

import json
import urllib.request

from django.core.files.base import ContentFile
from django.http import HttpResponse
from django.contrib.auth.models import User

from customer.models import Customer


def create(request):
    values = json.loads(request.body.decode('utf-8'))
    values['user'] = User.objects.get(id=1)
    values['logo'] = ContentFile(urllib.request.urlopen(values['logo']).read(),
                                                                    'test.png')
    model = Customer.objects.create(**values)
    return HttpResponse('Created customer with ' + str(values))

图像按预期上传到 customer/logo/test.png。现在,如何在前端显示这些图像?我可以将它们保存到静态文件目录中,但只有相关用户才能访问它。

(顺便说一下,Django 管理界面显示有一个为 Customer 对象上传的文件。但它链接到 http://localhost:8000/admin/customer/customer/20/customer/logo/test.png 这是一个错误的位置,导致找不到页面。)

最佳答案

FileFieldImageField 的文件是相对于 settings.MEDIA_ROOT 上传的,应该可以通过附加到 的相同相对文件名访问>settings.MEDIA_URL。这就是您的管理界面指向错误网址的原因。出于安全原因,这些应该不同于 STATIC_ROOTSTATIC_URL,否则 Django 将引发 ImproperlyConfiguredError

这不会阻止用户访问他们不应该看到的文件,如果他们知道或可以猜到 url。为此,您需要通过 Django 而不是您选择的 Web 服务器来提供这些私有(private)文件。基本上你需要在web根目录下指定一个私有(private)目录,如果用户有权限查看这些文件,你需要加载这些文件。例如:

from django.core.files.storage import FileSystemStorage

PRIVATE_DIR = os.path.join(ROOT_DIR, 'web-private')
fs = FileSystemStorage(location=PRIVATE_DIR)

class Customer(models.Model):
    logo = models.ImageField(upload_to='customer/logo', storage=fs, null=True, blank=True)

在您看来,您必须提供此文件。我当前项目中的自定义应用程序之一使用以下函数发送静态文件:

import mimetypes
from django.http import HttpResponse # StreamingHttpResponse
from django.core.servers.basehttp import FileWrapper

def send_file(file):
    """
    Send a file through Django without loading the whole file into
    memory at once. The FileWrapper will turn the file object into an
    iterator for chunks of 8KB.
    """
    filename = file.name
    if settings.PRIVATE_MEDIA_USE_XSENDFILE:
        # X-sendfile
        response = HttpResponse()
        response['X-Accel-Redirect'] = filename  # Nginx
        response['X-Sendfile'] = filename        # Apache 2, mod-xsendfile
        # Nginx doesn't overwrite headers, but does add the missing headers.
        del response['Content-Type']
    else:
        # Can use django.views.static.serve() method (which supports if-modified-since),
        # but this also does the job well, as it's mainly for debugging.
        mimetype, encoding = mimetypes.guess_type(filename)
        response = HttpResponse(FileWrapper(file), content_type=mimetype)
        response['Content-Length'] = os.path.getsize(filename)
    return response

然后在您的 View 中使用send_file(customer.logo)

Django >= 1.5 应该使用新的 StreamingHttpResponse 而不是 HttpResponse

关于python - 我应该将图像上传到 Django 中的静态目录吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23457774/

相关文章:

javascript - 通过JavaScript获取文档中文件上传的文件名

python - 如何将包含多个值和逗号的变量写入 csv 文件?

python - 如何使用 Docker 容器作为 virtualenv 从 IDE 运行 Python 测试?

python - TensorFlow, tf.reshape 导致 "Gradients do not exist for variables"

python - 如何使用 Tensorflow Optimizer 而不重新计算强化学习程序中的激活,从而在每次迭代后返回控制?

python - 反转 '' *'',参数 '()' 和关键字参数 '{}' 未找到

django - 我如何在序列化器中计算?

django - Docker 的 postgres 容器的密码验证失败

c# - 使用 HttpWebRequest 发送大文件,根据需要增加/缩小缓冲区

java - 如何在 Ruby 中访问上传的文件