首页 > 解决方案 > 无法再次在 Django 应用程序中正确提供静态文件

问题描述

几周前,我尝试在 google cloud VM(Ubuntu 16.04)中安装 django 应用程序。正如我在这篇文章中所描述的,我在 Django 应用程序中正确地提供静态文件时遇到了问题。由于某种原因,静态文件的 url 没有正确构建。我已通过修改我的 base.html 模板(加载所有 js 和 css)并使用 {% static %} 而不是 STATIC_URL 方法来解决此问题,如此处所述

昨天我尝试在另一个 frest VM 中再次重新安装该应用程序,但由于某种原因无法按预期工作。尽管我进行了上述更改,但我开始遇到与以前相同的错误:

在此处输入图像描述

URL 中似乎缺少“静态”字符串。例如:而不是将js作为:

myIP/static/lib/css/assets.min.css

它为他们服务:

myIP/lib/css/assets.min.css

我不确定为什么会发生这种情况,因为我在 local_settings.py 文件中定义了 STATIC_URL。在我的 settings.py 文件中,我将目录的路径设置为:

MEDIA_ROOT = '/var/www/geonode/uploaded'
STATIC_ROOT = '/var/www/geonode/static/'
STATIC_URL = '/static/'

  TEMPLATE_DIRS = (
    '/etc/geonode/templates',
    os.path.join(GEONODE_ROOT, 'templates'),
  )
  # Additional directories which hold static files
  STATICFILES_DIRS = [
    '/etc/geonode/media',
    os.path.join(GEONODE_ROOT, 'static'),
  ]

我的 base.html 文件如下所示(DEBUG_STATIC 设置为 False):

     {% load i18n avatar_tags %}
    {% load account socialaccount %}
    {% load static from staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <meta Http-Equiv="Cache-Control" Content="no-cache">
        <meta Http-Equiv="Pragma" Content="no-cache">
        <meta Http-Equiv="Expires" Content="0">
        <meta Http-Equiv="Pragma-directive: no-cache">
        <meta Http-Equiv="Cache-directive: no-cache">

        <title>{% block title %}{{ SITE_NAME }}{% endblock %}</title>
        {% block head %}
          {% if DEBUG_STATIC %}
              <link href="{{ STATIC_URL }}lib/css/jquery.dataTables.css?v={{ VERSION }}" rel="stylesheet" />
              <link href="{{ STATIC_URL }}lib/css/select2.css?v={{ VERSION }}" rel="stylesheet"/>
              <link href="{{ STATIC_URL }}lib/css/bootstrap.min.css?v={{ VERSION }}" rel="stylesheet"/>
              <link href="{{ STATIC_URL }}lib/css/jquery-ui.css?v={{ VERSION }}" rel="stylesheet"/>
          {% else %}
            <link href="{% static "lib/css/assets.min.css" %}?v={{ VERSION }}" rel="stylesheet"/>
          {% endif %}

          <link href="{% static "geonode/css/ext-compatibility.css" %}?v={{ VERSION }}" rel="stylesheet" />
          <link href="{% static "geonode/css/ux-all.css" %}?v={{ VERSION }}" rel="stylesheet" />
          <link href="{% static "geonode/css/base.css" %}?v={{ VERSION }}" rel="stylesheet" />
          <style type="text/css">[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}</style>

          {% block extra_head %}
          {% endblock %}
        {% endblock %}
        <!--[if IE]>
          <script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>
          <style>
            #ieflag{
                display: block !important;
                height: 150px;


        text-align: center;
            }
          </style>
        <![endif]-->
        <link rel="search" type="application/opensearchdescription+xml" href="/catalogue/opensearch" title="GeoNode Search"/>
      </head>

      <body class="{% block body_class %}{% endblock %}">
        <!-- Navbar -->
        {% block header %}
            <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
              <div class="container">
            <div class="navbar-header">
                  <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    <i class="fa fa-navicon fa-lg"></i>
                  </button>
                  <a class="navbar-brand" href="{% url "home" %}">GeoNode</a>
                </div>
                <div id="navbar" class="navbar-collapse collapse">
                  <ul class="nav navbar-nav toolbar">
                    {% block tabs %}
                    <li id="nav_layers">
                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Data" %}<i class="fa fa-angle-down fa-lg"></i></a>
                  <ul class="dropdown-menu">
                    <li><a href="{% url "layer_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Layers" %}</a></li>
                    <li><a href="{% url "document_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Documents" %}</a></li>
                    {% if user.is_authenticated %}
                    <li><a href="{% url "services" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Remote Services" %}</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="{% url "layer_upload" %}">Upload Layer</a></li>
                    {% if 'geonode.contrib.createlayer' in INSTALLED_APPS %}
                      <li><a href="{% url "layer_create" %}">{% trans "Create Layer" %}</a></li>
                    {% endif %}
                    <li><a href="{% url "document_upload" %}">Upload Document</a></li>
                    <li><a href="{% url "register_service" %}">{% trans "Add Remote Service" %}</a></li>
                    {% endif %}
                    </ul>
            </li>
                <li id="nav_maps">
              {% if user.is_authenticated %}
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Maps" %}<i class="fa fa-angle-down fa-lg"></i></a>
              <ul class="dropdown-menu">
                <li><a href="{% url "maps_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Explore Maps" %}</a></li>
                <li> <a href="{% url "new_map" %}">{% trans "Create Map" %}</a></li>
              </ul>
              {% else %}
              <a href="{% url "maps_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Maps" %}</a>
              {% endif %}


