diff options
author | Adolfo Fitoria <adolfo.fitoria@gmail.com> | 2012-01-16 16:14:08 -0300 |
---|---|---|
committer | Adolfo Fitoria <adolfo.fitoria@gmail.com> | 2012-01-16 16:14:08 -0300 |
commit | 6ce8aed0c928e31974058c7acc48c41b9a65c234 (patch) | |
tree | 3748211b37d4d7b6c82d8ce970b1e6925c72c523 | |
parent | 417ddb4822fa8315e7f413b08f993098bf4824c1 (diff) | |
parent | 3035bd461f02ff238ddcede43ccea428fd03c20c (diff) | |
download | askbot-6ce8aed0c928e31974058c7acc48c41b9a65c234.tar.gz askbot-6ce8aed0c928e31974058c7acc48c41b9a65c234.tar.bz2 askbot-6ce8aed0c928e31974058c7acc48c41b9a65c234.zip |
Merge branch 'master' of github.com:ASKBOT/askbot-devel
-rwxr-xr-x | .gitignore | 2 | ||||
-rw-r--r-- | askbot/context.py | 3 | ||||
-rw-r--r-- | askbot/deployment/__init__.py | 7 | ||||
-rw-r--r-- | askbot/deps/django_authopenid/views.py | 5 | ||||
-rw-r--r-- | askbot/doc/source/changelog.rst | 6 | ||||
-rw-r--r-- | askbot/doc/source/deployment.rst | 29 | ||||
-rw-r--r-- | askbot/management/commands/send_email_alerts.py | 27 | ||||
-rw-r--r-- | askbot/middleware/view_log.py | 3 | ||||
-rw-r--r-- | askbot/setup_templates/settings.py | 15 | ||||
-rw-r--r-- | askbot/setup_templates/settings.py.mustache | 16 | ||||
-rw-r--r-- | askbot/skins/common/media/js/utils.js | 2 | ||||
-rw-r--r-- | askbot/skins/common/templates/debug_header.html | 27 | ||||
-rw-r--r-- | askbot/skins/default/templates/base.html | 1 | ||||
-rw-r--r-- | askbot/skins/default/templates/meta/bottom_scripts.html | 1 | ||||
-rw-r--r-- | askbot/skins/utils.py | 9 | ||||
-rw-r--r-- | askbot/startup_procedures.py | 190 | ||||
-rw-r--r--[-rwxr-xr-x] | askbot/tests/images/logo.gif | bin | 910 -> 910 bytes | |||
-rw-r--r-- | askbot/tests/skin_tests.py | 6 | ||||
-rw-r--r-- | askbot/urls.py | 5 | ||||
-rw-r--r-- | askbot/utils/functions.py | 8 | ||||
-rw-r--r-- | askbot/views/meta.py | 11 |
21 files changed, 280 insertions, 93 deletions
@@ -4,6 +4,7 @@ db rebuild-locales.pl /src +/static cache/?? run *.wsgi @@ -14,6 +15,7 @@ settings.py *.iml lint env +/static django django/* nbproject diff --git a/askbot/context.py b/askbot/context.py index 17ab35bd..41298fc1 100644 --- a/askbot/context.py +++ b/askbot/context.py @@ -2,6 +2,7 @@ from the django settings, all parameters from the askbot livesettings and the application available for the templates """ +import sys from django.conf import settings import askbot from askbot import api @@ -15,8 +16,10 @@ def application_settings(request): my_settings = askbot_settings.as_dict() my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE', settings.LANGUAGE_CODE) my_settings['ASKBOT_URL'] = settings.ASKBOT_URL + my_settings['STATIC_URL'] = settings.STATIC_URL my_settings['ASKBOT_CSS_DEVEL'] = getattr(settings, 'ASKBOT_CSS_DEVEL', False) my_settings['DEBUG'] = settings.DEBUG + my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv my_settings['ASKBOT_VERSION'] = askbot.get_version() my_settings['LOGIN_URL'] = url_utils.get_login_url() my_settings['LOGOUT_URL'] = url_utils.get_logout_url() diff --git a/askbot/deployment/__init__.py b/askbot/deployment/__init__.py index 6f7a86f6..8832cd01 100644 --- a/askbot/deployment/__init__.py +++ b/askbot/deployment/__init__.py @@ -3,6 +3,7 @@ module for deploying askbot """ import os.path import sys +import django from optparse import OptionParser from askbot.utils import console from askbot.deployment import messages @@ -126,6 +127,12 @@ def deploy_askbot(directory, options): path_utils.create_path(directory) + if django.VERSION[0] == 1 and django.VERSION[1] < 3: + #force people install the django-staticfiles app + context['staticfiles_app'] = '' + else: + context['staticfiles_app'] = "'django.contrib.staticfiles'," + path_utils.deploy_into( directory, new_project = create_new_project, diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py index e9059c61..5f332a1a 100644 --- a/askbot/deps/django_authopenid/views.py +++ b/askbot/deps/django_authopenid/views.py @@ -48,6 +48,7 @@ from django.utils.safestring import mark_safe from django.core.mail import send_mail from recaptcha_works.decorators import fix_recaptcha_remote_ip from askbot.skins.loaders import render_into_skin, get_template +from urlparse import urlparse from openid.consumer.consumer import Consumer, \ SUCCESS, CANCEL, FAILURE, SETUP_NEEDED @@ -1094,8 +1095,10 @@ def _send_email_key(user): to user's email address """ subject = _("Recover your %(site)s account") % {'site': askbot_settings.APP_SHORT_NAME} + + url = urlparse(askbot_settings.APP_URL) data = { - 'validation_link': askbot_settings.APP_URL + \ + 'validation_link': url.scheme + '://' + url.netloc + \ reverse( 'user_account_recover', kwargs={'key':user.email_key} diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index 7751cba6..b4b810d6 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -1,6 +1,12 @@ Changes in Askbot ================= +Development version (not released yet) +-------------------------------------- +* Made email recovery link work when askbot is deployed on subdirectory (Evgeny) +* Added tests for the CSRF_COOKIE_DOMAIN setting in the startup_procedures (Evgeny) +* Askbot now respects django's staticfiles app (Radim Řehůřek, Evgeny) + 0.7.39 (Jan 11, 2012) --------------------- * restored facebook login after FB changed the procedure (Evgeny) diff --git a/askbot/doc/source/deployment.rst b/askbot/doc/source/deployment.rst index 8baa99c0..1ca7553f 100644 --- a/askbot/doc/source/deployment.rst +++ b/askbot/doc/source/deployment.rst @@ -6,18 +6,30 @@ Deploying Askbot Deploying askbot (assuming that it is already installed) entails: +* collecting static media files * setting correct file access permissions * configuring the webserver to work with your application This document currently explains the configuration under Apache and mod_wsgi_. +Collecting static media files +----------------------------- +Static media must be collected into a single location with a command:: + + python manage.py collectstatic + +There are several options on where to put the static files - the simplest is +a local directory, but it is also possible to use a dedicated static files +storage or a CDN, for more information see django documentation about +serving static files. + Setting up file access permissions ---------------------------------- Webserver process must be able to write to the following locations within your project:: - log/ - askbot/upfiles + log/ + askbot/upfiles If you know user name or the group name under which the webserver runs, you can make those directories writable by setting the permissons @@ -26,11 +38,11 @@ accordingly: For example, if you are using Linux installation of apache webserver running under group name 'apache' you could do the following:: - cd /path/to/django-project - cd .. #go one level up - chown -R yourlogin:apache django-project - chmod -R g+w django-project/askbot/upfiles - chmod -R g+w django-project/log + cd /path/to/django-project + cd .. #go one level up + chown -R yourlogin:apache django-project + chmod -R g+w django-project/askbot/upfiles + chmod -R g+w django-project/log If your account somehow limits you from running such commands - please consult your system administrator. @@ -71,9 +83,8 @@ Settings below are not perfect but may be a good starting point:: #aliases to serve static media directly #will probably need adjustment - Alias /m/ /usr/local/lib/python2.6/site-packages/askbot/skins/ + Alias /static/ /path/to/django-project/static/ Alias /upfiles/ /path/to/django-project/askbot/upfiles/ - Alias /admin/media/ /usr/local/lib/python2.6/site-packages/django/contrib/admin/media/ <DirectoryMatch "/path/to/django-project/askbot/skins/([^/]+)/media"> Order deny,allow Allow from all diff --git a/askbot/management/commands/send_email_alerts.py b/askbot/management/commands/send_email_alerts.py index c904cdde..46ee555f 100644 --- a/askbot/management/commands/send_email_alerts.py +++ b/askbot/management/commands/send_email_alerts.py @@ -451,33 +451,6 @@ class Command(NoArgsCommand): # 'the askbot and see what\'s new!<br>' # ) - text += _( - 'Please visit the askbot and see what\'s new! ' - 'Could you spread the word about it - ' - 'can somebody you know help answering those questions or ' - 'benefit from posting one?' - ) - - feeds = EmailFeedSetting.objects.filter(subscriber = user) - feed_freq = [feed.frequency for feed in feeds] - text += '<p></p>' - if 'd' in feed_freq: - text += _('Your most frequent subscription setting is \'daily\' ' - 'on selected questions. If you are receiving more than one ' - 'email per day' - 'please tell about this issue to the askbot administrator.' - ) - elif 'w' in feed_freq: - text += _('Your most frequent subscription setting is \'weekly\' ' - 'if you are receiving this email more than once a week ' - 'please report this issue to the askbot administrator.' - ) - text += ' ' - text += _( - 'There is a chance that you may be receiving links seen ' - 'before - due to a technicality that will eventually go away. ' - ) - link = url_prefix + reverse( 'user_subscriptions', kwargs = { diff --git a/askbot/middleware/view_log.py b/askbot/middleware/view_log.py index 0880ae1b..6eea44b8 100644 --- a/askbot/middleware/view_log.py +++ b/askbot/middleware/view_log.py @@ -13,13 +13,12 @@ from askbot.views.readers import questions as questions_view from askbot.views.commands import vote, get_tag_list from askbot.views.writers import delete_comment, post_comments, retag_question from askbot.views.readers import revisions, get_question_body -from askbot.views.meta import media from askbot.search.state_manager import ViewLog #todo: the list is getting bigger and bigger - maybe there is a better way to #trigger reset of sarch state? IGNORED_VIEWS = ( - serve, vote, media, delete_comment, post_comments, + serve, vote, delete_comment, post_comments, retag_question, revisions, javascript_catalog, get_tag_list, get_question_body ) diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py index 27ee77dc..7e285d03 100644 --- a/askbot/setup_templates/settings.py +++ b/askbot/setup_templates/settings.py @@ -3,11 +3,13 @@ import os.path import logging import sys import askbot +import site #this line is added so that we can import pre-packaged askbot dependencies -sys.path.append(os.path.join(os.path.dirname(askbot.__file__), 'deps')) +ASKBOT_ROOT = os.path.abspath(os.path.dirname(askbot.__file__)) +site.addsitedir(os.path.join(ASKBOT_ROOT, 'deps')) -DEBUG = False#set to True to enable debugging +DEBUG = True#set to True to enable debugging TEMPLATE_DEBUG = False#keep false when debugging jinja2 templates INTERNAL_IPS = ('127.0.0.1',) @@ -69,14 +71,16 @@ LANGUAGE_CODE = 'en' # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles') -MEDIA_URL = '/upfiles/' +MEDIA_URL = '/upfiles/'#url to uploaded media +STATIC_URL = '/m/'#url to project static files PROJECT_ROOT = os.path.dirname(__file__) +STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')#path to files collected by collectstatic # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". -ADMIN_MEDIA_PREFIX = '/admin/media/' +ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'#must be this value # Make up some unique string, and don't share it with anybody. SECRET_KEY = 'sdljdfjkldsflsdjkhsjkldgjlsdgfs s ' @@ -150,6 +154,7 @@ INSTALLED_APPS = ( 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', + 'django.contrib.staticfiles', #all of these are needed for the askbot 'django.contrib.admin', @@ -219,3 +224,5 @@ djcelery.setup_loader() CSRF_COOKIE_NAME = 'askbot_csrf' CSRF_COOKIE_DOMAIN = ''#enter domain name here - e.g. example.com + +STATICFILES_DIRS = ( os.path.join(ASKBOT_ROOT, 'skins'),) diff --git a/askbot/setup_templates/settings.py.mustache b/askbot/setup_templates/settings.py.mustache index 4b01b4df..3bca11ba 100644 --- a/askbot/setup_templates/settings.py.mustache +++ b/askbot/setup_templates/settings.py.mustache @@ -3,11 +3,13 @@ import os.path import logging import sys import askbot +import site #this line is added so that we can import pre-packaged askbot dependencies -sys.path.append(os.path.join(os.path.dirname(askbot.__file__), 'deps')) +ASKBOT_ROOT = os.path.abspath(os.path.dirname(askbot.__file__)) +site.addsitedir(os.path.join(ASKBOT_ROOT, 'deps')) -DEBUG = False#set to True to enable debugging +DEBUG = True#set to True to enable debugging TEMPLATE_DEBUG = False#keep false when debugging jinja2 templates INTERNAL_IPS = ('127.0.0.1',) @@ -66,17 +68,19 @@ SITE_ID = 1 USE_I18N = True LANGUAGE_CODE = 'en' -# Absolute path to the directory that holds media. +# Absolute path to the directory that holds uploaded media # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles') MEDIA_URL = '/upfiles/' +STATIC_URL = '/m/'#this must be different from MEDIA_URL PROJECT_ROOT = os.path.dirname(__file__) +STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static') # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". -ADMIN_MEDIA_PREFIX = '/admin/media/' +ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/' # Make up some unique string, and don't share it with anybody. SECRET_KEY = 'sdljdfjkldsflsdjkhsjkldgjlsdgfs s ' @@ -149,6 +153,7 @@ INSTALLED_APPS = ( 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', + {{ staticfiles_app }} #all of these are needed for the askbot 'django.contrib.admin', @@ -219,3 +224,6 @@ DOMAIN_NAME = '{{domain_name}}' CSRF_COOKIE_NAME = '{{domain_name}}_csrf' CSRF_COOKIE_DOMAIN = DOMAIN_NAME + +STATIC_ROOT = os.path.join(PROJECT_ROOT, "static") +STATICFILES_DIRS = (os.path.join(ASKBOT_ROOT, 'skins'),) diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js index 0afd03a7..60ac8d97 100644 --- a/askbot/skins/common/media/js/utils.js +++ b/askbot/skins/common/media/js/utils.js @@ -1,6 +1,6 @@ //var $, scriptUrl, askbotSkin var mediaUrl = function(resource){ - return scriptUrl + 'm/' + askbotSkin + '/' + resource; + return askbot['settings']['static_url'] + askbotSkin + '/' + resource; }; var cleanUrl = function(url){ diff --git a/askbot/skins/common/templates/debug_header.html b/askbot/skins/common/templates/debug_header.html new file mode 100644 index 00000000..e1230265 --- /dev/null +++ b/askbot/skins/common/templates/debug_header.html @@ -0,0 +1,27 @@ +{% if settings.USING_RUNSERVER %} + {% if settings.DEBUG == False %} + <div> + <p> + You are seeing this message because you are using Django runserver + and DEBUG_MODE is False. Runserver should not be used in production. + </p> + <p> + To serve static media in production - please run: + <pre>python manage.py collectstatic</pre> + </p> + <p> + If you do not see page styling - set DEBUG_MODE = True. + </p> + </div> + {% endif %} +{% else %} + {% if settings.DEBUG == True %} + <div> + <p> + Debug mode is on, do not use it in production. + To turn it off, use DEBUG = False in your + settings.py file. + </p> + </div> + {% endif %} +{% endif %} diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html index 8287f5ba..39b89fe8 100644 --- a/askbot/skins/default/templates/base.html +++ b/askbot/skins/default/templates/base.html @@ -16,6 +16,7 @@ {% endspaceless %} <body class="{% block body_class %}{% endblock %}{% if user_messages %} user-messages{% endif %}{% if page_class %} {{page_class}}{% endif %}{% if request.user.is_anonymous() %} anon{% endif %} lang-{{settings.LANGUAGE_CODE}}"> {% include "widgets/system_messages.html" %} + {% include "debug_header.html" %} {% include "custom_header.html" ignore missing %} {% if settings.CUSTOM_HEADER|trim != '' %} <div id="custom-header"> diff --git a/askbot/skins/default/templates/meta/bottom_scripts.html b/askbot/skins/default/templates/meta/bottom_scripts.html index 9a78d8a0..90d20e17 100644 --- a/askbot/skins/default/templates/meta/bottom_scripts.html +++ b/askbot/skins/default/templates/meta/bottom_scripts.html @@ -28,6 +28,7 @@ askbot['urls']['follow_user'] = '/followit/follow/user/{{'{{'}}userId{{'}}'}}/'; askbot['urls']['unfollow_user'] = '/followit/unfollow/user/{{'{{'}}userId{{'}}'}}/'; askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}'; + askbot['settings']['static_url'] = '{{ settings.STATIC_URL }}'; </script> <script type="text/javascript" diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py index 50c0d4fb..520fa2f7 100644 --- a/askbot/skins/utils.py +++ b/askbot/skins/utils.py @@ -154,13 +154,8 @@ def get_media_url(url, ignore_missing = False): logging.critical(log_message) return None - url = use_skin + '/media/' + url - url = '///' + django_settings.ASKBOT_URL + 'm/' + url - url = os.path.normpath(url).replace( - '\\', '/' - ).replace( - '///', '/' - ) + url = django_settings.STATIC_URL + use_skin + '/media/' + url + url = os.path.normpath(url).replace('\\', '/') if resource_revision: url += '?v=%d' % resource_revision diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py index 05426898..f4452e29 100644 --- a/askbot/startup_procedures.py +++ b/askbot/startup_procedures.py @@ -9,22 +9,58 @@ the main function is run_startup_tests """ import sys import os +import re +import askbot from django.db import transaction from django.conf import settings as django_settings from django.core.exceptions import ImproperlyConfigured from askbot.utils.loading import load_module +from askbot.utils.functions import enumerate_string_list +from urlparse import urlparse PREAMBLE = """\n ************************ * * * Askbot self-test * * * -************************""" +************************\n +""" + +FOOTER = """\n +If necessary, type ^C (Ctrl-C) to stop the program. +""" + +class AskbotConfigError(ImproperlyConfigured): + """Prints an error with a preamble and possibly a footer""" + def __init__(self, error_message): + msg = PREAMBLE + error_message + if sys.__stdin__.isatty(): + #print footer only when askbot is run from the shell + msg += FOOTER + super(AskbotConfigError, self).__init__(msg) def askbot_warning(line): """prints a warning with the nice header, but does not quit""" print >> sys.stderr, PREAMBLE + '\n' + line +def print_errors(error_messages, header = None, footer = None): + """if there is one or more error messages, + raise ``class:AskbotConfigError`` with the human readable + contents of the message + * ``header`` - text to show above messages + * ``footer`` - text to show below messages + """ + if len(error_messages) == 0: return + if len(error_messages) > 1: + error_messages = enumerate_string_list(error_messages) + + message = '' + if header: message += header + '\n' + message += 'Please attend to the following:\n\n' + message += '\n\n'.join(error_messages) + if footer: message += '\n\n' + footer + raise AskbotConfigError(message) + def format_as_text_tuple_entries(items): """prints out as entries or tuple containing strings ready for copy-pasting into say django settings file""" @@ -45,21 +81,21 @@ def test_askbot_url(): pass else: msg = 'setting ASKBOT_URL must be of string or unicode type' - raise ImproperlyConfigured(msg) + raise AskbotConfigError(msg) if url == '/': msg = 'value "/" for ASKBOT_URL is invalid. '+ \ 'Please, either make ASKBOT_URL an empty string ' + \ 'or a non-empty path, ending with "/" but not ' + \ 'starting with "/", for example: "forum/"' - raise ImproperlyConfigured(msg) + raise AskbotConfigError(msg) else: try: assert(url.endswith('/')) except AssertionError: msg = 'if ASKBOT_URL setting is not empty, ' + \ 'it must end with /' - raise ImproperlyConfigured(msg) + raise AskbotConfigError(msg) try: assert(not url.startswith('/')) except AssertionError: @@ -69,7 +105,7 @@ def test_askbot_url(): def test_middleware(): """Checks that all required middleware classes are installed in the django settings.py file. If that is not the - case - raises an ImproperlyConfigured exception. + case - raises an AskbotConfigError exception. """ required_middleware = ( 'django.contrib.sessions.middleware.SessionMiddleware', @@ -96,7 +132,7 @@ to the MIDDLEWARE_CLASSES variable in your site settings.py file. The order the middleware records may be important, please take a look at the example in https://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/settings.py:\n\n""" middleware_text = format_as_text_tuple_entries(missing_middleware_set) - raise ImproperlyConfigured(PREAMBLE + error_message + middleware_text) + raise AskbotConfigError(error_message + middleware_text) #middleware that was used in the past an now removed @@ -111,7 +147,7 @@ https://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/settin error_message = """\n\nPlease remove the following middleware entries from the list of MIDDLEWARE_CLASSES in your settings.py - these are not used any more:\n\n""" middleware_text = format_as_text_tuple_entries(remove_middleware_set) - raise ImproperlyConfigured(PREAMBLE + error_message + middleware_text) + raise AskbotConfigError(error_message + middleware_text) def try_import(module_name, pypi_package_name): """tries importing a module and advises to install @@ -124,7 +160,7 @@ def try_import(module_name, pypi_package_name): message += '\n\nTo install all the dependencies at once, type:' message += '\npip install -r askbot_requirements.txt\n' message += '\nType ^C to quit.' - raise ImproperlyConfigured(message) + raise AskbotConfigError(message) def test_modules(): """tests presence of required modules""" @@ -140,7 +176,7 @@ def test_postgres(): import psycopg2 version = psycopg2.__version__.split(' ')[0].split('.') if version == ['2', '4', '2']: - raise ImproperlyConfigured( + raise AskbotConfigError( 'Please install psycopg2 version 2.4.1,\n version 2.4.2 has a bug' ) elif version > ['2', '4', '2']: @@ -170,7 +206,7 @@ def test_template_loader(): loader that used to send a warning""" old_template_loader = 'askbot.skins.loaders.load_template_source' if old_template_loader in django_settings.TEMPLATE_LOADERS: - raise ImproperlyConfigured(PREAMBLE + \ + raise AskbotConfigError( "\nPlease change: \n" "'askbot.skins.loaders.load_template_source', to\n" "'askbot.skins.loaders.filesystem_load_template_source',\n" @@ -188,7 +224,7 @@ def test_celery(): if broker_backend is None: if broker_transport is None: - raise ImproperlyConfigured(PREAMBLE + \ + raise AskbotConfigError( "\nPlease add\n" 'BROKER_TRANSPORT = "djkombu.transport.DatabaseTransport"\n' "or other valid value to your settings.py file" @@ -198,7 +234,7 @@ def test_celery(): return if broker_backend != broker_transport: - raise ImproperlyConfigured(PREAMBLE + \ + raise AskbotConfigError( "\nPlease rename setting BROKER_BACKEND to BROKER_TRANSPORT\n" "in your settings.py file\n" "If you have both in your settings.py - then\n" @@ -206,7 +242,7 @@ def test_celery(): ) if hasattr(django_settings, 'BROKER_BACKEND') and not hasattr(django_settings, 'BROKER_TRANSPORT'): - raise ImproperlyConfigured(PREAMBLE + \ + raise AskbotConfigError( "\nPlease rename setting BROKER_BACKEND to BROKER_TRANSPORT\n" "in your settings.py file" ) @@ -217,7 +253,7 @@ def test_media_url(): media_url = django_settings.MEDIA_URL #todo: add proper url validation to MEDIA_URL setting if not (media_url.startswith('/') or media_url.startswith('http')): - raise ImproperlyConfigured(PREAMBLE + \ + raise AskbotConfigError( "\nMEDIA_URL parameter must be a unique url on the site\n" "and must start with a slash - e.g. /media/ or http(s)://" ) @@ -266,11 +302,129 @@ class SettingsTester(object): **self.requirements[setting_name] ) if len(self.messages) != 0: - raise ImproperlyConfigured( - PREAMBLE + + raise AskbotConfigError( '\n\nTime to do some maintenance of your settings.py:\n\n* ' + '\n\n* '.join(self.messages) ) + +def test_staticfiles(): + """tests configuration of the staticfiles app""" + errors = list() + import django + django_version = django.VERSION + if django_version[0] == 1 and django_version[1] < 3: + staticfiles_app_name = 'staticfiles' + wrong_staticfiles_app_name = 'django.contrib.staticfiles' + try_import('staticfiles', 'django-staticfiles') + import staticfiles + if staticfiles.__version__[0] != 1: + raise AskbotConfigError( + 'Please use the newest available version of ' + 'django-staticfiles app, type\n' + 'pip install --upgrade django-staticfiles' + ) + if not hasattr(django_settings, 'STATICFILES_STORAGE'): + raise AskbotConfigError( + 'Configure STATICFILES_STORAGE setting as desired, ' + 'a reasonable default is\n' + "STATICFILES_STORAGE = 'staticfiles.storage.StaticFilesStorage'" + ) + else: + staticfiles_app_name = 'django.contrib.staticfiles' + wrong_staticfiles_app_name = 'staticfiles' + + if staticfiles_app_name not in django_settings.INSTALLED_APPS: + errors.append( + 'Add to the INSTALLED_APPS section of your settings.py:\n' + " '%s'," % staticfiles_app_name + ) + if wrong_staticfiles_app_name in django_settings.INSTALLED_APPS: + errors.append( + 'Remove from the INSTALLED_APPS section of your settings.py:\n' + " '%s'," % wrong_staticfiles_app_name + ) + static_url = django_settings.STATIC_URL + if static_url is None or str(static_url).strip() == '': + errors.append( + 'Add STATIC_URL setting to your settings.py file. ' + 'The setting must be a url at which static files ' + 'are accessible.' + ) + url = urlparse(static_url).path + if not (url.startswith('/') and url.endswith('/')): + #a simple check for the url + errors.append( + 'Path in the STATIC_URL must start and end with the /.' + ) + if django_settings.ADMIN_MEDIA_PREFIX != static_url + 'admin/': + errors.append( + 'Set ADMIN_MEDIA_PREFIX as: \n' + " ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'" + ) + + askbot_root = os.path.dirname(askbot.__file__) + skin_dir = os.path.abspath(os.path.join(askbot_root, 'skins')) + if skin_dir not in map(os.path.abspath, django_settings.STATICFILES_DIRS): + errors.append( + 'Add to STATICFILES_DIRS list of your settings.py file:\n' + " '%s'," % skin_dir + ) + extra_skins_dir = getattr(django_settings, 'ASKBOT_EXTRA_SKINS_DIR', None) + if extra_skins_dir is not None: + if not os.path.isdir(extra_skins_dir): + errors.append( + 'Directory specified with settning ASKBOT_EXTRA_SKINS_DIR ' + 'must exist and contain your custom skins for askbot.' + ) + if extra_skins_dir not in django_settings.STATICFILES_DIRS: + errors.append( + 'Add ASKBOT_EXTRA_SKINS_DIR to STATICFILES_DIRS entry in ' + 'your settings.py file.\n' + 'NOTE: it might be necessary to move the line with ' + 'ASKBOT_EXTRA_SKINS_DIR just above STATICFILES_DIRS.' + ) + + if errors: + errors.append( + 'Run command (after fixing the above errors)\n' + ' python manage.py collectstatic\n' + ) + print_errors(errors) + if django_settings.DEBUG and django_settings.STATICFILES_STORAGE == \ + 'django.contrib.staticfiles.storage.StaticFilesStorage': + if not os.path.isdir(django_settings.STATIC_ROOT): + askbot_warning( + 'Please run command\n\n' + ' python manage.py collectstatic' + + ) + +def test_csrf_cookie_domain(): + """makes sure that csrf cookie domain setting is acceptable""" + #todo: maybe use the same steps to clean domain name + csrf_cookie_domain = django_settings.CSRF_COOKIE_DOMAIN + if csrf_cookie_domain == 'localhost': + raise ImproperlyConfigured( + PREAMBLE + + '\n\nPlease do not use value "localhost" for the setting ' + 'CSRF_COOKIE_DOMAIN\n' + 'instead use 127.0.0.1, a real IP ' + 'address or domain name.' + '\nThe value must match the network location you type in the ' + 'web browser to reach your site.' + ) + if re.match(r'https?://', csrf_cookie_domain): + raise ImproperlyConfigured( + PREAMBLE + + '\n\nplease remove http(s):// prefix in the CSRF_COOKIE_DOMAIN ' + 'setting' + ) + if ':' in csrf_cookie_domain: + raise ImproperlyConfigured( + PREAMBLE + + '\n\nPlease do not use port number in the CSRF_COOKIE_DOMAIN ' + 'setting' + ) def run_startup_tests(): """function that runs @@ -285,6 +439,8 @@ def run_startup_tests(): #test_postgres() test_middleware() test_celery() + test_csrf_cookie_domain() + test_staticfiles() settings_tester = SettingsTester({ 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY': { 'value': True, @@ -320,7 +476,7 @@ def run(): """runs all the startup procedures""" try: run_startup_tests() - except ImproperlyConfigured, error: + except AskbotConfigError, error: transaction.rollback() print error sys.exit(1) diff --git a/askbot/tests/images/logo.gif b/askbot/tests/images/logo.gif Binary files differindex 8540e12b..8540e12b 100755..100644 --- a/askbot/tests/images/logo.gif +++ b/askbot/tests/images/logo.gif diff --git a/askbot/tests/skin_tests.py b/askbot/tests/skin_tests.py index ecbea77d..5226e6d6 100644 --- a/askbot/tests/skin_tests.py +++ b/askbot/tests/skin_tests.py @@ -41,13 +41,9 @@ class SkinTests(TestCase): def assert_default_logo_in_skin(self, skin_name): url = skin_utils.get_media_url(askbot_settings.SITE_LOGO_URL) self.assertTrue('/' + skin_name + '/' in url) - response = self.client.get(url) - self.assertTrue(response.status_code == 200) def test_default_skin_logo(self): - """make sure that default logo - is where it is expected - """ + """make sure that default logo is where it is expected""" self.assert_default_logo_in_skin('default') def test_switch_to_custom_skin_logo(self): diff --git a/askbot/urls.py b/askbot/urls.py index cf7d3fe6..d0673520 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -36,11 +36,6 @@ urlpatterns = patterns('', {'sitemaps': sitemaps}, name='sitemap' ), - url( - r'^m/(?P<skin>[^/]+)/media/(?P<resource>.*)$', - views.meta.media, - name='askbot_media', - ), #no translation for this url!! url(r'import-data/$', views.writers.import_data, name='import_data'), url(r'^%s$' % _('about/'), views.meta.about, name='about'), diff --git a/askbot/utils/functions.py b/askbot/utils/functions.py index d31d9027..373cdf87 100644 --- a/askbot/utils/functions.py +++ b/askbot/utils/functions.py @@ -11,6 +11,14 @@ def get_from_dict_or_object(source, key): return getattr(source, key) +def enumerate_string_list(strings): + """for a list or a tuple ('one', 'two',) return + a list formatted as ['1) one', '2) two',] + """ + numbered_strings = enumerate(strings, start = 1) + return [ '%d) %s' % item for item in numbered_strings ] + + def is_iterable(thing): if hasattr(thing, '__iter__'): return True diff --git a/askbot/views/meta.py b/askbot/views/meta.py index 6415077a..884ec5e4 100644 --- a/askbot/views/meta.py +++ b/askbot/views/meta.py @@ -136,14 +136,3 @@ def badge(request, id): 'page_class': 'meta', } return render_into_skin('badge.html', data, request) - -def media(request, skin, resource): - """view that serves static media from any skin - uses django static serve view, where document root is - adjusted according to the current skin selection - - in production this views should be by-passed via server configuration - for the better efficiency of serving static files - """ - dir = skins.utils.get_path_to_skin(skin) - return static.serve(request, '/media/' + resource, document_root = dir) |