【问题标题】:How to install Django on Hostgator?如何在 Hostgator 上安装 Django?
【发布时间】:2021-10-01 05:50:03
【问题描述】:

我在 Hostgator 上读到可以在他们的托管服务上安装 Django,我已经联系了实时支持并回复说他们无法提供帮助。

有人已经做过了吗?

【问题讨论】:

    标签: django hosting


    【解决方案1】:

    可以在 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。
      • 不要担心消除 docs 和 tests 子文件夹的冲突,因为无论如何这些都需要排除在 re-FastCGI-ification 补丁之外。
      • 一旦安装了 HostGator 中安装的 Django 版本的补丁文件,使用 git apply 将 FastCGI 支持重新注入位于虚拟环境中的 Django 代码中 ./mydjango/lib/python2.7/site-packages/django
      • 最后是我最终得到的 Django 版本 1.10.1 的补丁文件。
    • 使用 PyMySQL 而不是标准的 mysql 库。 PyMySQL 是一个纯 python mysql 客户端,因为 Host Gator 不提供 gcc。
      • 安装库:pip install PyMySQL
      • Monkey 在 manage.py 和 index.fcgi 中通过在 #!蟒蛇行:
    #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
    

    【讨论】:

      【解决方案2】:

      基本步骤是您需要拥有 VPS 托管 http://www.hostgator.com/vps-hosting,除非他们已经为您完成,否则您将无法在其正常托管平台上安装 Django。

      设置好 VPS 后,您将拥有 SSH 凭据以登录 Linux 主机。 (您应该在 Windows 上为此使用 PuTTY)。将 SSH 连接到服务器后,您可以按照 Django 教程 (https://docs.djangoproject.com/en/1.8/intro/install/) 中的说明安装 Django。 (以及它的依赖项)

      可以在 Windows 上开发 Django 应用程序,但比在 linux 主机上开发更困难。这是一个意见。

      【讨论】:

      • 自 21 年 9 月 30 日起,您不需要任何特定帐户来在 Hostgator 上托管 Django,但作为第一个答案的详细信息,您确实需要应用补丁,并从 Hostgator 明确地自行管理该站点不为将 Django 安装到 CGI 提供支持或帮助。至于在 deciated/VPS 平台上,我并没有反驳你的回答,因为我只是说可以在他们的基本计划中托管 Django,但这可能会很棘手。
      猜你喜欢
      • 1970-01-01
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 2019-05-16
      • 1970-01-01
      相关资源
      最近更新 更多