Django在共享托管服务器中部署(Hostgator)

时间:2019-07-09 08:40:41

标签: python django web-hosting host

如何将django项目设置为我正在使用共享主机的hostgator服务器。

python是默认设置吗,还是需要在我的服务器(hostgator服务器)中设置?

请帮助我

1 个答案:

答案 0 :(得分:0)

可以在HostGator上共享Django。 Django放弃了对FastCGI的支持,这有点棘手。

  • 使用HostGator自己的说明设置Django。 http://support.hostgator.com/articles/django-with-fastcgi#shared-reseller

  • 但是在运行之前,您需要将对FastCGI的支持修补回Django。

    • 幸运的是,Django在一次提交中就删除了FastCGI: https://github.com/django/django/commit/41f0d3d3bc8b0a6831530e1176c6415f9ba45b0b.patch
    • 此修补程序需要反向并移植以指向您所拥有的版本。 这种要求需要检出django源项目并使用git。
    • 不必担心会破坏文档和测试子文件夹,因为无论如何它们都必须被排除在re-FastCGI-ification补丁之外。
    • 一旦准备好HostGator中安装的Django版本的补丁文件,请使用git apply将FastCGI支持重新注入到虚拟环境中的Django代码中 ./mydjango/lib/python2.7/site-packages/django
    • 最后是我最终得到的Django 1.10.1补丁文件。
  • 使用PyMySQL代替标准的mysql库。由于Host Gator不提供gcc,PyMySQL是纯Python mysql客户端。
    • 安装库:pip install PyMySQL
    • 通过在#!之后的两个文件的开头添加以下内容,将猴子修补在manage.py和index.fcgi中。 python行:
#monkey patch importing pymysql
try:
    import pymysql
    pymysql.install_as_MySQLdb()
except ImportError:
    pass

#Re-fast-cgi-ification-patch
From 51278286d278568dfe89263cad624204c01fa065 Mon Sep 17 00:00:00 2001
From: Joshua 
Date: Tue, 6 Sep 2016 18:19:20 -0400
Subject: django folder only