</li>
        <li>
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "About" %}<i class="fa fa-angle-down fa-lg"></i></a>
          <ul class="dropdown-menu">
            <li><a href="{% url "profile_browse" %}">{% trans "People" %}</a></li>
            <li><a href="{% url "group_list" %}">{% trans "Groups" %}</a></li>
            <li><a href="{% url "group_category_list" %}">{% trans "Group Categories" %}</a></li>
            {% if perms.announcements.can_manage %}
            <li><a href="{% url "announcements_list" %}">{% trans "Announcements" %}</a></li>
            {% endif %}
            <li role="separator" class="divider"></li>
            <li><a href="{% url "geonode.invitations:geonode-send-invite" %}">{% trans "Invite Users" %}</a></li>
            {% if user.is_superuser %}
            <li><a href="/admin/people/profile/add/">{% trans "Add User" %}</a></li>
            <li><a href="{% url "group_create" %}">{% trans "Create Group" %}</a></li>
            {% endif %}
          </ul>
        </li>

        {% block extra_tab %}
        {% endblock %}
        {% endblock %}
      </ul>
          <ul class="nav navbar-nav navbar-right">
        <li>
          <div class="search">
<form id="search" action="{% url "search" %}" >
                  <span class="fa fa-search"></span>
                  {% if HAYSTACK_SEARCH %}
                  <input id="search_input" type="text" placeholder="Search" name="q">
                  {% else %}
                  <input id="search_input" type="text" placeholder="Search" name="title__icontains">
                  {% endif %}
                </form>
              </div>
                </li>
            {% if not user.is_authenticated and ACCOUNT_OPEN_SIGNUP %}
            <li><a href="{% url "account_signup" %}">{% trans "Register" %}</a></li>
            {% endif %}
            {% if user.is_authenticated %}
            <li>
              <a href="#" class="dropdown-toggle avatar" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
                {% autoescape off %}{% avatar user 42 %}{% endautoescape %}
                {% with full_name=user.first_name|add:' '|add:user.last_name %}
                  {% if full_name.strip %}
                    {{ full_name | truncatechars:20 }}
                  {% else %}
                    {{ user.username | truncatechars:20 }}
                  {% endif %}
                {% endwith %}
                <i class="fa fa-angle-down fa-lg"></i>
              </a>
              <ul class="dropdown-menu">
                <li><a href="{{ user.get_absolute_url }}">{% trans "Profile" %}</a></li>
                <li><a href="{% url "recent-activity" %}">{% trans "Recent Activity" %}</a></li>
                <li><a href="{% url "messages_inbox" %}">{% trans "Inbox" %}</a></li>
                <li role="separator" class="divider"></li>
                <li><a href="{% url "admin:index" %}">Admin</a></li>
                {% if 'geonode.geoserver' in INSTALLED_APPS %}
                <li><a href="{% url "proxy" %}?url={{ GEOSERVER_LOCAL_URL }}web">GeoServer</a></li>
                {% endif %}
                {% if user.is_superuser and USE_MONITORING %}
                <li role="separator" class="divider"></li>
                <li><a href="{% url "monitoring:index" %}">{% trans "Monitoring" %}</a></li>
                {% endif %}
                <li role="separator" class="divider"></li>
                <li><a href="{% url "help" %}">{% trans "Help" %}</a></li>
                <li role="separator" class="divider"></li>
                <li><a href="/account/logout/">Logout</a></li>
                </ul>
                </li>
                      {% else %}
                      <li><a href="#" data-toggle="modal" data-target="#SigninModal" role="button" >{% trans "Sign in" %} </a></li>
              {% endif %}
            </ul>
          </div> <!--/.nav-collapse -->
        </div>
      </nav>
      {% endblock header %}
      <!-- End of Navbar -->

    <div class="alert alert-danger alert-dismissible" role="alert" id="ieflag" style="display:none">
      <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <h1>You are using an outdated browser that is not supported by GeoNode.</h1>
      <p>Please use a <strong>modern browser</strong> like Mozilla Firefox, Google Chrome or Safari.</p>
    </div>

  <div id="wrap">
    {% block middle %}
    <div class="container">
      {% include "_status_message.html" %}
      {% include "_announcements.html" %}
      {% include "_messages.html" %}
      {% block body_outer %}
      <div class="row">
        <div class="col-md-8">
        {% block body %}{% endblock %}
        </div>
        <div class="col-md-4">
        {% block sidebar %}{% endblock %}
        </div>
      </div>
      {% endblock %}
    </div>
    {% endblock middle %}
  </div>

  {% block monitoring %}
  {% endblock %}

  {% block footer %}
