如何在生产中提供媒体文件

时间:2020-09-28 01:12:22

标签: django

我有一个Django项目,该项目向用户发送带有附件pdf的自动电子邮件。目前,我只有一个普通的/media/文件夹,其中的pdf指向代码。这在开发中可行,但在生产中会引发服务器错误。

我的问题是如何在生产中管理media文件?我已经读了很多,但是找不到我想要的。

我在用于静态文件的生产环境中使用collectstatic,我希望media文件也能使用类似的东西。

网址

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('page.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

设置

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "static_media")

views.py(发送文件)

file_path = os.path.join(settings.STATIC_ROOT+'\\pdf\\free_pdf.pdf')
...
msg.attach_file(file_path)

passenger.wsgi

import os
import sys

sys.path.append(os.getcwd())
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi
from django.core.wsgi import get_wsgi_application
from whitenoise import WhiteNoise
SCRIPT_NAME = os.getcwd()
SCRIPT_NAME = '' #solution for damn link problem

class PassengerPathInfoFix(object):
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        from urllib.parse import unquote
        environ['SCRIPT_NAME'] = SCRIPT_NAME
        request_uri = unquote(environ['REQUEST_URI'])
        script_name = unquote(environ.get('SCRIPT_NAME', ''))
        offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0
        environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]
        return self.app(environ, start_response)
application = get_wsgi_application()
application = PassengerPathInfoFix(application)
application = WhiteNoise(application, root='/home/mysite/mysite/static_files')

(此代码来自我放弃媒体文件夹并试图仅将其与我的静态文件一起使用时的代码)

我的项目结构:

|project
|__app
|__static
|  |__app
|    |__style.css
|__media
|  |__app
|     |__pdfToBeSent
|__static_files (generated by collectstatic)
|__media_files (i created this)

collectstatic也不会将我的项目媒体文件复制到media_files中,我自己一直在其中复制它们(不确定)。

我还尝试将媒体文件移动到项目中的每个可能位置

我还在为带有白噪声的静态文件提供服务。

谢谢。

1 个答案:

答案 0 :(得分:1)

由于我处于类似情况(在同一主机上,A2Hosting),所以我将尝试分享对问题和我选择的解决方案的理解。

对不起,如果我在这次演讲中看起来很自以为是,我只是想追溯所有代表思想流向我寻求解决方案的观点。

一个小前提:如果使用“媒体文件”打算使用多媒体文件(例如图像等),我认为您不应该使用Django媒体文件夹,因为它旨在提供用户上传的文件 < / strong>。
不知道您的PDF是否确实由某些用户上传,我还是尝试公开我的解决方案。

在生产环境中,Django不会提供静态文件和媒体文件。
对于前者,我也使用了WhiteNoise,而对于后者,方法则有所不同(至少在共享托管基础上)。

当我们在 settings.py 中设置 Debug = False 时,我怀疑与Django项目一起创建的媒体文件夹变得有点难以读取/无法访问(我无法分辨如果是Django或托管服务商,或是两者的结合)。

处理媒体文件的官方方法确实是依靠外部存储服务(例如Amazon S3),但是此解决方案不适用于预算有限的情况。

在我的情况下,我的Django应用运行在与主域相关的子域上。
主要域: www.mydomain.com
应用程序域: subdomain.mydomain.com

保留使用Django项目创建的媒体文件夹,然后在以下unix路径中创建了另一个文件夹:
/home/A2hosting_username/subdomain.mydomain.com/media

然后,在 settings.py 中,我从以下位置更改了MEDIA_ROOT变量:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

收件人:

MEDIA_ROOT = '/home/A2hosting_username/subdomain.mydomain.com/media'

然后,在用于定义数据库并与之交互的 model.py 类中,我以这种方式指定了到上载媒体(在我的情况下为视频)的路径:

class Video(models.Model):
   name = models.CharField(max_length=50)
   path = models.FileField(upload_to="../media/videos", null=True, verbose_name="")

由于我们无权访问Apache配置文件,因此在其中编辑 .htaccess 文件(相对于 subdomain.mydomain.com )可能会很有用。通过以下方式,可以防止浏览器在上传的文件过重时“超时”:

<ifModule mod_headers.c>
    Header set Connection keep-alive
</ifModule>

我希望这会有所帮助。