提问人:Revero 提问时间:9/28/2023 最后编辑:Revero 更新时间:11/1/2023 访问量:97
Django Webapp 的 CGI 部署,例如 Strato.de Webhosting
CGI deployment for a Django Webapp e.g. Strato.de Webhosting
问:
IAM 尝试通过 strato.de 上的 CGI 部署我的 Django 应用程序。Strato 仅支持基本的 cgi,因此 iam 被迫使用此方法。
通过本教程,我已经通过 cgi 在 strato 上运行了一个烧瓶应用程序(顺便说一句,很棒的指南)。我试图改变它并将其熟练地用于 django 应用程序以使其在 Web 服务器上运行,但看起来我遗漏了一些东西。
如果我调用该网站,我会遇到 500 内部服务器错误。(我也会感谢一些如何调试这个的提示,我不知道从哪里开始)。提一下:在开发环境中一切正常。
已完成的步骤:
- 我确实检查了 requirements.txt 文件中列出的服务器上是否安装了所有必需的软件包。
- 我确实创建了一个 cgi 文件来加载带有 django cgi-handler 的 django 应用程序
pip install django-cgi
- 更改了部署 settings.py(密钥设置、允许的主机设置、debug = false)
- 阅读部署指南和官方文档
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q')
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
ALLOWED_HOSTS = ['*']
我确实设置了,因为我读到如果 django 为空 [] ,它就不会运行。allowed_hosts=['*']
问:是否有可能我必须使用一些 bash 命令设置Secret_key,以便应用程序找到它? 问:我到底需要将allowed_hosts
设置为什么?类似 allowed_hosts=['www.website.de']
settings.py 文件:
"""
Django settings for commerce project.
Generated by 'django-admin startproject' using Django 3.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
from urllib.parse import urlparse
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
#SECRET_KEY = '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q'
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q')
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'trainer',
'tinymce',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'denisevreden.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'denisevreden.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
AUTH_USER_MODEL = 'trainer.User'
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# The absolute path to the directory where collectstatic will collect static files for deployment.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# rest of the code
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'
# Email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.strato.de'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = *******
EMAIL_HOST_PASSWORD = *******
#csrf settings
CSRF_TRUSTED_ORIGINS = ['https://*.mydomain.com','https://*.127.0.0.1', 'https://localhost:8000']
# TinyMCE settings
TINYMCE_JS_URL = 'https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js'
TINYMCE_COMPRESSOR = False
TINYMCE_DEFAULT_CONFIG = {
"height": "320px",
"width": "960px",
"menubar": "file edit view insert format tools table help",
"plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code "
"fullscreen insertdatetime table paste code help wordcount spellchecker",
"toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft "
"aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor "
"backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | "
"fullscreen preview save print | insertfile image pageembed template link anchor codesample | "
"a11ycheck ltr rtl | showcomments addcomment code",
"custom_undo_redo_levels": 10,
}
manage.py 文件:
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import dependencies
import os, sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'denisevreden.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
** cgi_handler.py:**
#!/usr/local/python/3.10.4/bin/python
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
快乐的 .cgi 文件:
#!/usr/bin/python3
import os
import sys
#!/usr/bin/env python
import os
import sys
# Add the path to the Django project to the system path
sys.path.append('/mnt/web315/a3/18/512337018/htdocs/.cgi-bin/Happy-dv')
# Set the environment variable to tell Django where the settings module is
os.environ['DJANGO_SETTINGS_MODULE'] = 'Happy-dv.settings'
# Import the CGIHandler class
from wsgiref.handlers import CGIHandler
# Run the application using the CGIHandler
CGIHandler().run(application)
try:
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
except Exception as err:
print("Content-Typ: text/html\n\n")
print(err)
dependencies.py 文件:
#!/usr/bin/python3
import os
import sys
#!/usr/bin/env python
import os
import sys
# Add the path to the Django project to the system path
sys.path.append('/mnt/web315/a3/18/512337018/htdocs/.cgi-bin/Happy-dv')
# Set the environment variable to tell Django where the settings module is
os.environ['DJANGO_SETTINGS_MODULE'] = 'Happy-dv.settings'
# Import the CGIHandler class
from wsgiref.handlers import CGIHandler
# Run the application using the CGIHandler
CGIHandler().run(application)
try:
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
except Exception as err:
print("Content-Typ: text/html\n\n")
print(err)
谢谢
答:
有一个 CGI 脚本可用于 Django。
然而,这确实有一些严重的缺点。
因为CGI的工作方式;每次发出请求时,它都会生成一个新进程。
这基本上意味着它将在每个请求上启动 django。
它还可能具有一些严重的安全隐患;如上所列。
CGI软件有可能产生一些巨大的安全漏洞 在您的系统上。如果它们被粗心地编程,它们允许 在互联网上将 Unix 命令输入到表单中的恶人 并让它们在您的 Web 服务器上执行。本文介绍了 确保 CGI 软件安全的基础知识。
撇开这一点不谈;该脚本在以下 GitHub 存储库中公开发布:https://github.com/chibiegg/django-cgi/blob/master/django-python3.cgi
回购相当旧;所以我不能保证它会开箱即用。
#!/home/user/.pyenv/versions/envname/bin/python
# encoding: utf-8
"""
django-.cgi
A simple cgi script which uses the django WSGI to serve requests.
Code copy/pasted from PEP-0333 and then tweaked to serve django.
http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side
This script assumes django is on your sys.path, and that your site code is at
/djangoproject/src. Copy this script into your cgi-bin directory (or do
whatever you need to to make a cgi script executable on your system), and then
update the paths at the bottom of this file to suit your site.
This is probably the slowest way to serve django pages, as the python
interpreter, the django code-base and your site code has to be loaded every
time a request is served. FCGI and mod_python solve this problem, use them if
you can.
In order to speed things up it may be worth experimenting with running
uncompressed zips on the sys.path for django and the site code, as this can be
(theorectically) faster. See PEP-0273 (specifically Benchmarks).
http://www.python.org/dev/peps/pep-0273/
Make sure all python files are compiled in your code base. See
http://docs.python.org/lib/module-compileall.html
"""
import os, sys
# Change this to the directory above your site code.
# sys.path.append("/home/user/local/lib/python3.4/site-packages")
# sys.path.append("/djangoproject/src")
def run_with_cgi(application):
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin.buffer
environ['wsgi.errors'] = sys.stderr.buffer
environ['wsgi.version'] = (1,0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS','off') in ('on','1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
def write(data):
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent:
# Before the first output, send the stored headers
status, response_headers = headers_sent[:] = headers_set
sys.stdout.buffer.write(('Status: %s\r\n' % status).encode("ascii"))
for header in response_headers:
sys.stdout.buffer.write(('%s: %s\r\n' % header).encode("ascii"))
sys.stdout.buffer.write(('\r\n').encode("ascii"))
sys.stdout.buffer.write(data)
sys.stdout.buffer.flush()
def start_response(status,response_headers,exc_info=None):
if exc_info:
try:
if headers_sent:
# Re-raise original exception if headers sent
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
finally:
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status,response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
result.close()
# Change to the name of your settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'application.settings'
from django.core.wsgi import get_wsgi_application
run_with_cgi(get_wsgi_application())
评论
export DJANGO_SECRET_KEY="my-super-secure-key"
["www.example.com", "example.com"]