Commits

Hynek Cernoch committed e5831e0

Fixed staticfiles support for Django 1.3+. Closes #1331, #1347. part A) code

Comments (0)

Files changed (6)

docs/requirements.txt

 Django instance to use Satchmo.  The `Django installation guide`_ will step you
 through the process.
 
-You must use Django 1.2.3 or greater in order to use the latest CSRF features.
-Series 1.3.x is currently recommended.
+You must use Django 1.2.3 or greater. Series 1.3.x is currently recommended.
+At final Satchmo 0.9.3 may be required Django 1.3.x or 1.4.
 
-Satchmo requires Python 2.4 or later and a database supported by Django.
+Satchmo requires Python 2.5 or later and a database supported by Django.
 
 There is always a challenge in deciding how many dependencies to include in a project. With
 Satchmo, we strongly believe in avoiding "Not Invented Here" syndrome and using the power

satchmo/apps/satchmo_store/shop/config.py

 # -*- coding: utf-8 -*-
 
 import os
+import sys
 import urlparse
 from decimal import Decimal
 from django.conf import settings
 
 SHOP_GROUP = ConfigurationGroup('SHOP', _('Satchmo Shop Settings'), ordering=0)
 
+project_root = os.path.dirname(os.path.normpath(sys.modules[os.environ['DJANGO_SETTINGS_MODULE']].__file__))
+# default value `project_root + 'static'` is currently the best common for all Django 1.2 - 1.4
 default_icon_url = urlparse.urlunsplit(
     ('file',
      '',
-     os.path.join(settings.MEDIA_ROOT, 'images/sample-logo.bmp'),
+     os.path.join(project_root, 'static', 'images/sample-logo.bmp'),
      '',
      '')
     )

satchmo/apps/satchmo_store/shop/context_processors.py

 from satchmo_store.shop import get_satchmo_setting
 from satchmo_store.shop.models import Config, Cart
 from satchmo_store.shop.signals import satchmo_context
-from satchmo_utils import current_media_url, request_is_secure
+from satchmo_utils import current_media_url, current_static_url, request_is_secure
 import logging
 
 log = logging.getLogger('shop_context')
         'shop' : shop_config,
         'shop_name': shop_config.store_name,
         'media_url': current_media_url(request),
+        'STATIC_URL': current_static_url(request),
         'cart_count': cart.numItems,
         'cart': cart,
         'categories': all_categories,

satchmo/apps/satchmo_store/shop/templatetags/satchmo_util.py

 register.filter('as_json', as_json)
 
 def blackbird_logging(context):
-    form = context.get('form', None)
     return {
         'debug' : settings.DEBUG,
-        'media_url' : settings.MEDIA_URL,
-        'form' : form,
+        'form': context.get('form', None), 
+        'STATIC_URL': context.get('STATIC_URL', None),
         }
 
 register.inclusion_tag('shop/_blackbird_logging.html', takes_context=True)(blackbird_logging)
     else:
         url = ""
 
-    media_url = context.get('media_url', None)
     return {
         'enabled' : enabled,
         'set_language_url' : url,
         'languages' : languages,
-        'media_url' : media_url,
+        'STATIC_URL': context.get('STATIC_URL', ''),  # for easy flag images
         'django_language' : request.session.get('django_language', 'en'),
     }
 register.inclusion_tag("l10n/_language_selection_form.html", takes_context=True)(satchmo_language_selection_form)

satchmo/apps/satchmo_store/urls/default.py

 from django.conf import settings
-from django.conf.urls.defaults import patterns, include
+from django.conf.urls.defaults import patterns, include, url
 from django.contrib import admin
 import logging
+import re
+
+try:
+    import django.contrib.staticfiles
+    view = 'django.contrib.staticfiles.views.serve'
+except ImportError:
+    view = 'django.views.static.serve'   # for Django 1.2
+
 log = logging.getLogger('satchmo_store.urls')
 
 # discover all admin modules - if you override this for your
 else:
     urlpatterns = adminpatterns
 
-#The following is used to serve up local media files like images
-if getattr(settings, 'LOCAL_DEV', False):
-    log.debug("Adding local serving of static files at: %s", settings.MEDIA_ROOT)
-    baseurlregex = r'^static/(?P<path>.*)$'
+#The following is used to serve up local media files like product images
+prefix = settings.MEDIA_URL
+if getattr(settings, 'LOCAL_DEV', False) and prefix and not '://' in prefix:
+    log.debug("Adding local serving of media files '%s' at: %s", prefix, \
+            settings.MEDIA_ROOT)
     urlpatterns += patterns('',
-        (baseurlregex, 'django.views.static.serve',
+        # usually r'^media/(?P<path>.*)$'
+        url(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view,
         {'document_root':  settings.MEDIA_ROOT}),
-
-        (r'^site_media/(.*)$', 'django.views.static.serve',
-        {'document_root': settings.MEDIA_ROOT}),
     )
 
-
+# Removed prefix '^site_media/' because it is very old, unused, duplicated,
+# undocumented and a replacement is easy.

satchmo/apps/satchmo_utils/__init__.py

 from django.conf import settings
 import datetime
+import django
 import logging
 import os
 import random
 import sys
 import types
+import warnings
 
 log = logging.getLogger('shop.utils')
 
             media_url = media_url.replace('http://','https://')
     return media_url
 
+def current_static_url(request):
+    """Return the static_url, taking into account SSL."""
+    static_url = getattr(settings, 'STATIC_URL', None)
+    if not static_url:
+        if django.VERSION >= (1, 3):
+            warnings.warn("Undefined settings.STATIC_URL. This is a problem. Read docs.")
+        else:
+            warnings.warn("Undefined settings.STATIC_URL. It has been replaced by '%s'. "
+                    "It is normal for Django 1.2 in order to work with newer packages."
+                                % settings.MEDIA_URL, PendingDeprecationWarning)
+            static_url = settings.MEDIA_URL
+    secure = request_is_secure(request)
+    if secure:
+        try:
+            static_url = settings.STATIC_SECURE_URL
+        except AttributeError:
+            static_url = static_url.replace('http://','https://')
+    return static_url
+
 def is_scalar(maybe):
     """Test to see value is a string, an int, or some other scalar type"""
     return is_string_like(maybe) or not can_loop_over(maybe)