<footer>
    <div class="container">
      <div class="row">
        <div class="col-md-2">
          <ul class="list-unstyled">
            <li>Data</li>
            <li><a href="{% url "layer_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Layers" %}</a></li>
            <li><a href="{% url "document_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Documents" %}</a></li>
            {% if user.is_authenticated %}
            <li><a href="{% url "services" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Remote Services" %}</a></li>
            <li><a href="{% url "layer_upload" %}">Upload Layer</a></li>
            {% if 'geonode.contrib.createlayer' in INSTALLED_APPS %}
              <li><a href="{% url "layer_create" %}">{% trans "Create Layer" %}</a></li>
            {% endif %}
            <li><a href="{% url "document_upload" %}">Upload Document</a></li>
            <li><a href="{% url "register_service" %}">{% trans "Add Remote Service" %}</a></li>
            {% endif %}
          </ul>
        </div>
        <div class="col-md-2">
          <ul class="list-unstyled">
            <li>Maps</li>
            <li><a href="{% url "maps_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}">{% trans "Explore Maps" %}</a></li>
            {% if user.is_authenticated %}
            <li> <a href="{% url "new_map" %}">{% trans "Create Map" %}</a></li>
            {% endif %}
          </ul>
        </div>
                <div class="col-md-2">
          <ul class="list-unstyled">
            <li>About</li>
            <li><a href="{% url "profile_browse" %}">{% trans "People" %}</a></li>
            <li><a href="{% url "group_list" %}">{% trans "Groups" %}</a></li>
            {% if perms.announcements.can_manage %}
            <li><a href="{% url "announcements_list" %}">{% trans "Announcements" %}</a></li>
            {% endif %}
            <li><a href="{% url "geonode.invitations:geonode-send-invite" %}">{% trans "Invite Users" %}</a></li>
            {% if user.is_superuser %}