Revert "Removed FastCGI support per deprecation timeline; refs #20766." This reverts commit 41f0d3d3bc8b0a6831530e1176c6415f9ba45b0b. # Conflicts: # django/core/management/__init__.py # docs/howto/deployment/wsgi/index.txt # docs/man/django-admin.1 # docs/ref/django-admin.txt # tests/.coveragerc # Conflicts: # docs/man/django-admin.1 # docs/ref/django-admin.txt diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 576ff6b..8d1461f 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -415,8 +415,8 @@ X_FRAME_OPTIONS = 'SAMEORIGIN' USE_X_FORWARDED_HOST = False USE_X_FORWARDED_PORT = False -# The Python dotted path to the WSGI application that Django's internal server -# (runserver) will use. If `None`, the return value of +# The Python dotted path to the WSGI application that Django's internal servers +# (runserver, runfcgi) will use. If `None`, the return value of # 'django.core.wsgi.get_wsgi_application' is used, thus preserving the same # behavior as previous versions of Django. Otherwise this should point to an # actual WSGI application object. diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index 739dc25..2aa84d7 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -251,8 +251,13 @@ class ManagementUtility(object): # special case: the 'help' subcommand has no options elif cwords[0] in subcommands and cwords[0] != 'help': subcommand_cls = self.fetch_command(cwords[0]) + # special case: 'runfcgi' stores additional options as + # 'key=value' pairs + if cwords[0] == 'runfcgi': + from django.core.servers.fastcgi import FASTCGI_OPTIONS + options.extend((k, 1) for k in FASTCGI_OPTIONS) # special case: add the names of installed apps to options - if cwords[0] in ('dumpdata', 'sqlmigrate', 'sqlsequencereset', 'test'): + elif cwords[0] in ('dumpdata', 'sqlmigrate', 'sqlsequencereset', 'test'): try: app_configs = apps.get_app_configs() # Get the last part of the dotted path as the app name. diff --git a/django/core/management/commands/runfcgi.py b/django/core/management/commands/runfcgi.py new file mode 100644 index 0000000..98de800 --- /dev/null +++ b/django/core/management/commands/runfcgi.py @@ -0,0 +1,32 @@ +import argparse +import warnings + +from django.core.management.base import BaseCommand +from django.utils.deprecation import RemovedInDjango19Warning + + +class Command(BaseCommand): + help = "Runs this project as a FastCGI application. Requires flup." + + def add_arguments(self, parser): + parser.add_argument('args', nargs=argparse.REMAINDER, + help='Various KEY=val options.') + + def handle(self, *args, **options): + warnings.warn( + "FastCGI support has been deprecated and will be removed in Django 1.9.", + RemovedInDjango19Warning) + + from django.conf import settings + from django.utils import translation + # Activate the current language, because it won't get activated later. + try: + translation.activate(settings.LANGUAGE_CODE) + except AttributeError: + pass + from django.core.servers.fastcgi import runfastcgi + runfastcgi(args) + + def usage(self, subcommand): + from django.core.servers.fastcgi import FASTCGI_HELP + return FASTCGI_HELP diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 60fc09a..5560438 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -34,11 +34,13 @@ def get_internal_wsgi_application(): this will be the ``application`` object in ``projectname/wsgi.py``. This function, and the ``WSGI_APPLICATION`` setting itself, are only useful - for Django's internal server (runserver); external WSGI servers should just - be configured to point to the correct application object directly. + for Django's internal servers (runserver, runfcgi); external WSGI servers + should just be configured to point to the correct application object + directly. If settings.WSGI_APPLICATION is not set (is ``None``), we just return whatever ``django.core.wsgi.get_wsgi_application`` returns. + """ from django.conf import settings app_path = getattr(settings, 'WSGI_APPLICATION') diff --git a/django/core/servers/fastcgi.py b/django/core/servers/fastcgi.py new file mode 100644 index 0000000..b44473b --- /dev/null +++ b/django/core/servers/fastcgi.py @@ -0,0 +1,187 @@ +""" +FastCGI (or SCGI, or AJP1.3 ...) server that implements the WSGI protocol. + +Uses the flup python package: http://www.saddi.com/software/flup/ + +This is an adaptation of the flup package to add FastCGI server support +to run Django apps from Web servers that support the FastCGI protocol. +This module can be run standalone or from the django-admin / manage.py +scripts using the "runfcgi" directive. + +Run with the extra option "help" for a list of additional options you can +pass to this server. +""" + +import importlib +import os +import sys + +__version__ = "0.1" +__all__ = ["runfastcgi"] + +FASTCGI_OPTIONS = { + 'protocol': 'fcgi', + 'host': None, + 'port': None, + 'socket': None, + 'method': 'fork', + 'daemonize': None, + 'workdir': '/', + 'pidfile': None, + 'maxspare': 5, + 'minspare': 2, + 'maxchildren': 50, + 'maxrequests': 0, + 'debug': None, + 'outlog': None, + 'errlog': None, + 'umask': None, +} + +FASTCGI_HELP = r""" + Run this project as a fastcgi (or some other protocol supported + by flup) application. To do this, the flup package from + http://www.saddi.com/software/flup/ is required. + + runfcgi [options] [fcgi settings] + +Optional Fcgi settings: (setting=value) + protocol=PROTOCOL fcgi, scgi, ajp, ... (default %(protocol)s) + host=HOSTNAME hostname to listen on. + port=PORTNUM port to listen on. + socket=FILE UNIX socket to listen on. + method=IMPL prefork or threaded (default %(method)s). + maxrequests=NUMBER number of requests a child handles before it is + killed and a new child is forked (0 = no limit). + maxspare=NUMBER max number of spare processes / threads (default %(maxspare)s). + minspare=NUMBER min number of spare processes / threads (default %(minspare)s). + maxchildren=NUMBER hard limit number of processes / threads (default %(maxchildren)s). + daemonize=BOOL whether to detach from terminal. + pidfile=FILE write the spawned process-id to this file. + workdir=DIRECTORY change to this directory when daemonizing (default %(workdir)s). + debug=BOOL set to true to enable flup tracebacks. + outlog=FILE write stdout to this file. + errlog=FILE write stderr to this file. + umask=UMASK umask to use when daemonizing, in octal notation (default 022). + +Examples: + Run a "standard" fastcgi process on a file-descriptor + (for Web servers which spawn your processes for you) + $ manage.py runfcgi method=threaded + + Run a scgi server on a TCP host/port + $ manage.py runfcgi protocol=scgi method=prefork host=127.0.0.1 port=8025 + + Run a fastcgi server on a UNIX domain socket (posix platforms only) + $ manage.py runfcgi method=prefork socket=/tmp/fcgi.sock + + Run a fastCGI as a daemon and write the spawned PID in a file + $ manage.py runfcgi socket=/tmp/fcgi.sock method=prefork \ + daemonize=true pidfile=/var/run/django-fcgi.pid + +""" % FASTCGI_OPTIONS + + +def fastcgi_help(message=None): + print(FASTCGI_HELP) + if message: + print(message) + return False + + +def runfastcgi(argset=[], **kwargs): + options = FASTCGI_OPTIONS.copy() + options.update(kwargs) + for x in argset: + if "=" in x: + k, v = x.split('=', 1) + else: + k, v = x, True + options[k.lower()] = v + + if "help" in options: + return fastcgi_help() + + try: + import flup # NOQA + except ImportError as e: + sys.stderr.write("ERROR: %s\n" % e) + sys.stderr.write(" Unable to load the flup package. In order to run django\n") + sys.stderr.write(" as a FastCGI application, you will need to get flup from\n") + sys.stderr.write(" http://www.saddi.com/software/flup/ If you've already\n") + sys.stderr.write(" installed flup, then make sure you have it in your PYTHONPATH.\n") + return False + + flup_module = 'server.' + options['protocol'] + + if options['method'] in ('prefork', 'fork'): + wsgi_opts = { + 'maxSpare': int(options["maxspare"]), + 'minSpare': int(options["minspare"]), + 'maxChildren': int(options["maxchildren"]), + 'maxRequests': int(options["maxrequests"]), + } + flup_module += '_fork' + elif options['method'] in ('thread', 'threaded'): + wsgi_opts = { + 'maxSpare': int(options["maxspare"]), + 'minSpare': int(options["minspare"]), + 'maxThreads': int(options["maxchildren"]), + } + else: + return fastcgi_help("ERROR: Implementation must be one of prefork or " + "thread.") + + wsgi_opts['debug'] = options['debug'] is not None + + try: + module = importlib.import_module('.%s' % flup_module, 'flup') + WSGIServer = module.WSGIServer + except Exception: + print("Can't import flup." + flup_module) + return False + + # Prep up and go + from django.core.servers.basehttp import get_internal_wsgi_application + + if options["host"] and options["port"] and not options["socket"]: + wsgi_opts['bindAddress'] = (options["host"], int(options["port"])) + elif options["socket"] and not options["host"] and not options["port"]: + wsgi_opts['bindAddress'] = options["socket"] + elif not options["socket"] and not options["host"] and not options["port"]: + wsgi_opts['bindAddress'] = None + else: + return fastcgi_help("Invalid combination of host, port, socket.") + + if options["daemonize"] is None: + # Default to daemonizing if we're running on a socket/named pipe. + daemonize = (wsgi_opts['bindAddress'] is not None) + else: + if options["daemonize"].lower() in ('true', 'yes', 't'): + daemonize = True + elif options["daemonize"].lower() in ('false', 'no', 'f'): + daemonize = False + else: + return fastcgi_help("ERROR: Invalid option for daemonize " + "parameter.") + + daemon_kwargs = {} + if options['outlog']: + daemon_kwargs['out_log'] = options['outlog'] + if options['errlog']: + daemon_kwargs['err_log'] = options['errlog'] + if options['umask']: + daemon_kwargs['umask'] = int(options['umask'], 8) + + if daemonize: + from django.utils.daemonize import become_daemon + become_daemon(our_home_dir=options["workdir"], **daemon_kwargs) + + if options["pidfile"]: + with open(options["pidfile"], "w") as fp: + fp.write("%d\n" % os.getpid()) + + WSGIServer(get_internal_wsgi_application(), **wsgi_opts).run() + +if __name__ == '__main__': + runfastcgi(sys.argv[1:]) diff --git a/django/utils/daemonize.py b/django/utils/daemonize.py new file mode 100644 index 0000000..76f4d5d --- /dev/null +++ b/django/utils/daemonize.py @@ -0,0 +1,62 @@ +import os +import sys + +from . import six + +buffering = int(six.PY3) # No unbuffered text I/O on Python 3 (#20815). + +if os.name == 'posix': + def become_daemon(our_home_dir='.', out_log='/dev/null', + err_log='/dev/null', umask=0o022): + "Robustly turn into a UNIX daemon, running in our_home_dir." + # First fork + try: + if os.fork() > 0: + sys.exit(0) # kill off parent + except OSError as e: + sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror)) + sys.exit(1) + os.setsid() + os.chdir(our_home_dir) + os.umask(umask) + + # Second fork + try: + if os.fork() > 0: + os._exit(0) + except OSError as e: + sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror)) + os._exit(1) + + si = open('/dev/null', 'r') + so = open(out_log, 'a+', buffering) + se = open(err_log, 'a+', buffering) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + # Set custom file descriptors so that they get proper buffering. + sys.stdout, sys.stderr = so, se +else: + def become_daemon(our_home_dir='.', out_log=None, err_log=None, umask=0o022): + """ + If we're not running under a POSIX system, just simulate the daemon + mode by doing redirections and directory changing. + """ + os.chdir(our_home_dir) + os.umask(umask) + sys.stdin.close() + sys.stdout.close() + sys.stderr.close() + if err_log: + sys.stderr = open(err_log, 'a', buffering) + else: + sys.stderr = NullDevice() + if out_log: + sys.stdout = open(out_log, 'a', buffering) + else: + sys.stdout = NullDevice() + + class NullDevice: + "A writeable object that writes to nowhere -- like /dev/null." + def write(self, s): + pass