summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore2
-rw-r--r--askbot/context.py3
-rw-r--r--askbot/deployment/__init__.py7
-rw-r--r--askbot/deps/django_authopenid/views.py5
-rw-r--r--askbot/doc/source/changelog.rst6
-rw-r--r--askbot/doc/source/deployment.rst29
-rw-r--r--askbot/management/commands/send_email_alerts.py27
-rw-r--r--askbot/middleware/view_log.py3
-rw-r--r--askbot/setup_templates/settings.py15
-rw-r--r--askbot/setup_templates/settings.py.mustache16
-rw-r--r--askbot/skins/common/media/js/utils.js2
-rw-r--r--askbot/skins/common/templates/debug_header.html27
-rw-r--r--askbot/skins/default/templates/base.html1
-rw-r--r--askbot/skins/default/templates/meta/bottom_scripts.html1
-rw-r--r--askbot/skins/utils.py9
-rw-r--r--askbot/startup_procedures.py190
-rw-r--r--[-rwxr-xr-x]askbot/tests/images/logo.gifbin910 -> 910 bytes
-rw-r--r--askbot/tests/skin_tests.py6
-rw-r--r--askbot/urls.py5
-rw-r--r--askbot/utils/functions.py8
-rw-r--r--askbot/views/meta.py11
21 files changed, 280 insertions, 93 deletions
diff --git a/.gitignore b/.gitignore
index d6a06e66..b12637db 100755
--- a/.gitignore
+++ b/.gitignore
@@ -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
index 8540e12b..8540e12b 100755..100644
--- a/askbot/tests/images/logo.gif
+++ b/askbot/tests/images/logo.gif
Binary files differ
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)