<li><a href="/admin/people/profile/add/">{% trans "Add User" %}</a></li>
            <li><a href="{% url "group_create" %}">{% trans "Create Group" %}</a></li>
            {% endif %}
          </ul>
        </div>
        <div class="col-md-6 text-right">
          <ul class="list-unstyled">
            <li>{% trans "Powered by" %} <a href="http://geonode.org">{% trans "GeoNode" %}</a> <em>{% trans "version" %} {{ VERSION }}</em></li>
            <li><a href="{% url "developer" %}">{% trans "Developers" %}</a> | <a href="{% url "about" %}">{% trans "About" %}</a><li>
          </ul>
          <label class="hidden">{% trans "Language" %}</label>
          {% if csrf_token != "NOTPROVIDED" %}
          {% get_current_language as LANGUAGE %}
          <form class="form-inline" action="/i18n/setlang/" method="post">
          {% csrf_token %}
            <select class="col-md-6 pull-right" name="language" onchange="javascript:form.submit()">
              {% for lang in LANGUAGES %}
              <option value="{{ lang.0 }}" {% ifequal LANGUAGE_CODE lang.0 %} selected="selected"{% endifequal %}>
                {{ lang.1 }}
              </option>
              {% endfor %}
            </select>
          </form>
          {% endif %}
        </div>
      </div>
    </div>
  </footer>
  {% endblock footer %}


        <!-- Modal must stay outside the navbar -->
        {% if not user.is_authenticated %}
        <div class="modal fade" id="SigninModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
          <div class="modal-dialog modal-sm">
     <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                <h4 class="modal-title" id="myModalLabel">{% trans "Sign in" %}</h4>
              </div>
              <form class="form-signin" role="form" action="{% url "account_login" %}?next={{ request.path }}" method="post">
                <div class="modal-body">
                  {% csrf_token %}
                  {% get_providers as socialaccount_providers %}
                  {% if socialaccount_providers %}
                      {% include "socialaccount/snippets/provider_list.html" with process="login" %}
                      {% include "socialaccount/snippets/login_extra.html" %}
                    <hr>
                  {% endif %}
                  <div class="form-group">
                    <label for="id_username" class="sr-only">{% trans "Username" %}:</label>
                    <input id="id_username" class="form-control" name="login" placeholder="{% trans "Username" %}" type="text" />
                  </div>
                  <div class="form-group">
                    <label for="id_password" class="sr-only">{% trans "Password" %}:</label>
                    <input id="id_password" class="form-control" name="password" placeholder="{% trans "Password" %}" type="password" />
                  </div>
                  <label class="checkbox">
                    <input type="checkbox" /> {% trans "Remember Me" %}
                  </label>
                </div>
                <div class="modal-footer">
                  <button type="submit" class="btn btn-primary btn-block">{% trans "Sign in" %}</button>
                </div>
              </form>
            </div>
          </div>
        </div>
        {% endif %}
        <!-- End of Modal -->
        {% if DEBUG_STATIC %}
        <script src="{{ STATIC_URL }}lib/js/jquery.min.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery.dataTables.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery.timeago.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery.ajaxprogress.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery.ajaxQueue.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery-ui.custom.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/jquery.raty.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/bootstrap.min.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/moment-with-locales.min.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/bootstrap-datetimepicker.min.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/json2.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/select2.js?v={{ VERSION }}"></script>
        <script src="{{ STATIC_URL }}lib/js/waypoints.js?v={{ VERSION }}"></script>
        {% else %}
        <script src="{% static "lib/js/assets.min.js" %}?v={{ VERSION }}"></script>
        {% endif %}
        <script src="{% static "geonode/js/utils/utils.js" %}?v={{ VERSION }}"></script>
        <script src="{% static "geonode/js/base/base.js" %}?v={{ VERSION }}"></script>
        {% include 'autocomplete_light/static.html' %}
        <script type="text/javascript" src="{% url "javascript-catalog" %}"></script>
        {% block extra_script %}{% endblock extra_script %}
        <script type="text/javascript">
            var autocomplete = $('#search_input').yourlabsAutocomplete({
                url: '{% url "autocomplete_light_autocomplete" "ResourceBaseAutocomplete" %}',
                choiceSelector: 'span',
                hideAfter: 200,
                minimumCharacters: 1,
                placeholder: '{% trans 'Type your search here ...' %}',
                appendAutocomplete: $('#search_input'),
                autoHilightFirst: false
            });
            $('#search_input').bind('selectChoice', function(e, choice, autocomplete) {
                if(choice[0].children[0] == undefined) {
                    $('#search_input').val($(choice[0]).text());
                    $('#search').submit();
                }
            });
        </script>
        <script>
            // Workaround to fix the autocomplete box positions
            yourlabs.Autocomplete.prototype.fixPosition = function(html) {
                this.input.parents().filter(function() {
                    return $(this).css('overflow') === 'hidden';
                }).first().css('overflow', 'visible');
                if(this.input.attr('name') !== 'resource-keywords'){
                  this.box.insertAfter(this.input).css({top: 28, left: 0});
                }else{ ...

编辑

我的 apache 虚拟主机如下所示:

WSGIDaemonProcess geonode user=www-data threads=15 processes=2
<VirtualHost *:80>
    Servername localhost
    ServerAdmin webmaster@localhost
    LimitRequestFieldSize 32760
    LimitRequestLine 32760
    ErrorLog /var/log/apache2/error.log
    LogLevel warn
    CustomLog /var/log/apache2/access.log combined
    WSGIProcessGroup geonode
    WSGIPassAuthorization On
    WSGIScriptAlias / /var/www/geonode/wsgi/geonode.wsgi
    <Directory "/var/www/geonode/">
       Order allow,deny
       Options -Indexes
       Allow from all
    </Directory>
    Alias /static/ /var/www/geonode/static/
    Alias /uploaded/ /var/www/geonode/uploaded/
    Alias /robots.txt /var/www/geonode/robots.txt
    <Directory "/var/www/geonode/uploaded/documents/">
       Order allow,deny
       Deny from all
    </Directory>
    <Directory "/var/www/geonode/uploaded/layers/">
       Order allow,deny
       Deny from all
    </Directory>

 <Directory "/var/www/geonode/static_root/">
        Order allow,deny
        Options Indexes FollowSymLinks
        Allow from all
        Require all granted
        IndexOptions FancyIndexing
    </Directory>

    <Directory "/var/www/geonode/uploaded/thumbs/">
        Order allow,deny
        Options Indexes FollowSymLinks
        Allow from all
        Require all granted
        IndexOptions FancyIndexing
    </Directory>

    <Directory "/var/www/geonode/uploaded/avatars/">
        Order allow,deny
        Options Indexes FollowSymLinks
        Allow from all
        Require all granted
        IndexOptions FancyIndexing
    </Directory>

    <Directory "/var/www/geonode/uploaded/people_group/">
        Order allow,deny
        Options Indexes FollowSymLinks
        Allow from all
        Require all granted
        IndexOptions FancyIndexing
    </Directory>

    <Directory "/var/www/geonode/uploaded/group/">
        Order allow,deny
        Options Indexes FollowSymLinks
        Allow from all
        Require all granted
        IndexOptions FancyIndexing
    </Directory>

<Proxy *>
      Order allow,deny
      Allow from all
    </Proxy>

    ProxyPreserveHost On
    ProxyPass /geoserver http://localhost:8080/geoserver
    ProxyPassReverse /geoserver http://localhost:8080/geoserver
</VirtualHost>

标签: djangopython-2.7django-staticfiles

解决方案


推荐阅读