summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/__init__.py2
-rw-r--r--askbot/conf/license.py2
-rw-r--r--askbot/conf/login_providers.py2
-rw-r--r--askbot/conf/skin_general_settings.py6
-rw-r--r--askbot/conf/user_settings.py11
-rw-r--r--askbot/deps/livesettings/values.py28
-rw-r--r--askbot/doc/source/changelog.rst8
-rw-r--r--askbot/doc/source/contributors.rst2
-rw-r--r--askbot/forms.py1
-rw-r--r--askbot/locale/es/LC_MESSAGES/django.po76
-rw-r--r--askbot/setup_templates/settings.py7
-rw-r--r--askbot/setup_templates/settings.py.mustache7
-rw-r--r--askbot/setup_templates/urls.py5
-rw-r--r--askbot/skins/common/media/js/editor.js7
-rw-r--r--askbot/skins/default/templates/about.html10
-rw-r--r--askbot/skins/default/templates/base.html5
-rw-r--r--askbot/skins/default/templates/faq.html10
-rw-r--r--askbot/skins/default/templates/meta/bottom_scripts.html2
-rw-r--r--askbot/skins/default/templates/privacy.html8
-rw-r--r--askbot/skins/default/templates/static_page.html10
-rw-r--r--askbot/skins/default/templates/user_profile/user_edit.html21
-rw-r--r--askbot/skins/default/templates/widgets/header.html1
-rw-r--r--askbot/skins/utils.py11
-rw-r--r--askbot/startup_procedures.py43
-rw-r--r--askbot/tests/page_load_tests.py4
-rw-r--r--askbot/tests/skin_tests.py7
-rw-r--r--askbot/urls.py6
-rw-r--r--askbot/utils/markup.py15
-rw-r--r--askbot/views/meta.py41
-rw-r--r--askbot/views/writers.py18
30 files changed, 204 insertions, 172 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index d4727712..7b12329c 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -9,7 +9,7 @@ import smtplib
import sys
import logging
-VERSION = (0, 7, 36)
+VERSION = (0, 7, 37)
#keys are module names used by python imports,
#values - the package qualifier to use for pip
diff --git a/askbot/conf/license.py b/askbot/conf/license.py
index 20a2743f..faf50697 100644
--- a/askbot/conf/license.py
+++ b/askbot/conf/license.py
@@ -76,8 +76,6 @@ settings.register(
LICENSE_SETTINGS,
'LICENSE_LOGO_URL',
description = _('License logo image'),
- upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
- upload_url = '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default = '/images/cc-by-sa.png',
url_resolver = skin_utils.get_media_url
)
diff --git a/askbot/conf/login_providers.py b/askbot/conf/login_providers.py
index b6073eea..3fab7d6a 100644
--- a/askbot/conf/login_providers.py
+++ b/askbot/conf/login_providers.py
@@ -56,8 +56,6 @@ settings.register(
livesettings.ImageValue(
LOGIN_PROVIDERS,
'WORDPRESS_SITE_ICON',
- upload_directory=django_settings.ASKBOT_FILE_UPLOAD_DIR,
- upload_url='/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default='/images/logo.gif',
description=_('Upload your icon'),
url_resolver=skin_utils.get_media_url
diff --git a/askbot/conf/skin_general_settings.py b/askbot/conf/skin_general_settings.py
index 387ac1f6..ccecdaba 100644
--- a/askbot/conf/skin_general_settings.py
+++ b/askbot/conf/skin_general_settings.py
@@ -25,8 +25,6 @@ settings.register(
'To change the logo, select new file, '
'then submit this whole form.'
),
- upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
- upload_url = django_settings.ASKBOT_URL + '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default = '/images/logo.gif',
url_resolver = skin_utils.get_media_url
)
@@ -58,9 +56,7 @@ settings.register(
'about favicon '
'at <a href="%(favicon_info_url)s">this page</a>.'
) % {'favicon_info_url': const.DEPENDENCY_URLS['favicon']},
- upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
allowed_file_extensions = ('ico',),#only allow .ico files
- upload_url = '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default = '/images/favicon.gif',
url_resolver = skin_utils.get_media_url
)
@@ -75,8 +71,6 @@ settings.register(
'An 88x38 pixel image that is used on the login screen '
'for the password login button.'
),
- upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
- upload_url = '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default = '/images/pw-login.gif',
url_resolver = skin_utils.get_media_url
)
diff --git a/askbot/conf/user_settings.py b/askbot/conf/user_settings.py
index cec13083..321d38f9 100644
--- a/askbot/conf/user_settings.py
+++ b/askbot/conf/user_settings.py
@@ -27,6 +27,15 @@ settings.register(
settings.register(
livesettings.BooleanValue(
USER_SETTINGS,
+ 'EDITABLE_EMAIL',
+ default = True,
+ description = _('Allow users change own email addresses')
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ USER_SETTINGS,
'ALLOW_ACCOUNT_RECOVERY_BY_EMAIL',
default = True,
description = _('Allow account recovery by email')
@@ -61,8 +70,6 @@ settings.register(
'To change the avatar image, select new file, '
'then submit this whole form.'
),
- upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
- upload_url = '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
default = '/images/nophoto.png',
url_resolver = skin_utils.get_media_url
)
diff --git a/askbot/deps/livesettings/values.py b/askbot/deps/livesettings/values.py
index 9587a16d..e5516d8b 100644
--- a/askbot/deps/livesettings/values.py
+++ b/askbot/deps/livesettings/values.py
@@ -4,6 +4,7 @@ http://code.google.com/p/django-values/
"""
from decimal import Decimal
from django import forms
+from django.conf import settings as django_settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import simplejson
from django.utils.datastructures import SortedDict
@@ -600,8 +601,14 @@ class ImageValue(StringValue):
'allowed_file_extensions',
('jpg', 'gif', 'png')
)
- self.upload_directory = kwargs.pop('upload_directory')
- self.upload_url = kwargs.pop('upload_url')
+ self.upload_directory = kwargs.pop(
+ 'upload_directory',
+ django_settings.MEDIA_ROOT
+ )
+ self.upload_url = kwargs.pop(
+ 'upload_url',
+ django_settings.MEDIA_URL
+ )
self.url_resolver = kwargs.pop('url_resolver', None)
super(ImageValue, self).__init__(*args, **kwargs)
@@ -632,13 +639,20 @@ class ImageValue(StringValue):
"""uploaded_file is an instance of
django UploadedFile object
"""
- #1) come up with a file name
+ #0) initialize file storage
+ file_storage_class = storage.get_storage_class()
- file_storage = storage.FileSystemStorage(
- location = self.upload_directory,
- base_url = self.upload_url
- )
+ storage_settings = {}
+ if django_settings.DEFAULT_FILE_STORAGE == \
+ 'django.core.files.storage.FileSystemStorage':
+ storage_settings = {
+ 'location': self.upload_directory,
+ 'base_url': self.upload_url
+ }
+
+ file_storage = file_storage_class(**storage_settings)
+ #1) come up with a file name
#todo: need better function here to calc name
file_name = file_storage.get_available_name(uploaded_file.name)
file_storage.save(file_name, uploaded_file)
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index c228e158..ce18fe11 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -1,8 +1,8 @@
Changes in Askbot
=================
-Development version (not released yet)
---------------------------------------
+0.7.37 (Jan 8, 2012)
+--------------------
* added basic slugification treatment to question titles with
``ALLOW_UNICODE_SLUGS = True`` (Evgeny)
* added verification of the project directory name to
@@ -15,6 +15,10 @@ Development version (not released yet)
text to live settings and allowed body-less questions (Radim Řehůřek, Evgeny)
* allowed disabling use of gravatar site-wide (Rosandra Cuello Suñol)
* when internal login app is disabled - links to login/logout/add-remove-login-methods are gone (Evgeny)
+* replaced setting `ASKBOT_FILE_UPLOAD_DIR` with django's `MEDIA_ROOT` (Evgeny)
+* replaced setting `ASKBOT_UPLOADED_FILES_URL` with django's `MEDIA_URL` (Evgeny)
+* allowed changing file storage backend for file uploads by configuration (Evgeny)
+* file uploads to amazon S3 now work with proper configuration (Evgeny)
0.7.36 (Dec 20, 2011)
---------------------
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
index 6285d9a6..30e31175 100644
--- a/askbot/doc/source/contributors.rst
+++ b/askbot/doc/source/contributors.rst
@@ -39,7 +39,7 @@ Programming and documentation
Translations
------------
* Mike Chen, Sailing Cai, suyu8776 - Chinese
-* Bruno Sarlo, Adolfo Fitoria - Spanish
+* Bruno Sarlo, Adolfo Fitoria, Francisco Espinoza - Spanish
* Evgeny Kalinin - Russian
* Evgeny Fadeev - English
* Oktay Yildiz, Onur Mat, Cemre - Turkish
diff --git a/askbot/forms.py b/askbot/forms.py
index 4e490ce6..cc6c2f73 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -918,7 +918,6 @@ class EditAnswerForm(forms.Form):
class EditUserForm(forms.Form):
email = forms.EmailField(
label=u'Email',
- help_text=_('this email will be linked to gravatar'),
required=True,
max_length=255,
widget=forms.TextInput(attrs={'size' : 35})
diff --git a/askbot/locale/es/LC_MESSAGES/django.po b/askbot/locale/es/LC_MESSAGES/django.po
index d5a88e1d..b88131cc 100644
--- a/askbot/locale/es/LC_MESSAGES/django.po
+++ b/askbot/locale/es/LC_MESSAGES/django.po
@@ -22,7 +22,7 @@ msgstr ""
#: exceptions.py:13
#, fuzzy
msgid "Sorry, but anonymous visitors cannot access this function"
-msgstr "usuarios anónimos no pueden votar"
+msgstr "Lo sentimos pero los usuarios anónimos no pueden acceder a esta función"
#: feed.py:26 feed.py:100
msgid " - "
@@ -40,16 +40,16 @@ msgstr "últimas preguntas"
#: forms.py:74
#, fuzzy
msgid "select country"
-msgstr "Eliminar cuenta"
+msgstr "seleccione país"
#: forms.py:83
msgid "Country"
-msgstr ""
+msgstr "País"
#: forms.py:91
#, fuzzy
msgid "Country field is required"
-msgstr "este campo es requerido"
+msgstr "El campo País es requerido"
#: forms.py:104 skins/default/templates/widgets/answer_edit_tips.html:45
#: skins/default/templates/widgets/answer_edit_tips.html:49
@@ -66,8 +66,8 @@ msgstr "por favor ingrese un título descriptivo para su pregunta"
#, fuzzy, python-format
msgid "title must be > %d character"
msgid_plural "title must be > %d characters"
-msgstr[0] "el título debe contener más de 10 carácteres"
-msgstr[1] "el título debe contener más de 10 carácteres"
+msgstr[0] "el título debe contener más de %d carácter"
+msgstr[1] "el título debe contener más de %d carácteres"
#: forms.py:131
msgid "content"
@@ -88,10 +88,10 @@ msgid_plural ""
"Tags are short keywords, with no spaces within. Up to %(max_tags)d tags can "
"be used."
msgstr[0] ""
-"Las etiquetas son claves cortas, con o sin espacios. Puedes usar más de 5 "
-"etiquetas."
+"Las etiquetas son claves cortas, sin espacios. Puedes usar hasta %(max_tags)d "
+"etiqueta."
msgstr[1] ""
-"Las etiquetas son claves cortas, con o sin espacios. Puedes usar más de 5 "
+"Las etiquetas son claves cortas, sin espacios. Puedes usar hasta %(max_tags)d "
"etiquetas."
#: forms.py:201 skins/default/templates/question_retag.html:58
@@ -102,35 +102,35 @@ msgstr "etiquetas requeridas"
#, fuzzy, python-format
msgid "please use %(tag_count)d tag or less"
msgid_plural "please use %(tag_count)d tags or less"
-msgstr[0] "por favor, use 5 etiquetas o menos"
-msgstr[1] "por favor, use 5 etiquetas o menos"
+msgstr[0] "por favor, use %(tag_count)d etiqueta o menos"
+msgstr[1] "por favor, use %(tag_count)d etiquetas o menos"
#: forms.py:218
#, python-format
msgid "At least one of the following tags is required : %(tags)s"
-msgstr ""
+msgstr "Al menos una de las siguientes etiquetas se requieren : %(tags)s"
#: forms.py:227
#, fuzzy, python-format
msgid "each tag must be shorter than %(max_chars)d character"
msgid_plural "each tag must be shorter than %(max_chars)d characters"
-msgstr[0] "las etiquetas deben contener menos de 20 carácteres"
-msgstr[1] "las etiquetas deben contener menos de 20 carácteres"
+msgstr[0] "las etiquetas deben contener menos de %(max_chars)d carácter"
+msgstr[1] "las etiquetas deben contener menos de %(max_chars)d carácteres"
#: forms.py:235
msgid "use-these-chars-in-tags"
-msgstr ""
+msgstr "usa-estos-caracteres-en-las-etiquetas"
#: forms.py:270
msgid "community wiki (karma is not awarded & many others can edit wiki post)"
-msgstr ""
+msgstr "wiki comunitaria (no se premia karma y cualquiera puede editar la publicación wiki)"
#: forms.py:271
msgid ""
"if you choose community wiki option, the question and answer do not generate "
"points and name of author will not be shown"
msgstr ""
-"si marcas la opción Wiki, la pregunta y las respuestas no generan puntos y "
+"si marcas la opción Wiki comunitaria,la pregunta y las respuestas no generan puntos y "
"el nombre del autor no se muestra"
#: forms.py:287
@@ -147,7 +147,7 @@ msgstr ""
#: forms.py:364
msgid "Enter number of points to add or subtract"
-msgstr ""
+msgstr "Ingrese el número de puntos a añadir o quitar"
#: forms.py:378 const/__init__.py:250
msgid "approved"
@@ -160,7 +160,7 @@ msgstr "visto"
#: forms.py:380 const/__init__.py:252
#, fuzzy
msgid "suspended"
-msgstr "actualizado"
+msgstr "pausado"
#: forms.py:381 const/__init__.py:253
msgid "blocked"
@@ -169,26 +169,26 @@ msgstr "bloqueado"
#: forms.py:383
#, fuzzy
msgid "administrator"
-msgstr "administración"
+msgstr "administrador"
#: forms.py:384 const/__init__.py:249
#, fuzzy
msgid "moderator"
-msgstr "moderar-usuario/"
+msgstr "moderador"
#: forms.py:404
#, fuzzy
msgid "Change status to"
-msgstr "Cambiar etiquetas"
+msgstr "Cambiar estado a"
#: forms.py:431
msgid "which one?"
-msgstr ""
+msgstr "Cuál?"
#: forms.py:452
#, fuzzy
msgid "Cannot change own status"
-msgstr "no se puede votar por sus propias publicaciones"
+msgstr "No puede cambiar su propio estado"
#: forms.py:458
msgid "Cannot turn other user to moderator"
@@ -201,62 +201,64 @@ msgstr "No tiene permitido cambiar el estado de otro moderador"
#: forms.py:471
#, fuzzy
msgid "Cannot change status to admin"
-msgstr "no se puede votar por sus propias publicaciones"
+msgstr "No puede cambiar el estado a admin"
#: forms.py:477
#, python-format
msgid ""
"If you wish to change %(username)s's status, please make a meaningful "
"selection."
-msgstr ""
+msgstr "Si desea cambiar el estado de %(username), por favor, haga una selección "
+"apropiada."
#: forms.py:486
msgid "Subject line"
-msgstr "Sujeto"
+msgstr "Línea del tema"
#: forms.py:493
msgid "Message text"
-msgstr "Mensaje de Texto"
+msgstr "Texto del mensaje"
#: forms.py:579
#, fuzzy
msgid "Your name (optional):"
-msgstr "Tu nombre:"
+msgstr "Su nombre (opcional):"
#: forms.py:580
#, fuzzy
msgid "Email:"
-msgstr "no enviar emails"
+msgstr "Correo electrónico:"
#: forms.py:582
msgid "Your message:"
-msgstr "Tu mensaje:"
+msgstr "Su mensaje:"
#: forms.py:587
msgid "I don't want to give my email or receive a response:"
-msgstr ""
+msgstr "No deseo dar mi correo electrónico o recibir una respuesta:"
#: forms.py:609
msgid "Please mark \"I dont want to give my mail\" field."
-msgstr ""
+msgstr "Por favor, marque el campo \"No deseo dar mi correo electrónico\"."
#: forms.py:648
msgid "ask anonymously"
-msgstr ""
+msgstr "pregunte anónimamente"
#: forms.py:650
msgid "Check if you do not want to reveal your name when asking this question"
-msgstr ""
+msgstr "Compruebe si no desea revelar su nombre cuando realice esta pregunta"
#: forms.py:810
msgid ""
"You have asked this question anonymously, if you decide to reveal your "
"identity, please check this box."
-msgstr ""
+msgstr "Ha solicitado realizar esta pregunta anónimamente, si decide revelar su "
+"identidad, por favor marque esta caja."
#: forms.py:814
msgid "reveal identity"
-msgstr ""
+msgstr "revelar identidad"
#: forms.py:872
msgid ""
diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py
index 715e6ce8..27ee77dc 100644
--- a/askbot/setup_templates/settings.py
+++ b/askbot/setup_templates/settings.py
@@ -68,7 +68,8 @@ LANGUAGE_CODE = 'en'
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
-ASKBOT_FILE_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
+MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
+MEDIA_URL = '/upfiles/'
PROJECT_ROOT = os.path.dirname(__file__)
@@ -167,9 +168,6 @@ INSTALLED_APPS = (
'djkombu',
'followit',
#'avatar',#experimental use git clone git://github.com/ericflo/django-avatar.git$
- #requires setting of MEDIA_ROOT and MEDIA_URL
- #values of which can be the same as ASKBOT_FILE_UPLOAD_DIR and ASKBOT_UPLOADED_FILES_URL,
- #respectively
)
@@ -209,7 +207,6 @@ LOGIN_URL = '/%s%s%s' % (ASKBOT_URL,_('account/'),_('signin/'))
LOGIN_REDIRECT_URL = ASKBOT_URL #adjust if needed
#note - it is important that upload dir url is NOT translated!!!
#also, this url must not have the leading slash
-ASKBOT_UPLOADED_FILES_URL = 'upfiles/'
ALLOW_UNICODE_SLUGS = False
ASKBOT_USE_STACKEXCHANGE_URLS = False #mimic url scheme of stackexchange
diff --git a/askbot/setup_templates/settings.py.mustache b/askbot/setup_templates/settings.py.mustache
index 69da823a..4b01b4df 100644
--- a/askbot/setup_templates/settings.py.mustache
+++ b/askbot/setup_templates/settings.py.mustache
@@ -68,7 +68,8 @@ LANGUAGE_CODE = 'en'
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
-ASKBOT_FILE_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
+MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles')
+MEDIA_URL = '/upfiles/'
PROJECT_ROOT = os.path.dirname(__file__)
@@ -166,9 +167,6 @@ INSTALLED_APPS = (
'djkombu',
'followit',
#'avatar',#experimental use git clone git://github.com/ericflo/django-avatar.git$
- #requires setting of MEDIA_ROOT and MEDIA_URL
- #values of which can be the same as ASKBOT_FILE_UPLOAD_DIR and ASKBOT_UPLOADED_FILES_URL,
- #respectively
)
@@ -208,7 +206,6 @@ LOGIN_URL = '/%s%s%s' % (ASKBOT_URL,_('account/'),_('signin/'))
LOGIN_REDIRECT_URL = ASKBOT_URL #adjust, if needed
#note - it is important that upload dir url is NOT translated!!!
#also, this url must not have the leading slash
-ASKBOT_UPLOADED_FILES_URL = 'upfiles/'
ALLOW_UNICODE_SLUGS = False
ASKBOT_USE_STACKEXCHANGE_URLS = False #mimic url scheme of stackexchange
diff --git a/askbot/setup_templates/urls.py b/askbot/setup_templates/urls.py
index 2ec69cf0..8c92f6d1 100644
--- a/askbot/setup_templates/urls.py
+++ b/askbot/setup_templates/urls.py
@@ -14,6 +14,11 @@ urlpatterns = patterns('',
(r'^settings/', include('askbot.deps.livesettings.urls')),
(r'^followit/', include('followit.urls')),
(r'^robots.txt$', include('robots.urls')),
+ url( # TODO: replace with django.conf.urls.static ?
+ r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:],
+ 'django.views.static.serve',
+ {'document_root': settings.MEDIA_ROOT.replace('\\','/')},
+ ),
)
if 'rosetta' in settings.INSTALLED_APPS:
diff --git a/askbot/skins/common/media/js/editor.js b/askbot/skins/common/media/js/editor.js
index f5b1e2af..e580f9f6 100644
--- a/askbot/skins/common/media/js/editor.js
+++ b/askbot/skins/common/media/js/editor.js
@@ -42,11 +42,11 @@ function ajaxFileUpload(imageUrl, startUploadHandler)
url: askbot['urls']['upload'],
secureuri:false,
fileElementId:'file-upload',
- dataType: 'xml',
+ dataType: 'json',
success: function (data, status)
{
- var fileURL = $(data).find('file_url').text();
- var error = $(data).find('error').text();
+ var fileURL = data['file_url'];
+ var error = data['error'];
if(error != ''){
alert(error);
if (startUploadHandler){
@@ -57,7 +57,6 @@ function ajaxFileUpload(imageUrl, startUploadHandler)
}else{
imageUrl.attr('value', fileURL);
}
-
},
error: function (data, status, e)
{
diff --git a/askbot/skins/default/templates/about.html b/askbot/skins/default/templates/about.html
deleted file mode 100644
index d5d1b949..00000000
--- a/askbot/skins/default/templates/about.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "two_column_body.html" %}
-<!-- template about.html -->
-{% block title %}{% spaceless %}{% trans site_name=settings.APP_SHORT_NAME %}About {{site_name}}{% endtrans %}{% endspaceless %}{% endblock %}
-{% block content %}
-<h1 class="section-title">{% trans site_name=settings.APP_SHORT_NAME %}About {{site_name}}{% endtrans %}</h1>
-<div class="content">
- {{settings.FORUM_ABOUT}}
-</div>
-{% endblock %}
-<!-- end template about.html -->
diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html
index 1102007b..8287f5ba 100644
--- a/askbot/skins/default/templates/base.html
+++ b/askbot/skins/default/templates/base.html
@@ -17,6 +17,11 @@
<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 "custom_header.html" ignore missing %}
+ {% if settings.CUSTOM_HEADER|trim != '' %}
+ <div id="custom-header">
+ {{settings.CUSTOM_HEADER}}
+ </div>
+ {% endif %}
{% include "widgets/header.html" %} {# Logo, user tool navigation and meta navitation #}
{% include "widgets/secondary_header.html" %} {# Scope selector, search input and ask button #}
<div class="content-wrapper">
diff --git a/askbot/skins/default/templates/faq.html b/askbot/skins/default/templates/faq.html
deleted file mode 100644
index 51873a06..00000000
--- a/askbot/skins/default/templates/faq.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "two_column_body.html" %}
-<!-- template faq.html -->
-{% block title %}{% spaceless %}{% trans %}FAQ{% endtrans %}{% endspaceless %}{% endblock %}
-{% block content %}
-<div class="content">
-<h1 class="section-title">FAQ</h1>
- {{forum_faq}}
-</div>
-{% endblock %}
-<!-- end template faq.html -->
diff --git a/askbot/skins/default/templates/meta/bottom_scripts.html b/askbot/skins/default/templates/meta/bottom_scripts.html
index 3d87805b..be9b69e1 100644
--- a/askbot/skins/default/templates/meta/bottom_scripts.html
+++ b/askbot/skins/default/templates/meta/bottom_scripts.html
@@ -93,7 +93,7 @@
</script>
{% if settings.USE_CUSTOM_JS %}
<script
- src="{% url "custom_js"%}?{{ settings.MEDIA_RESOURCE_REVISION }}"
+ src="{% url "custom_js"%}?v={{ settings.MEDIA_RESOURCE_REVISION }}"
type="text/javascript"
></script>
{% endif %}
diff --git a/askbot/skins/default/templates/privacy.html b/askbot/skins/default/templates/privacy.html
deleted file mode 100644
index e9b6f58b..00000000
--- a/askbot/skins/default/templates/privacy.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends "two_column_body.html" %}
-<!-- privacy.html -->
-{% block title %}{% spaceless %}{% trans %}Privacy policy{% endtrans %}{% endspaceless %}{% endblock %}
-{% block content %}
-<h1 class="section-title">{% trans %}Privacy policy{% endtrans %}</h1>
-{{settings.FORUM_PRIVACY}}
-{% endblock %}
-<!-- end privacy.html -->
diff --git a/askbot/skins/default/templates/static_page.html b/askbot/skins/default/templates/static_page.html
new file mode 100644
index 00000000..c537e199
--- /dev/null
+++ b/askbot/skins/default/templates/static_page.html
@@ -0,0 +1,10 @@
+{% extends "two_column_body.html" %}
+<!-- template static_page.html -->
+{% block title %}{% spaceless %}{{title}}{% endspaceless %}{% endblock %}
+{% block content %}
+<div class="content">
+ <h1 class="section-title">{{title}}</h1>
+ {{content}}
+</div>
+{% endblock %}
+<!-- end template static_page.html -->
diff --git a/askbot/skins/default/templates/user_profile/user_edit.html b/askbot/skins/default/templates/user_profile/user_edit.html
index daaa3663..94a1d58d 100644
--- a/askbot/skins/default/templates/user_profile/user_edit.html
+++ b/askbot/skins/default/templates/user_profile/user_edit.html
@@ -42,17 +42,24 @@
{{ form.username }}
<span class="form-error"></span> {{ form.username.errors }} </td>
{% else %}
- {{ request.user.username }}
+ {{ view_user.username }}
{% endif %}
</td>
</tr>
<tr>
- <td>{{ form.email.label_tag() }}:</td>
- <td>{{ form.email }} <span class="form-error"></span> {{ form.email.errors }} </td>
- </tr>
- <tr>
- <td></td>
- <td class="title-desc">{{ form.email.help_text }}</td>
+ <td>
+ {{ form.email.label_tag() }}:
+ </td>
+ <td>
+ {% if settings.EDITABLE_EMAIL %}
+ {{ form.email }}
+ <span class="form-error"></span>
+ {{ form.email.errors }}
+ {% else %}
+ {{ view_user.email }}
+ {% trans %}(cannot be changed){% endtrans %}
+ {% endif %}
+ </td>
</tr>
<tr>
<td>{{ form.realname.label_tag() }}:</td>
diff --git a/askbot/skins/default/templates/widgets/header.html b/askbot/skins/default/templates/widgets/header.html
index d4e7d66a..52e528bc 100644
--- a/askbot/skins/default/templates/widgets/header.html
+++ b/askbot/skins/default/templates/widgets/header.html
@@ -7,7 +7,6 @@
<div class="content-wrapper">
<div id="userToolsNav">
{% include "widgets/user_navigation.html" %}
- {{settings.CUSTOM_HEADER}}
</div>
{% if settings.SHOW_LOGO %}
{% include "widgets/logo.html" %}
diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py
index da3a8a06..50c0d4fb 100644
--- a/askbot/skins/utils.py
+++ b/askbot/skins/utils.py
@@ -98,18 +98,23 @@ def get_media_url(url, ignore_missing = False):
#before = datetime.datetime.now()
url = urllib.unquote(unicode(url))
while url[0] == '/': url = url[1:]
+
+ #a hack allowing urls media stored on external locations to
+ #just pass through unchanged
+ if url.startswith('http://') or url.startswith('https://'):
+ return url
#todo: handles case of multiple skin directories
#if file is in upfiles directory, then give that
url_copy = url
- if url_copy.startswith(django_settings.ASKBOT_UPLOADED_FILES_URL):
+ if url_copy.startswith(django_settings.MEDIA_URL[1:]):
file_path = url_copy.replace(
- django_settings.ASKBOT_UPLOADED_FILES_URL,
+ django_settings.MEDIA_URL[1:],
'',
1
)
file_path = os.path.join(
- django_settings.ASKBOT_FILE_UPLOAD_DIR,
+ django_settings.MEDIA_ROOT,
file_path
)
if os.path.isfile(file_path):
diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py
index 9c962f2a..05426898 100644
--- a/askbot/startup_procedures.py
+++ b/askbot/startup_procedures.py
@@ -211,6 +211,17 @@ def test_celery():
"in your settings.py file"
)
+def test_media_url():
+ """makes sure that setting `MEDIA_URL`
+ has leading slash"""
+ 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 + \
+ "\nMEDIA_URL parameter must be a unique url on the site\n"
+ "and must start with a slash - e.g. /media/ or http(s)://"
+ )
+
class SettingsTester(object):
"""class to test contents of the settings.py file"""
@@ -228,14 +239,25 @@ class SettingsTester(object):
self.requirements = requirements
- def test_setting(self, name, value = None, message = None):
+ def test_setting(self, name,
+ value = None, message = None,
+ test_for_absence = False,
+ replace_hint = None
+ ):
"""if setting does is not present or if the value != required_value,
adds an error message
"""
- if not hasattr(self.settings, name):
- self.messages.append(message)
- elif value and getattr(self.settings, name) != value:
- self.messages.append(message)
+ if test_for_absence:
+ if hasattr(self.settings, name):
+ if replace_hint:
+ value = getattr(self.settings, name)
+ message += replace_hint % value
+ self.messages.append(message)
+ else:
+ if not hasattr(self.settings, name):
+ self.messages.append(message)
+ elif value and getattr(self.settings, name) != value:
+ self.messages.append(message)
def run(self):
for setting_name in self.requirements:
@@ -278,9 +300,20 @@ def run_startup_tests():
'where you want to send users after they log in\n'
'a reasonable default is\n'
'LOGIN_REDIRECT_URL = ASKBOT_URL'
+ },
+ 'ASKBOT_FILE_UPLOAD_DIR': {
+ 'test_for_absence': True,
+ 'message': 'Please replace setting ASKBOT_FILE_UPLOAD_DIR ',
+ 'replace_hint': "with MEDIA_ROOT = '%s'"
+ },
+ 'ASKBOT_UPLOADED_FILES_URL': {
+ 'test_for_absence': True,
+ 'message': 'Please replace setting ASKBOT_UPLOADED_FILES_URL ',
+ 'replace_hint': "with MEDIA_URL = '/%s'"
}
})
settings_tester.run()
+ test_media_url()
@transaction.commit_manually
def run():
diff --git a/askbot/tests/page_load_tests.py b/askbot/tests/page_load_tests.py
index ac84d092..7249febd 100644
--- a/askbot/tests/page_load_tests.py
+++ b/askbot/tests/page_load_tests.py
@@ -139,11 +139,11 @@ class PageLoadTestCase(AskbotTestCase):
self.try_url(
'about',
status_code=status_code,
- template='about.html')
+ template='static_page.html')
self.try_url(
'privacy',
status_code=status_code,
- template='privacy.html')
+ template='static_page.html')
self.try_url('logout', template='authopenid/logout.html')
#todo: test different tabs
self.try_url(
diff --git a/askbot/tests/skin_tests.py b/askbot/tests/skin_tests.py
index f8e940ee..ecbea77d 100644
--- a/askbot/tests/skin_tests.py
+++ b/askbot/tests/skin_tests.py
@@ -65,11 +65,6 @@ class SkinTests(TestCase):
new_logo = UploadedFile(file = logo_file)
askbot_settings.update('SITE_LOGO_URL', new_logo)
logo_url = askbot_settings.SITE_LOGO_URL
- self.assertTrue(
- logo_url.startswith(
- django_settings.ASKBOT_URL + \
- '/' + django_settings.ASKBOT_UPLOADED_FILES_URL
- )
- )
+ self.assertTrue(logo_url.startswith(django_settings.MEDIA_URL))
response = self.client.get(logo_url)
self.assertTrue(response.status_code == 200)
diff --git a/askbot/urls.py b/askbot/urls.py
index adf01f08..f39fd785 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -41,12 +41,6 @@ urlpatterns = patterns('',
views.meta.media,
name='askbot_media',
),
- url( # TODO: replace with django.conf.urls.static ?
- r'^%s(?P<path>.*)$' % settings.ASKBOT_UPLOADED_FILES_URL,
- 'django.views.static.serve',
- {'document_root': settings.ASKBOT_FILE_UPLOAD_DIR.replace('\\','/')},
- name='uploaded_file',
- ),
#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/markup.py b/askbot/utils/markup.py
index 3ebea3e4..ac96ec74 100644
--- a/askbot/utils/markup.py
+++ b/askbot/utils/markup.py
@@ -11,15 +11,11 @@ from markdown2 import Markdown
#url taken from http://regexlib.com/REDetails.aspx?regexp_id=501 by Brian Bothwell
URL_RE = re.compile("((?<!(href|.src|data)=['\"])((http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+))*))")
-LINK_PATTERNS = [
- (URL_RE, r'\1'),
-]
-
-
def get_parser():
"""returns an instance of configured ``markdown2`` parser
"""
extras = ['link-patterns', 'video']
+
if askbot_settings.ENABLE_MATHJAX or \
askbot_settings.MARKUP_CODE_FRIENDLY:
extras.append('code-friendly')
@@ -30,12 +26,17 @@ def get_parser():
#pip install -e git+git://github.com/andryuha/python-markdown2.git
extras.append('video')
+ link_patterns = [
+ (URL_RE, r'\1'),
+ ]
if askbot_settings.ENABLE_AUTO_LINKING:
pattern_list = askbot_settings.AUTO_LINK_PATTERNS.split('\n')
url_list = askbot_settings.AUTO_LINK_URLS.split('\n')
pairs = zip(pattern_list, url_list)#always takes equal number of items
for item in pairs:
- LINK_PATTERNS.append(
+ if item[0].strip() =='' or item[1].strip() == '':
+ continue
+ link_patterns.append(
(
re.compile(item[0].strip()),
item[1].strip()
@@ -57,7 +58,7 @@ def get_parser():
return Markdown(
html4tags=True,
extras=extras,
- link_patterns = LINK_PATTERNS
+ link_patterns = link_patterns
)
diff --git a/askbot/views/meta.py b/askbot/views/meta.py
index 493ab8ec..6415077a 100644
--- a/askbot/views/meta.py
+++ b/askbot/views/meta.py
@@ -29,11 +29,17 @@ def config_variable(request, variable_name = None, mimetype = None):
"""Print value from the configuration settings
as response content. All parameters are required.
"""
+ #todo add http header-based caching here!!!
output = getattr(askbot_settings, variable_name, '')
return HttpResponse(output, mimetype = mimetype)
def about(request, template='about.html'):
- return generic_view(request, template = template, page_class = 'meta')
+ title = _('About %(site)s') % {'site': askbot_settings.APP_SHORT_NAME}
+ data = {
+ 'title': title,
+ 'content': askbot_settings.FORUM_ABOUT
+ }
+ return render_into_skin('static_page.html', data, request)
def page_not_found(request, template='404.html'):
return generic_view(request, template)
@@ -42,30 +48,19 @@ def server_error(request, template='500.html'):
return generic_view(request, template)
def faq(request):
- if getattr(askbot_settings, 'FORUM_FAQ',''):
- text = _(getattr(askbot_settings, 'FORUM_FAQ',''))
+ if askbot_settings.FORUM_FAQ.strip() != '':
+ return render_into_skin(
+ 'static_page.html',
+ {'title': _('FAQ'), 'content': askbot_settings.FORUM_FAQ},
+ request
+ )
+ else:
data = {
'gravatar_faq_url': reverse('faq') + '#gravatar',
- #'send_email_key_url': reverse('send_email_key'),
- 'ask_question_url': reverse('ask'),
- 'page_class': 'meta',
- }
- forum_faq = render_text_into_skin(text, data, request)
- data_out = {
- 'gravatar_faq_url': reverse('faq') + '#gravatar',
- #'send_email_key_url': reverse('send_email_key'),
'ask_question_url': reverse('ask'),
'page_class': 'meta',
- 'forum_faq' : forum_faq,
}
- return render_into_skin('faq.html', data_out, request)
- data = {
- 'gravatar_faq_url': reverse('faq') + '#gravatar',
- #'send_email_key_url': reverse('send_email_key'),
- 'ask_question_url': reverse('ask'),
- 'page_class': 'meta',
- }
- return render_into_skin('faq_static.html', data, request)
+ return render_into_skin('faq_static.html', data, request)
@csrf.csrf_protect
def feedback(request):
@@ -94,7 +89,11 @@ def feedback(request):
feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)')
def privacy(request):
- return render_into_skin('privacy.html', {'page_class': 'meta'}, request)
+ data = {
+ 'title': _('Privacy policy'),
+ 'content': askbot_settings.FORUM_PRIVACY
+ }
+ return render_into_skin('static_page.html', data, request)
def badges(request):#user status/reputation system
#todo: supplement database data with the stuff from badges.py
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 12cc2471..62ee1ead 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -12,7 +12,7 @@ import random
import sys
import tempfile
import time
-from django.core.files.storage import FileSystemStorage
+from django.core.files.storage import get_storage_class
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
@@ -78,10 +78,7 @@ def upload(request):#ajax upload file to a question or answer
str(random.randint(0,100000))
) + file_extension
- file_storage = FileSystemStorage(
- location = settings.ASKBOT_FILE_UPLOAD_DIR,
- base_url = reverse('uploaded_file', kwargs = {'path':''}),
- )
+ file_storage = get_storage_class()()
# use default storage to store file
file_storage.save(new_file_name, f)
# check file size
@@ -106,11 +103,12 @@ def upload(request):#ajax upload file to a question or answer
result = ''
file_url = ''
- #<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>
- xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
- xml = xml_template % (result, error, file_url)
-
- return HttpResponse(xml, mimetype="application/xml")
+ data = simplejson.dumps({
+ 'result': result,
+ 'error': error,
+ 'file_url': file_url
+ })
+ return HttpResponse(data, mimetype = 'application/json')
def __import_se_data(dump_file):
"""non-view function that imports the SE data