【问题标题】:How to serve static files to AWS when deploying Django app (`python manage.py collectstatic` didn't work)?部署 Django 应用程序时如何向 AWS 提供静态文件(`python manage.py collectstatic` 不起作用)?
【发布时间】:2017-07-16 17:11:36
【问题描述】:

昨天,我创建了这个帖子:DjangoRestFramework browsable api looks different locally vs when deployed on server?

基本上,当我执行python manage.py runserver 时,会显示:

但在我将其部署到 AWS (eb deploy) 后,我在访问该站点时看到的是:

上面帖子的答案提到这是因为我的静态文件丢失了。于是我搜索了如何在 AWS 上部署静态文件,偶然发现了这个教程:http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-django.html#python-django-update-app

在“创建站点管理员”部分下,它提到为了提供静态文件,我必须首先在settings.py 中定义STATIC_ROOT(所以我做了:STATIC_ROOT = os.path.join(BASE_DIR, "ebdjangoapp/static/"))然后我做了eb deploy .但是,该站点看起来仍然与第二张图片相同(没有静态文件)。然后我尝试做python manage.py collectstatic(这创建了一个静态文件夹,其中包含rest_framework 目录,包含css 文件等),然后又做了eb deploy,但该站点看起来与第二张图像相同。

为什么静态文件还没有显示出来?

注意,我搜索了一下,发现了这个帖子:Django app deployment not loading static files,答案是:

“然后,您需要通过您选择的 Web 服务器为 settings.STATIC_URL 提供 settings.STATIC_ROOT,通常使用 nginx 作为 Apache-mod_wsgi 应用服务器后面的反向代理。”

但我不知道网络服务器(nginx、反向代理、Apache-mod_wsgi)是如何工作的。我有一个使用 python manage.py runserver 在本地运行的 Django 应用程序,并且我有 AWS 弹性 beanstalk。我通过 eb deploy 将我的 Django 应用程序部署到 AWS。为了让静态文件出现在部署中,我需要采取哪些步骤(假设我不知道如何配置 nginx、反向代理等)。?

【问题讨论】:

  • 您是否随时运行python manage.py collectstatic
  • @GrahamDumpleton 是的,我在eb deploy 之前就这样做了。 (基本上,我是在本地做的,所有的文件都放在静态文件夹中,然后我部署它)。

标签: django amazon-web-services django-rest-framework


【解决方案1】:

有关于从 RealPython 将 django 应用程序部署到 AWS Elastic Beanstalk 的权威指南 - here it is。 它有关于静态文件以及如何使用 eb 配置它的整个部分,您不需要了解有关 nginx/apache 等的任何信息。

基本上你应该在你的 eb 配置中定义container_commands,这些命令将在应用程序部署完成后执行。例如migratecollectstatic,所以这是 eb 配置文件中此类部分的示例:

container_commands:
  01_migrate:
    command: "source /opt/python/run/venv/bin/activate && python iotd/manage.py migrate --noinput"
    leader_only: true
  02_collectstatic:
    command: "source /opt/python/run/venv/bin/activate && python iotd/manage.py collectstatic --noinput"

option_settings:
  "aws:elasticbeanstalk:application:environment":
    DJANGO_SETTINGS_MODULE: "iotd.settings"
    "PYTHONPATH": "/opt/python/current/app/iotd:$PYTHONPATH"
    "ALLOWED_HOSTS": ".elasticbeanstalk.com"
  "aws:elasticbeanstalk:container:python":
    WSGIPath: iotd/iotd/wsgi.py
    NumProcesses: 3
    NumThreads: 20
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "www/static/"

注意aws:elasticbeanstalk:container:python:staticfiles部分。 你也应该在你的 django 设置文件中定义这部分:

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

我几乎完全从上面的文章中复制了这个例子,你真的应该检查一下,太棒了。

UPD:如何调试丢失的静态文件。 我通常这样做(它涉及到您的 eb 实例):

  1. 确保django.contrib.staticfiles 包含在我的INSTALLED_APPS 中。
  2. 在浏览器控制台 URL 中检查丢失的文件,例如 /static/js/somefile.js
  3. 确保在我的 django 设置中STATIC_URL 是相同的,例如/static/
  4. 检查STATIC_ROOT 中的实际值并检查此文件夹是否实际包含您在生产服务器中的静态文件。
  5. 检查我的 eb 配置是否指向正确的文件夹(在配置中的 option_settings 部分下)

您还可以尝试将静态收集到生产服务器上的/static 目录中(这是 eb 默认查找它们的位置)。如果它突然开始工作 - 这意味着您的设置未能覆盖默认设置,您应该检查它的其他定义位置。

我希望这些步骤能帮助您找到正确的方向。

【讨论】:

  • 感谢您的链接。所以我编辑了settings.py,所以STATIC_ROOTSTATIC_URL 就是你提到的。然后我在.ebextensions 文件夹中创建了一个名为02_python.config 的文件,并复制粘贴了您在此处发布的内容。我将iotd 更改为ebdjango(我的项目名称......我的应用程序名称是ebdjangoapp)。然后我将python ebjango/manage.py collectstatic --noinput 更改为python manage.py collectstatic --noinput(因为python 路径已经指向ebdjango)。但它仍然不起作用(服务器看起来仍然像我发布的第二张图片)。知道如何调试此问题吗?
  • 答案更新了可能的调试步骤,希望对您有所帮助。
  • 这次更新帮了大忙!现在,当我让STATIC_ROOT = os.path.join(BASE_DIR, "static") 并且在我的option_settings 配置文件中没有提及staticfiles 时,它可以工作(默认位置,如您所述)!当我在option_settings 中给出"aws:elasticbeanstalk:container:python:staticfiles" 的绝对或相对路径时,它也可以正常工作。但是当我将STATIC_ROOT 更改为os.path.join(BASE_DIR, "..", "www", "static") 并在我的option_settings 中执行"/static/": "www/static/" 时,它会为静态文件提供404。当我让它等于"/static/": "../www/static/" 时,它会给出一个 403 的静态值。
  • 403 表示某些内部 Web 服务器无权访问此文件夹。修复它的最简单方法是授予此访问权限,但您必须知道此服务器的实际用户名,这很不方便。顺便说一句,我认为您仅将 eb 实例用于静态文件作为初始教程。下一步将为此使用 S3 存储桶:)
  • 注意:使用 Amazon Linux 2 时,命名空间为 aws:elasticbeanstalk:environment:proxy:staticfiles。见the ELB docs
