我想在 Django 项目中提供所有类型的媒体文件,我使用 Whitenoise 来提供静态文件,并且静态文件运行良好,但在提供用户上传的图像时遇到问题(我正在使用 Linux 共享托管 Cpanel) ) 目录结构
Project_name
App_1
App_2
Staticfiles (that are collected via collectstatic cmd)
manage.py
passenger_wsgi.py
这是项目的settings.py
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATIC_URL = '/static/'
MEDIA_URL = ''
STATICFILES_DIRS =[
BASE_DIR/ 'static'
]
MEDIA_ROOT = BASE_DIR / 'staticfiles/images'
和文件 urls.py
urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
虽然不推荐,但如果您不使用 ngingx/apache 并且服务器较小,则可能需要它。 我的情况是我使用whitenoise 和gunicorn 在本地服务器上提供服务。
您可以通过为媒体文件创建视图来提供媒体文件。
在
myapp.views.py
def media(request, file_path=None):
from django.conf import settings as cfg
media_root = getattr(cfg, 'MEDIA_ROOT', None)
if not media_root:
return HttpResponseBadRequest('Invalid Media Root Configuration')
if not file_path:
return HttpResponseBadRequest('Invalid File Path')
with open(os.path.join(media_root, file_path), 'rb') as doc:
response = HttpResponse(doc.read(), content_type='application/doc')
response['Content-Disposition'] = 'filename=%s' % (file_path.split('/')[-1])
return response
现在在应用程序中添加网址
myapp.urls.py
url(r'^myapp/media/(?P<file_path>.+)+', myapp.views.media, name='media'),
在
settings.py
MEDIA_ROOT = os.path.abspath(__file__ + "../../../media")
MEDIA_URL = '/myapp/media/'
Whitenoise 仅在启动时检查静态文件,因此应用程序启动后添加的文件将不会被看到。
因为,Whitenose 不适合提供用户上传的媒体文件。
请查看 Whitenose 官方文档。 http://whitenoise.evans.io/en/latest/django.html#serving-media-files
如果您想在生产中从 django 提供媒体服务,只需基于原始静态函数创建您自己的
static
函数,如下所示:
#my_app/static.py
import re
from urllib.parse import urlsplit
from django.core.exceptions import ImproperlyConfigured
from django.urls import re_path
from django.views.static import serve
def static(prefix, view=serve, **kwargs):
"""
Return a URL pattern for serving files in debug mode.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"""
if not prefix:
raise ImproperlyConfigured("Empty static prefix not permitted")
elif urlsplit(prefix).netloc: # <- removed DEBUG from this line
# No-op if non-local prefix.
return []
return [
re_path(
r"^%s(?P<path>.*)$" % re.escape(prefix.lstrip("/")), view, kwargs=kwargs
),
]
Whitenoise 仅在启动时检查静态文件,因此应用程序启动后添加的文件将不会被看到。也就是说,只有在静态文件夹中找到的文件才能在静态页面/模板上使用。因此,Whitenose 不得用于提供用户上传的媒体文件。
要解决此问题,您需要设置一个新的子域来存储图像/媒体文件。例如:
media.your-domain.com
。这将在 public_html
中创建一个与您的子域同名的目录。这是您必须使用 django
以及在提供图像/媒体文件时存储/保存图像/媒体文件的位置(by Apache server
不再是 django
)。
编辑
settings.py
(位于 django 项目目录中)以通知 django 在哪里上传媒体文件。
MEDIA_ROOT = "/home/username/public_html/media.your-domain.com"
将用户名替换为
CPanel
和 media.your-domain.com
中的用户名
通过您创建的子域。
还将
MEDIA_URL
变量/常量设置/更改为:
MEDIA_URL = 'https://media.your-domain.com'
请记住将上面的地址更改为您创建的子域。经过 这样,
django
将不再服务器媒体文件/图像,因为将发送请求
到子域并由 Apache
在您的情况下处理。
在包含媒体文件的目录中创建一个名为
.haccess
的文件,这是带有子域名的文件夹,位于 public_html 中。
编辑文件并添加以下内容:
<IfModule mod_headers.c> Header set Access-Control-Allow-Origin "https://your-domain.com" </IfModule>
最后,通过添加以下内容来保护子域以防止目录列出 以下在同一文件中。
Options All -Indexes