生产中的 Django Download/Upload 个文件
Django Download/Upload Files In Production
我有一个当前托管的 Django 项目。我正在提供静态文件,但不知道如何处理 MEDIA 文件夹中的用户文件上传/下载。我已经阅读了很多关于 Docker、Nginx 和 Gunicorn 的文章,但不知道我需要哪些,也不知道如何设置它们。我已经学习了不少于 20 个教程并观看了不少于 15 个 YouTube 视频,但仍然感到困惑(我已经访问了所有 Google 搜索的前 2 页的每个 link)。
我的问题是,我需要其中哪些才能允许用户从网站 upload/download 文件?最重要的是,我已经尝试让所有三个都工作但无法弄清楚它们,当然我不是唯一一个对此有如此困难的人,有没有好的 resource/tutorial 可以指导我完成这个过程(我花了 40 多个小时阅读这些东西并试图让它发挥作用,我已经到了只要它起作用的地步,我不关心理解它们是如何组合在一起的) ?
谢谢。
edit - 这是所请求内容的精简版本。我没有包含 html,因为这是我第一次这样做,而且我已经使用了 Ajax 之类的东西,它完全是一团糟,我肯定会让你感到困惑。
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static_media')
STAT=os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [ STAT,
os.path.join('static/'),
os.path.join('templates/static/'), # for overridden templates css
]
view.py
class UploadView(View):
def get(self, request):
files_list = UploadedFile.objects.all()
return render(self.request, 'users/modules.html', {'files': files_list})
def post(self, request, *args, **kwargs):
data = {}
form = UploadedFileForm(self.request.POST, self.request.FILES)
form.instance.data_id = self.request.POST['data_id']
if form.is_valid():
uploaded_file = form.save()
谢谢。
所以您想知道如何使您的(在开发环境中工作)项目准备好投入生产。让我们从需要哪些组件开始
- 网络服务器(Nginx)
- 应用服务器(uWSGI)
- 应用程序(Django)
Web 服务器 服务于用户的请求。它知道如何为请求生成正确的输出——从文件系统读取文件,将请求进一步传递给应用程序服务器等等。 Nginx 是不错的选择。
Application Server 是 Web Server 和 Application 之间的中间人。它可以产生应用程序实例(进程),平衡这些实例之间的负载,重启死实例和许多其他事情。 uWSGI在这里是不错的选择。
Application - 在您的情况下,它是您在开发环境中工作的 Django 项目。你已经准备好了一切,但很可能你应该稍微调整一下设置。 Django 将通过 WSGI 协议与 Application Server 通信。
此时您还应该了解 Web 浏览器将如何加载、呈现和显示您的网站。一切都始于想要打开您网站上的页面的用户,例如 http://example.com/uploads。浏览器将向您的服务器发送 HTTP GET 请求,Web 服务器程序 (Nginx) 将捕获此请求并决定下一步做什么。
由于该特定请求与某个静态文件(静态 HTML 文件或静态 JPEG 图像等)无关 - Nginx 将决定将请求传递给应用程序服务器。 uWSGI 将获取请求并将其转发给 Django。
Django 将使用所有 urls.py
文件来找到正确的视图来为 http://example.com/upload 页面生成响应。你的观点会做什么?
def get(self, request):
files_list = UploadedFile.objects.all()
return render(self.request, 'users/modules.html', {'files': files_list})
它将 return HTML 页面(呈现的模板)。这样 HTML 文档将被 return 返回到应用程序服务器,然后返回到 Web 服务器,最后返回到用户的 Web 浏览器。
然后浏览器将开始解析该 HTML 文档,很可能它会找到一些额外的资源来加载 - css、javascript、图像、字体...对于每个资源 - 它将向 Web 服务器发出额外的 GET 请求。而这次 Web Server 不会将请求推送到 Application Server。它只会从文件系统读取这些文件,然后 return 返回给浏览器。
那些资源不是动态的,它们是静态的。所以你基本上将它们存储在 static
命名空间下。例如:
- http://example.com/static/main.css
- http://example.com/static/main.js
- http://example.com/static/logo.png
- ...
这些文件是您的应用程序的一部分。您的应用程序随附这些文件。但也有一些文件可以上传到您的系统。您可以将这些文件保存在任何地方——文件系统、数据库……但是您必须有它们的 URL。通常是 media
命名空间:
在这两种情况下 - 这些调用将只转发到 Web 服务器,然后转发到文件系统。
为什么您看到您的开发环境中的一切都在运行?这可能是因为您 运行 应用 python manage.py runserver
。在那种情况下 - Django 也是您的 Web 服务器(并且不会有应用程序服务器中间人)。所以它会管理它自己的实例,它会得到用户的请求,它会 return 静态文件,它会 return “媒体”文件,它会 return 动态生成的页面等等。
上述每个组件都需要有自己的配置文件。让我向您展示一些可用于您的项目的示例。
网络服务器 (Nginx)
sites-enabled/default.conf
upstream uwsgi {
server uwsgi:8080;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
error_log /var/log/nginx/error.log;
charset utf-8;
location /media {
alias /home/web/media;
expires 7d;
}
location /static {
alias /home/web/static;
expires 7d;
}
location / {
uwsgi_pass uwsgi;
include uwsgi_params;
}
}
备注:
- http://example.com/static 下的所有内容都将转到文件系统(
/home/web/static
目录)
- 例如:http://example.com/static/css/main.css ->
/home/web/static/css/main.css
- http://example.com/media 下的所有内容都将转到文件系统(
/home/web/media
目录)
- 例如:http://example.com/media/reports/john-02-12-2020.pdf ->
/home/web/media/reports/john-02-12-2020.pdf
- 其他所有内容都将传递给 uWSGI(传递给主机
uwsgi
,传递给端口 8080
)
应用服务器 (uWSGI)
uwsgi.conf
[uwsgi]
req-logger = file:/var/log/uwsgi-requests.log
logger = file:/var/log/uwsgi-errors.log
workers = %k
# enable-threads = true
# threads = 4
chdir = /home/web/app
module = core.wsgi
master = true
pidfile=/tmp/app.pid
socket = 0.0.0.0:8080
env = DJANGO_SETTINGS_MODULE=core.settings
memory-report = true
harakiri = 60
listen = 10240
备注:
chdir = /home/web/app
- 这是您的应用程序的路径
module = core.wsgi
- 你的应用程序应该有主(核心)应用程序的目录,名为 core
(你应该在那里看到 wsgi.py
)
pidfile=/tmp/app.pid
- 只是 pid 文件的地方
socket = 0.0.0.0:8080
- 它将监听端口 8080
env = DJANGO_SETTINGS_MODULE=core.settings
- 同样,您需要调用主应用程序 core
(它应该在 core
目录中)并且您应该在其中包含 settings.py
)
Docker / Docker 撰写
您可能需要 Docker 和 Docker Compose 来协调所有软件。但是没有它也可以尝试 运行 一切。
docker-compose.yml
version: "2.4"
services:
uwsgi:
build:
context: ./docker
dockerfile: Dockerfile
hostname: uwsgi
sysctls:
net.core.somaxconn: 10240
environment:
- DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE}
- C_FORCE_ROOT=${C_FORCE_ROOT}
volumes:
- ./config/uwsgi/uwsgi.conf:/uwsgi.conf
- ../app:/home/web/app
- ./static:/home/web/static:rw
- ./media:/home/web/media:rw
- ./logs:/var/log/
restart: always
networks:
myapp_backend:
aliases:
- uwsgi
web:
image: nginx
hostname: nginx
sysctls:
net.core.somaxconn: 10240
depends_on:
- uwsgi
volumes:
# - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./config/nginx/sites-enabled:/etc/nginx/conf.d
- ./media:/home/web/media:ro
- ./static:/home/web/static:ro
- ./logs:/var/log/nginx
ports:
- "80:80"
# - "443:443"
restart: always
networks:
- myapp_backend
networks:
myapp_backend:
Dockerfile
FROM python:3.9.0
RUN export DEBIAN_FRONTEND=noninteractive
ENV DEBIAN_FRONTEND noninteractive
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN apt-get install -y --fix-missing && apt-get update -y
RUN apt-get install -y python3-pip \
python3-setuptools
COPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN pip install uwsgi
WORKDIR /home/web/app
EXPOSE 8080
CMD ["uwsgi", "--ini", "/uwsgi.conf"]
目录结构
您可以使用此存储库中的目录结构:https://github.com/ansysy24/GameEconomy/tree/master/deployment
并且不要忘记像这样添加 .env
文件 https://github.com/ansysy24/GameEconomy/blob/master/deployment/.env_template(但你应该重命名 ofc)
我有一个当前托管的 Django 项目。我正在提供静态文件,但不知道如何处理 MEDIA 文件夹中的用户文件上传/下载。我已经阅读了很多关于 Docker、Nginx 和 Gunicorn 的文章,但不知道我需要哪些,也不知道如何设置它们。我已经学习了不少于 20 个教程并观看了不少于 15 个 YouTube 视频,但仍然感到困惑(我已经访问了所有 Google 搜索的前 2 页的每个 link)。
我的问题是,我需要其中哪些才能允许用户从网站 upload/download 文件?最重要的是,我已经尝试让所有三个都工作但无法弄清楚它们,当然我不是唯一一个对此有如此困难的人,有没有好的 resource/tutorial 可以指导我完成这个过程(我花了 40 多个小时阅读这些东西并试图让它发挥作用,我已经到了只要它起作用的地步,我不关心理解它们是如何组合在一起的) ?
谢谢。
edit - 这是所请求内容的精简版本。我没有包含 html,因为这是我第一次这样做,而且我已经使用了 Ajax 之类的东西,它完全是一团糟,我肯定会让你感到困惑。
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static_media')
STAT=os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [ STAT,
os.path.join('static/'),
os.path.join('templates/static/'), # for overridden templates css
]
view.py
class UploadView(View):
def get(self, request):
files_list = UploadedFile.objects.all()
return render(self.request, 'users/modules.html', {'files': files_list})
def post(self, request, *args, **kwargs):
data = {}
form = UploadedFileForm(self.request.POST, self.request.FILES)
form.instance.data_id = self.request.POST['data_id']
if form.is_valid():
uploaded_file = form.save()
谢谢。
所以您想知道如何使您的(在开发环境中工作)项目准备好投入生产。让我们从需要哪些组件开始
- 网络服务器(Nginx)
- 应用服务器(uWSGI)
- 应用程序(Django)
Web 服务器 服务于用户的请求。它知道如何为请求生成正确的输出——从文件系统读取文件,将请求进一步传递给应用程序服务器等等。 Nginx 是不错的选择。
Application Server 是 Web Server 和 Application 之间的中间人。它可以产生应用程序实例(进程),平衡这些实例之间的负载,重启死实例和许多其他事情。 uWSGI在这里是不错的选择。
Application - 在您的情况下,它是您在开发环境中工作的 Django 项目。你已经准备好了一切,但很可能你应该稍微调整一下设置。 Django 将通过 WSGI 协议与 Application Server 通信。
此时您还应该了解 Web 浏览器将如何加载、呈现和显示您的网站。一切都始于想要打开您网站上的页面的用户,例如 http://example.com/uploads。浏览器将向您的服务器发送 HTTP GET 请求,Web 服务器程序 (Nginx) 将捕获此请求并决定下一步做什么。
由于该特定请求与某个静态文件(静态 HTML 文件或静态 JPEG 图像等)无关 - Nginx 将决定将请求传递给应用程序服务器。 uWSGI 将获取请求并将其转发给 Django。
Django 将使用所有 urls.py
文件来找到正确的视图来为 http://example.com/upload 页面生成响应。你的观点会做什么?
def get(self, request):
files_list = UploadedFile.objects.all()
return render(self.request, 'users/modules.html', {'files': files_list})
它将 return HTML 页面(呈现的模板)。这样 HTML 文档将被 return 返回到应用程序服务器,然后返回到 Web 服务器,最后返回到用户的 Web 浏览器。
然后浏览器将开始解析该 HTML 文档,很可能它会找到一些额外的资源来加载 - css、javascript、图像、字体...对于每个资源 - 它将向 Web 服务器发出额外的 GET 请求。而这次 Web Server 不会将请求推送到 Application Server。它只会从文件系统读取这些文件,然后 return 返回给浏览器。
那些资源不是动态的,它们是静态的。所以你基本上将它们存储在 static
命名空间下。例如:
- http://example.com/static/main.css
- http://example.com/static/main.js
- http://example.com/static/logo.png
- ...
这些文件是您的应用程序的一部分。您的应用程序随附这些文件。但也有一些文件可以上传到您的系统。您可以将这些文件保存在任何地方——文件系统、数据库……但是您必须有它们的 URL。通常是 media
命名空间:
在这两种情况下 - 这些调用将只转发到 Web 服务器,然后转发到文件系统。
为什么您看到您的开发环境中的一切都在运行?这可能是因为您 运行 应用 python manage.py runserver
。在那种情况下 - Django 也是您的 Web 服务器(并且不会有应用程序服务器中间人)。所以它会管理它自己的实例,它会得到用户的请求,它会 return 静态文件,它会 return “媒体”文件,它会 return 动态生成的页面等等。
上述每个组件都需要有自己的配置文件。让我向您展示一些可用于您的项目的示例。
网络服务器 (Nginx)
sites-enabled/default.conf
upstream uwsgi {
server uwsgi:8080;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
error_log /var/log/nginx/error.log;
charset utf-8;
location /media {
alias /home/web/media;
expires 7d;
}
location /static {
alias /home/web/static;
expires 7d;
}
location / {
uwsgi_pass uwsgi;
include uwsgi_params;
}
}
备注:
- http://example.com/static 下的所有内容都将转到文件系统(
/home/web/static
目录) - 例如:http://example.com/static/css/main.css ->
/home/web/static/css/main.css
- http://example.com/media 下的所有内容都将转到文件系统(
/home/web/media
目录) - 例如:http://example.com/media/reports/john-02-12-2020.pdf ->
/home/web/media/reports/john-02-12-2020.pdf
- 其他所有内容都将传递给 uWSGI(传递给主机
uwsgi
,传递给端口8080
)
应用服务器 (uWSGI)
uwsgi.conf
[uwsgi]
req-logger = file:/var/log/uwsgi-requests.log
logger = file:/var/log/uwsgi-errors.log
workers = %k
# enable-threads = true
# threads = 4
chdir = /home/web/app
module = core.wsgi
master = true
pidfile=/tmp/app.pid
socket = 0.0.0.0:8080
env = DJANGO_SETTINGS_MODULE=core.settings
memory-report = true
harakiri = 60
listen = 10240
备注:
chdir = /home/web/app
- 这是您的应用程序的路径module = core.wsgi
- 你的应用程序应该有主(核心)应用程序的目录,名为core
(你应该在那里看到wsgi.py
)pidfile=/tmp/app.pid
- 只是 pid 文件的地方socket = 0.0.0.0:8080
- 它将监听端口8080
env = DJANGO_SETTINGS_MODULE=core.settings
- 同样,您需要调用主应用程序core
(它应该在core
目录中)并且您应该在其中包含settings.py
)
Docker / Docker 撰写
您可能需要 Docker 和 Docker Compose 来协调所有软件。但是没有它也可以尝试 运行 一切。
docker-compose.yml
version: "2.4"
services:
uwsgi:
build:
context: ./docker
dockerfile: Dockerfile
hostname: uwsgi
sysctls:
net.core.somaxconn: 10240
environment:
- DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE}
- C_FORCE_ROOT=${C_FORCE_ROOT}
volumes:
- ./config/uwsgi/uwsgi.conf:/uwsgi.conf
- ../app:/home/web/app
- ./static:/home/web/static:rw
- ./media:/home/web/media:rw
- ./logs:/var/log/
restart: always
networks:
myapp_backend:
aliases:
- uwsgi
web:
image: nginx
hostname: nginx
sysctls:
net.core.somaxconn: 10240
depends_on:
- uwsgi
volumes:
# - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./config/nginx/sites-enabled:/etc/nginx/conf.d
- ./media:/home/web/media:ro
- ./static:/home/web/static:ro
- ./logs:/var/log/nginx
ports:
- "80:80"
# - "443:443"
restart: always
networks:
- myapp_backend
networks:
myapp_backend:
Dockerfile
FROM python:3.9.0
RUN export DEBIAN_FRONTEND=noninteractive
ENV DEBIAN_FRONTEND noninteractive
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN apt-get install -y --fix-missing && apt-get update -y
RUN apt-get install -y python3-pip \
python3-setuptools
COPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN pip install uwsgi
WORKDIR /home/web/app
EXPOSE 8080
CMD ["uwsgi", "--ini", "/uwsgi.conf"]
目录结构
您可以使用此存储库中的目录结构:https://github.com/ansysy24/GameEconomy/tree/master/deployment
并且不要忘记像这样添加 .env
文件 https://github.com/ansysy24/GameEconomy/blob/master/deployment/.env_template(但你应该重命名 ofc)