【解决方案2】:

这对我有用。

.config 文件中删除所有静态文件指令。在软件配置下找到静态文件部分。左栏是您的每个 /static/ 网址。右边是相对于父目录的静态文件夹。

确保您的 STATIC_ROOT 设置与右侧的值匹配。不要忘记结尾的/

仍然粘贴我的设置。

 STATIC_URL = '/static/'
 STATICFILES_DIRS = ('assets',)
 STATIC_ROOT = os.path.join(BASE_DIR, '..', 'www', 'static')

这就是我的文件夹结构相对于设置文件的样子

project/
├── __init__.py
├── settings
│   ├── base.py
│   ├── __init__.py
│   ├── local.py
│   ├── production.py

wsgi.pyurls.py 位于project 文件夹中。 www 文件夹比 project 文件夹高一级。

希望这至少可以节省您的周日时间。

【讨论】:

  • 您好 Manu,我正在尝试实施您的解决方案,但我无法在软件配置下找到静态文件部分。您是如何启用虚拟路径的?
  • 您的回答很好,但可能不够清楚。 1. STATIC_ROOT 是你的目标目录,collectstatic 时会拉取找到的静态文件。我建议给这个值取一个像“static_build”这样的名字。 2. 在本地运行 collect static 并将 static_build 中的所有文件提交到您的源代码树。 3. 在 AWS 中或通过 .ebextensions/django.config 为每个虚拟路径设置 STATIC FILES 值。与尝试将服务器配置为在每次部署时运行 collectstatic 相比,这需要更少的配置。
猜你喜欢
  • 2020-09-11
  • 2021-09-08
  • 1970-01-01
  • 2021-03-05
  • 2015-05-17
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 2018-02-18
相关资源
最近更新 更多