summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-04-16 08:11:18 -0500
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-04-16 08:11:18 -0500
commitca08230d3dca4d55d93336ac641a820f7d643e7d (patch)
treed84b8bc26cf27b81b3de13fcbd6a345971c56173
parent511a7e1d9a7b1ed2fa60c3a58e0191f975384c6d (diff)
parentca5efbe3667058e2bfd36403c1236819f954ee40 (diff)
downloadaskbot-ca08230d3dca4d55d93336ac641a820f7d643e7d.tar.gz
askbot-ca08230d3dca4d55d93336ac641a820f7d643e7d.tar.bz2
askbot-ca08230d3dca4d55d93336ac641a820f7d643e7d.zip
merged in bug fixes from the master branch
-rwxr-xr-x.gitignore1
-rw-r--r--MANIFEST.in3
-rw-r--r--askbot/__init__.py4
-rw-r--r--askbot/auth.py42
-rw-r--r--askbot/conf/license.py2
-rw-r--r--askbot/deps/django_authopenid/forms.py2
-rw-r--r--askbot/doc/source/changelog.rst6
-rw-r--r--askbot/doc/source/contributors.rst1
-rw-r--r--askbot/search/state_manager.py5
-rw-r--r--askbot/setup_templates/settings.py2
-rw-r--r--askbot/setup_templates/settings.py.mustache2
-rw-r--r--askbot/skins/common/media/jquery-openid/openid.css3
-rw-r--r--askbot/skins/common/templates/authopenid/authopenid_macros.html77
-rw-r--r--askbot/skins/common/templates/authopenid/email_validation.txt2
-rw-r--r--askbot/skins/common/templates/authopenid/signin.html17
-rw-r--r--askbot/skins/common/templates/widgets/related_tags.html8
-rw-r--r--askbot/skins/default/templates/macros.html8
-rw-r--r--askbot/skins/default/templates/revisions.html2
-rw-r--r--askbot/skins/default/templates/tags.html2
-rw-r--r--askbot/startup_procedures.py4
-rw-r--r--askbot/views/meta.py9
-rw-r--r--askbot/views/readers.py5
-rw-r--r--askbot/views/users.py4
-rw-r--r--askbot_requirements.txt2
-rw-r--r--askbot_requirements_dev.txt2
25 files changed, 141 insertions, 74 deletions
diff --git a/.gitignore b/.gitignore
index 586c4c8a..07a3f84f 100755
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ lint
env
/static
django
+lamson
django/*
nbproject
pip-log.txt
diff --git a/MANIFEST.in b/MANIFEST.in
index 72c4fd65..cce28976 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -11,6 +11,9 @@ recursive-exclude .git
prune dist
prune tmp
prune build
+prune static
+prune django
+prune lamson
exclude db
exclude lint
exclude settings.py
diff --git a/askbot/__init__.py b/askbot/__init__.py
index af9603e1..f861033d 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -9,13 +9,13 @@ import smtplib
import sys
import logging
-VERSION = (0, 7, 39)
+VERSION = (0, 7, 40)
#keys are module names used by python imports,
#values - the package qualifier to use for pip
REQUIREMENTS = {
'akismet': 'akismet',
- 'django': 'django>=1.1.2',
+ 'django': 'django==1.3.1',
'jinja2': 'Jinja2',
'coffin': 'Coffin>=0.3',
'south': 'South>=0.7.1',
diff --git a/askbot/auth.py b/askbot/auth.py
index 5c0f7bd9..eba24c80 100644
--- a/askbot/auth.py
+++ b/askbot/auth.py
@@ -199,6 +199,11 @@ def onAnswerAccept(answer, user, timestamp=None):
reputation=answer.author.reputation)
reputation.save()
+ if answer.author == question.author and user == question.author:
+ #a plug to prevent reputation gaming by posting a question
+ #then answering and accepting as best all by the same person
+ return
+
user.receive_reputation(askbot_settings.REP_GAIN_FOR_ACCEPTING_ANSWER)
user.save()
reputation = Repute(user=user,
@@ -214,24 +219,29 @@ def onAnswerAcceptCanceled(answer, user, timestamp=None):
if timestamp is None:
timestamp = datetime.datetime.now()
answer.thread.set_accepted_answer(answer=None, timestamp=None)
-
- answer.author.receive_reputation(
- askbot_settings.REP_LOSS_FOR_RECEIVING_CANCELATION_OF_ANSWER_ACCEPTANCE
- )
- answer.author.save()
-
question = answer.thread._question_post()
- reputation = Repute(
- user=answer.author,
- negative=\
- askbot_settings.REP_LOSS_FOR_RECEIVING_CANCELATION_OF_ANSWER_ACCEPTANCE,
- question=question,
- reputed_at=timestamp,
- reputation_type=-2,
- reputation=answer.author.reputation
- )
- reputation.save()
+ if user != answer.author:
+ answer.author.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_RECEIVING_CANCELATION_OF_ANSWER_ACCEPTANCE
+ )
+ answer.author.save()
+ reputation = Repute(
+ user=answer.author,
+ negative=\
+ askbot_settings.REP_LOSS_FOR_RECEIVING_CANCELATION_OF_ANSWER_ACCEPTANCE,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-2,
+ reputation=answer.author.reputation
+ )
+ reputation.save()
+
+ if answer.author == question.author and user == question.author:
+ #a symmettric measure for the reputation gaming plug
+ #as in the onAnswerAccept function
+ #here it protects the user from uwanted reputation loss
+ return
user.receive_reputation(
askbot_settings.REP_LOSS_FOR_CANCELING_ANSWER_ACCEPTANCE
diff --git a/askbot/conf/license.py b/askbot/conf/license.py
index faf50697..453213c4 100644
--- a/askbot/conf/license.py
+++ b/askbot/conf/license.py
@@ -10,7 +10,7 @@ from django.conf import settings as django_settings
LICENSE_SETTINGS = livesettings.ConfigurationGroup(
'LICENSE_SETTINGS',
- _('Content LicensContent License'),
+ _('Content License'),
super_group = CONTENT_AND_UI
)
diff --git a/askbot/deps/django_authopenid/forms.py b/askbot/deps/django_authopenid/forms.py
index 8e6ce528..db2afcd8 100644
--- a/askbot/deps/django_authopenid/forms.py
+++ b/askbot/deps/django_authopenid/forms.py
@@ -392,7 +392,7 @@ class AccountRecoveryForm(forms.Form):
if 'email' in self.cleaned_data:
email = self.cleaned_data['email']
try:
- user = User.objects.get(email=email)
+ user = User.objects.get(email__iexact=email)
self.cleaned_data['user'] = user
except User.DoesNotExist:
del self.cleaned_data['email']
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index 5a1b6482..eb1cd591 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -8,8 +8,8 @@ Future version
* Enabling/disabling the badges system (Evgeny)
* Created a basic post moderation feature (Evgeny)
-0.7.40
-------
+0.7.40 (March 29, 2012)
+-----------------------
* New data models!!! (`Tomasz Zieliński <http://pyconsultant.eu>`_)
* 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)
@@ -32,6 +32,8 @@ Future version
* Added "reply by email" function (`Vasil Vangelovski <http://www.atomidata.com>`_)
* Enabled "ask by email" via Lamson (Evgeny)
* Tags can be optional (Evgeny)
+* Fixed dependency of Django up to 1.3.1, because settings must be upgraded
+ for Django 1.4 (Evgeny)
0.7.39 (Jan 11, 2012)
---------------------
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
index caa07a08..71bc5cc9 100644
--- a/askbot/doc/source/contributors.rst
+++ b/askbot/doc/source/contributors.rst
@@ -37,6 +37,7 @@ Programming and documentation
* `Jacob Oscarson <http://www.aspektratio.net>`_
* `Radim Řehůřek <https://github.com/piskvorky>`_
* `monkut <https://github.com/monkut>`_
+* `Jim Tittsler <http://wikieducator.org/User:JimTittsler>`_
Translations
------------
diff --git a/askbot/search/state_manager.py b/askbot/search/state_manager.py
index ee46501e..8096cbdd 100644
--- a/askbot/search/state_manager.py
+++ b/askbot/search/state_manager.py
@@ -241,8 +241,13 @@ class SearchState(object):
class DummySearchState(object): # Used for caching question/thread summaries
+
def add_tag(self, tag):
self.tag = tag
return self
+
+ def change_scope(self, new_scope):
+ return self
+
def full_url(self):
return '<<<%s>>>' % self.tag
diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py
index b1d7dd06..f9920bca 100644
--- a/askbot/setup_templates/settings.py
+++ b/askbot/setup_templates/settings.py
@@ -226,3 +226,5 @@ CSRF_COOKIE_NAME = 'askbot_csrf'
#CSRF_COOKIE_DOMAIN = ''
STATICFILES_DIRS = ( os.path.join(ASKBOT_ROOT, 'skins'),)
+
+RECAPTCHA_USE_SSL = True
diff --git a/askbot/setup_templates/settings.py.mustache b/askbot/setup_templates/settings.py.mustache
index 855e6294..e39231f0 100644
--- a/askbot/setup_templates/settings.py.mustache
+++ b/askbot/setup_templates/settings.py.mustache
@@ -227,3 +227,5 @@ CSRF_COOKIE_NAME = '{{domain_name}}_csrf'
STATIC_ROOT = os.path.join(PROJECT_ROOT, "static")
STATICFILES_DIRS = (os.path.join(ASKBOT_ROOT, 'skins'),)
+
+RECAPTCHA_USE_SSL = True
diff --git a/askbot/skins/common/media/jquery-openid/openid.css b/askbot/skins/common/media/jquery-openid/openid.css
index 00287224..f9430108 100644
--- a/askbot/skins/common/media/jquery-openid/openid.css
+++ b/askbot/skins/common/media/jquery-openid/openid.css
@@ -1,7 +1,8 @@
-div#login-icons {margin:10px 0 0 0;padding:10px;border:#eee 1px solid;}
+div#login-icons {padding:20px 0 0 0;}
ul.login-icons {width: 450px; margin:0;padding:0;text-align:left; list-style-type:none; display:block;}
ul.login-icons li {display:inline;}
ul.large input {height: 40px; width: 90px;border:1px solid #ccc;margin:0 5px 5px 0;}
+.openid-signin h1 {margin-top: -15px; padding-bottom: 10px;}
.openid-signin h2 {margin-top:15px;}
.openid-signin h2#account-recovery-heading {margin-bottom:2px;}
#account-recovery-form p.hint a {color:#1b79bd; text-decoration: none;}
diff --git a/askbot/skins/common/templates/authopenid/authopenid_macros.html b/askbot/skins/common/templates/authopenid/authopenid_macros.html
index 477d277c..9d35ac6f 100644
--- a/askbot/skins/common/templates/authopenid/authopenid_macros.html
+++ b/askbot/skins/common/templates/authopenid/authopenid_macros.html
@@ -15,44 +15,55 @@
minor_login_providers = None,
hide_local_login = False,
settings = None,
- logged_in = False
+ logged_in = False,
+ show_buttons = True
)
%}
- <div id="login-icons">
- <ul class="login-icons large">
- {% for login_provider in major_login_providers %}
- {% if login_provider.name == 'local' and hide_local_login == True %}
- {# do nothing here, left if statement this way for simplicity #}
- {% else %}
- {% if logged_in == True and login_provider.type == 'password' and login_provider.password_changeable == False %}
+ {% if show_buttons == True %}{# a hack #}
+ <div id="login-icons">
+ {% if major_login_providers %}
+ <ul class="login-icons large">
+ {% for login_provider in major_login_providers %}
+ {% if login_provider.name == 'local' and hide_local_login == True %}
+ {# do nothing here, left if statement this way for simplicity #}
+ {% else %}
+ {% if logged_in == True and login_provider.type == 'password'
+ and login_provider.password_changeable == False
+ %}
+ {% else %}
+ <li>
+ {{ login_provider_input(login_provider) }}
+ </li>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% if minor_login_providers %}
+ <ul class="login-icons small">
+ {% for login_provider in minor_login_providers %}
+ {% if logged_in == True and login_provider.type == 'password'
+ and login_provider.password_changeable == False
+ %}
{% else %}
<li>
{{ login_provider_input(login_provider) }}
</li>
{% endif %}
- {% endif %}
- {% endfor %}
- </ul>
- <ul class="login-icons small">
- {% for login_provider in minor_login_providers %}
- {% if logged_in == True and login_provider.type == 'password' and login_provider.password_changeable == False %}
- {% else %}
- <li>
- {{ login_provider_input(login_provider) }}
- </li>
- {% endif %}
- {% endfor %}
- </ul>
- </div>
- <fieldset
- id="openid-fs"
- {% if not login_form.openid_login_token.errors %}
- style="display:none;"
- {% endif %}
- >
- <h2 id="openid-heading">{% trans %}Please enter your <span>user name</span>, then sign in{% endtrans %}</h2>
- <p class="hint">{% trans %}(or select another login method above){% endtrans %}</p>
- <input type="text" name="openid_login_token" />
- <input class="submit-b" type="submit" name="openid_login_with_extra_token" value="{% trans %}Sign in{% endtrans %}"/>
- </fieldset>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+ <fieldset
+ id="openid-fs"
+ {% if not login_form.openid_login_token.errors %}
+ style="display:none;"
+ {% endif %}
+ >
+ <h2 id="openid-heading">{% trans %}Please enter your <span>user name</span>, then sign in{% endtrans %}</h2>
+ <p class="hint">{% trans %}(or select another login method above){% endtrans %}</p>
+ <input type="text" name="openid_login_token" />
+ <input class="submit-b" type="submit" name="openid_login_with_extra_token" value="{% trans %}Sign in{% endtrans %}"/>
+ </fieldset>
+ {% endif %}
{% endmacro %}
diff --git a/askbot/skins/common/templates/authopenid/email_validation.txt b/askbot/skins/common/templates/authopenid/email_validation.txt
index 4a58ab86..bd68c61a 100644
--- a/askbot/skins/common/templates/authopenid/email_validation.txt
+++ b/askbot/skins/common/templates/authopenid/email_validation.txt
@@ -7,7 +7,7 @@
{% trans %}Following the link above will help us verify your email address.{% endtrans %}
{% trans %}If you believe that this message was sent in mistake -
-no further action is needed. Just ingore this email, we apologize
+no further action is needed. Just ignore this email, we apologize
for any inconvenience{% endtrans %}
{% trans %}Sincerely,
diff --git a/askbot/skins/common/templates/authopenid/signin.html b/askbot/skins/common/templates/authopenid/signin.html
index 3b522d9b..f9c0cfea 100644
--- a/askbot/skins/common/templates/authopenid/signin.html
+++ b/askbot/skins/common/templates/authopenid/signin.html
@@ -26,7 +26,7 @@
{% endif %}
<p id='login-intro'>
{% if view_subtype == 'default' and have_buttons %}
- {% trans %}Take a pick of your favorite service below to sign in using secure OpenID or similar technology. Your external service password always stays confidential and you don't have to rememeber or create another one.{% endtrans %}
+ {% trans %}Choose your favorite service below to sign in using secure OpenID or similar technology. Your external service password always stays confidential and you don't have to rememeber or create another one.{% endtrans %}
{% elif view_subtype == 'add_openid' and have_buttons %}
{% if existing_login_methods %}
{% trans %}It's a good idea to make sure that your existing login methods still work, or add a new one. Please click any of the icons below to check/change or add new login methods.{% endtrans %}
@@ -62,7 +62,8 @@
minor_login_providers = minor_login_providers,
hide_local_login = settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN,
settings = settings,
- logged_in = user.is_authenticated()
+ logged_in = user.is_authenticated(),
+ show_buttons = have_buttons
)
}}
{% if use_password_login == True %}
@@ -84,9 +85,15 @@
>
{{login_form.password_action}}
{% if user.is_anonymous() %}
- <h2 id="password-heading">
- {% trans %}Please enter your <span>user name and password</span>, then sign in{% endtrans %}
- </h2>
+ {% if have_buttons %}
+ <h2 id="password-heading">
+ {% trans %}or enter your <span>user name and password</span>, then sign in{% endtrans %}
+ </h2>
+ {% else %}
+ <h1 class="section-title">
+ {% trans %}Please, sign in{% endtrans %}
+ </h1>
+ {% endif %}
{% if have_buttons %}
<p class="hint">{% trans %}(or select another login method above){% endtrans %}</p>
{% endif %}
diff --git a/askbot/skins/common/templates/widgets/related_tags.html b/askbot/skins/common/templates/widgets/related_tags.html
index 39873437..05520998 100644
--- a/askbot/skins/common/templates/widgets/related_tags.html
+++ b/askbot/skins/common/templates/widgets/related_tags.html
@@ -16,7 +16,13 @@
{% endfor %}
</ul>
{% else %}
- {{ macros.tag_cloud(tags = tags, font_sizes = font_size) }}
+ {{
+ macros.tag_cloud(
+ tags = tags,
+ font_sizes = font_size,
+ search_state = search_state
+ )
+ }}
{% endif %}
</div>
{% endcache %}
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index d67cf7cd..39562ef5 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -180,10 +180,14 @@ poor design of the data or methods on data objects #}
{%- endif -%}
{%- endmacro -%}
-{%- macro tag_cloud(tags = None, font_sizes = None) -%}
+{%- macro tag_cloud(tags = None, font_sizes = None, search_state = None) -%}
{% for tag in tags %}
<span class="tag-size-{{ font_sizes[tag.name] }}">
- <a class="link-typeA" title="Number of entries: {{ tag.used_count }}" href="{% url questions %}?tags={{ tag.name }}">{{ tag.name }}</a>
+ <a
+ class="link-typeA"
+ title="Number of entries: {{ tag.used_count }}"
+ href="{{ search_state.add_tag(tag.name).full_url() }}"
+ >{{ tag.name }}</a>
</span>
{% endfor %}
{%- endmacro -%}
diff --git a/askbot/skins/default/templates/revisions.html b/askbot/skins/default/templates/revisions.html
index 07b98b5b..fd7dbf0c 100644
--- a/askbot/skins/default/templates/revisions.html
+++ b/askbot/skins/default/templates/revisions.html
@@ -19,7 +19,7 @@
<td width="20" style="vertical-align:middle">
<img
id="rev-arrow-{{ revision.revision }}"
- src="{{"/images/expander-arrow-show.gif"|media}}"
+ src="{{"/images/expander-arrow-hide.gif"|media}}"
alt="{% trans %}click to hide/show revision{% endtrans %}"
/>
</td>
diff --git a/askbot/skins/default/templates/tags.html b/askbot/skins/default/templates/tags.html
index 0f0c1fc6..2bd4b2ec 100644
--- a/askbot/skins/default/templates/tags.html
+++ b/askbot/skins/default/templates/tags.html
@@ -55,7 +55,7 @@
{% if not tags %}
<span>{% trans %}Nothing found{% endtrans %}</span>
{% endif %}
- {{ macros.tag_cloud(tags = tags, font_sizes = font_size) }}
+ {{ macros.tag_cloud(tags = tags, font_sizes = font_size, search_state = search_state) }}
{% endif %}
{% endblock %}
diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py
index b4b36e35..e890fb89 100644
--- a/askbot/startup_procedures.py
+++ b/askbot/startup_procedures.py
@@ -508,6 +508,10 @@ def run_startup_tests():
'test_for_absence': True,
'message': 'Please replace setting ASKBOT_UPLOADED_FILES_URL ',
'replace_hint': "with MEDIA_URL = '/%s'"
+ },
+ 'RECAPTCHA_USE_SSL': {
+ 'value': True,
+ 'message': 'Please add: RECAPTCHA_USE_SSL = True'
}
})
settings_tester.run()
diff --git a/askbot/views/meta.py b/askbot/views/meta.py
index f288e3fe..3e5a0b35 100644
--- a/askbot/views/meta.py
+++ b/askbot/views/meta.py
@@ -37,6 +37,7 @@ def about(request, template='about.html'):
title = _('About %(site)s') % {'site': askbot_settings.APP_SHORT_NAME}
data = {
'title': title,
+ 'page_class': 'meta',
'content': askbot_settings.FORUM_ABOUT
}
return render_into_skin('static_page.html', data, request)
@@ -56,9 +57,14 @@ def help(request):
def faq(request):
if askbot_settings.FORUM_FAQ.strip() != '':
+ data = {
+ 'title': _('FAQ'),
+ 'content': askbot_settings.FORUM_FAQ,
+ 'page_class': 'meta',
+ }
return render_into_skin(
'static_page.html',
- {'title': _('FAQ'), 'content': askbot_settings.FORUM_FAQ},
+ data,
request
)
else:
@@ -98,6 +104,7 @@ feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, giv
def privacy(request):
data = {
'title': _('Privacy policy'),
+ 'page_class': 'meta',
'content': askbot_settings.FORUM_PRIVACY
}
return render_into_skin('static_page.html', data, request)
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index 57664e37..9bb6495d 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -34,7 +34,7 @@ from askbot.models.tag import Tag
from askbot import const
from askbot.utils import functions
from askbot.utils.decorators import anonymous_forbidden, ajax_only, get_only
-from askbot.search.state_manager import SearchState
+from askbot.search.state_manager import SearchState, DummySearchState
from askbot.templatetags import extra_tags
import askbot.conf
from askbot.conf import settings as askbot_settings
@@ -295,6 +295,7 @@ def tags(request):#view showing a listing of available tags - plain list
'stag' : stag,
'tab_id' : sortby,
'keywords' : stag,
+ 'search_state': SearchState(*[None for x in range(7)])
}
return render_into_skin('tags.html', data, request)
@@ -525,7 +526,7 @@ def question(request, id):#refactor - long subroutine. display question body, an
)
data = {
- 'is_cacheable': is_cacheable,
+ 'is_cacheable': False,#is_cacheable, #temporary, until invalidation fix
'long_time': const.LONG_TIME,#"forever" caching
'page_class': 'question-page',
'active_tab': 'questions',
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 33a801bd..61273e95 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -40,7 +40,7 @@ from askbot.models.badges import award_badges_signal
from askbot.skins.loaders import render_into_skin
from askbot.templatetags import extra_tags
from askbot.search.state_manager import SearchState
-
+from askbot.utils import url_utils
def owner_or_moderator_required(f):
@functools.wraps(f)
@@ -51,7 +51,7 @@ def owner_or_moderator_required(f):
pass
else:
params = '?next=%s' % request.path
- return HttpResponseRedirect(reverse('user_signin') + params)
+ return HttpResponseRedirect(url_utils.get_login_url() + params)
return f(request, profile_owner, context)
return wrapped_func
diff --git a/askbot_requirements.txt b/askbot_requirements.txt
index c82f17f0..7b619c36 100644
--- a/askbot_requirements.txt
+++ b/askbot_requirements.txt
@@ -1,5 +1,5 @@
akismet
-django>=1.1.2
+django==1.3.1
Jinja2
Coffin>=0.3
South>=0.7.1
diff --git a/askbot_requirements_dev.txt b/askbot_requirements_dev.txt
index e725252c..ada0d83e 100644
--- a/askbot_requirements_dev.txt
+++ b/askbot_requirements_dev.txt
@@ -1,5 +1,5 @@
akismet
-django>=1.1.2
+django==1.3.1
Jinja2
Coffin>=0.3
South>=0.7.1