我应该将图像上传到Django中的静态目录吗? [英] Should I upload images to a static directory in Django?

查看:95
本文介绍了我应该将图像上传到Django中的静态目录吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have this model containing an image field.

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下载图像并将其存储在image字段中.为了进行测试,我将测试用户用作外键.

In my view, I download the image from the specified url and store it in the image field. For testing, I use a test user as foreign key.

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.现在,如何在前端显示这些图像?我可以将它们保存到静态文件目录中,但是只有相关用户才能访问它.

The image gets uploaded to customer/logo/test.png as expected. Now, how can I display those images in the frontend? I could save them into the static files directory, but only the related user should be able to access it.

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

(By the way, Django admin interface shows that there is a file uploaded for the Customer object. But it links to http://localhost:8000/admin/customer/customer/20/customer/logo/test.png which is a wrong location and leads to a not found page.)

推荐答案

FileFieldImageField的文件是相对于settings.MEDIA_ROOT上载的,并且应使用与settings.MEDIA_URL相同的相对文件名进行访问.这就是为什么您的管理界面指向错误的URL的原因.出于安全原因,它们应该与STATIC_ROOTSTATIC_URL不同,否则Django将引发ImproperlyConfiguredError.

The files for FileField and ImageField are uploaded relative to settings.MEDIA_ROOT and should be accessible by the same relative filename appended to settings.MEDIA_URL. This is why your admin interface points to the wrong url. For security reasons these should be different than STATIC_ROOT and STATIC_URL, otherwise Django will raise an ImproperlyConfiguredError.

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

This will not prevent users from accessing files they shouldn't see, if they know or can guess the url. For this you will need to serve these private files through Django, instead of your web server of choice. Basically you need to specify a private directory under the web root level, and you need to load these files if the user has permission to see the file. E.g.:

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)

在您看来,您将必须提供此文件.我当前项目中的一个自定义应用程序使用以下功能发送静态文件:

In your view you will have to serve this file. One of the custom apps on my current project uses the following function to send static files:

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

,然后在视图中使用send_file(customer.logo).

And then use send_file(customer.logo) in your view.

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

Django >= 1.5 should use the new StreamingHttpResponse instead of HttpResponse.

这篇关于我应该将图像上传到Django中的静态目录吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