Permalink
Browse files

merged in latest Mikes changes

  • Loading branch information...
1 parent 96be321 commit 464c14f8e63cc1df409f2f72a1871d364d41b0d7 @evgenyfadeev evgenyfadeev committed Jul 27, 2009
View
@@ -0,0 +1,33 @@
+PRE-REQUIREMENTS:
+-----------------------------------------------
+1. Python2.5, MySQL, Django v1.0+
+
+2. Python-openid v2.2
+http://openidenabled.com/python-openid/
+
+3. django-authopenid(Included in project already)
+http://code.google.com/p/django-authopenid/
+
+4. html5lib
+http://code.google.com/p/html5lib/
+Used for HTML sanitizer
+
+5. Markdown2
+http://code.google.com/p/python-markdown2/
+
+
+INSTALL STEPS:
+-----------------------------------------------
+1. Copy settings_local.py.dist to settings_local.py and
+update all your settings. Check settings.py and update
+it as well if necessory.
+
+2. Prepare your database by using the same database/account
+configuration from above.
+
+3. Run "python manager.py runserver" to startup django
+development environment.
+
+4. There are some demo scripts under sql_scripts folder,
+including badges and test accounts for CNProg.com. You
+don't need them to run your sample.
View
@@ -1,12 +1,14 @@
-��Ȩ����(c) 2008 CNProg.com
+Copyright (C) 2009. Chen Gang
-���2.0�汾Apache���֤("���֤")��Ȩ��
-��ݱ����֤���û����Բ�ʹ�ô��ļ���
-�û��ɴ�������ַ������֤������
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
-http://www.apache.org/licenses/LICENSE-2.0
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
-��������÷�����Ҫ������ͬ�⣬
-������֤�ַ�������ǻ���"��ԭ��"���ṩ��
-���κ���ʾ�Ļ�ʾ�ı�֤�������
-��������֤����£��ض����ԵĹ�ϽȨ�޺����ơ�
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
View
@@ -0,0 +1,9 @@
+from django.conf import settings
+def application_settings(context):
+ return {
+ 'APP_TITLE' : settings.APP_TITLE,
+ 'APP_URL' : settings.APP_URL,
+ 'APP_KEYWORDS' : settings.APP_KEYWORDS,
+ 'APP_DESCRIPTION' : settings.APP_DESCRIPTION,
+ 'APP_INTRO' : settings.APP_INTRO
+ }
View
@@ -0,0 +1,30 @@
+# development
+
+==July 26 2009, Evgeny==
+
+django_authopenid:
+considerably changed user interface
+
+log/forum/forms.py:
+- added tag input validation using regex
+- fixed bug with date type mismatch near self.fields['birthday'] =
+ in EditUserForm.__init__()
+
+/forum/templatetags/extra_tags.py:
+- fixed date type mismatch in get_age()
+
+/templates/content/js/com.cnprog.post.js:
+- fixed bug with post deletion/recovery
+
+javascript:
+- changed to use of non-minified code - better for editing
+and debugging
+
+/templates/question.html:
+- fixed display of delete/undelete links
+
+templates:
+added comments in the beginning/end of each template
+for the debugging purposes - so that you know which template outputs what html
+<!-- user_favorites.html -->
+<!-- end user_favorites.html -->
@@ -3,7 +3,7 @@
from django.contrib.auth.models import User
from django.db import models
-import md5, random, sys, os, time
+import hashlib, random, sys, os, time
__all__ = ['Nonce', 'Association', 'UserAssociation',
'UserPasswordQueueManager', 'UserPasswordQueue']
@@ -47,7 +47,7 @@ def get_new_confirm_key(self):
# The random module is seeded when this Apache child is created.
# Use SECRET_KEY as added salt.
while 1:
- confirm_key = md5.new("%s%s%s%s" % (
+ confirm_key = hashlib.md5("%s%s%s%s" % (
random.randint(0, sys.maxint - 1), os.getpid(),
time.time(), settings.SECRET_KEY)).hexdigest()
try:
@@ -15,7 +15,7 @@
except:
from yadis import xri
-import time, base64, md5, operator
+import time, base64, hashlib, operator
import urllib
from models import Association, Nonce
@@ -128,7 +128,7 @@ def cleanupAssociations(self):
def getAuthKey(self):
# Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY
- return md5.new(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
+ return hashlib.md5(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
def isDumb(self):
return False
@@ -157,7 +157,8 @@ def first_type_award(self):
"""
activity_types = ','.join('%s' % item for item in BADGE_AWARD_TYPE_FIRST.keys())
# ORDER BY user_id, activity_type
- query = "SELECT id, user_id, activity_type, content_type_id, object_id FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types
+ query = "SELECT id, user_id, activity_type, content_type_id, object_id "+
+ "FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types
cursor = connection.cursor()
try:
@@ -205,7 +206,10 @@ def first_ask_be_voted(self):
(13, '学生', 3, '学生', '第一次提问并且有一次以上赞成票', 0, 0),
"""
- query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM activity act, question q WHERE act.activity_type = %s AND act.object_id = q.id AND act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13)
+ query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM "+
+ "activity act, question q WHERE act.activity_type = %s AND "+
+ "act.object_id = q.id AND "+
+ "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13)
cursor = connection.cursor()
try:
cursor.execute(query)
@@ -232,7 +236,10 @@ def first_answer_be_voted(self):
(15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0),
"""
- query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM activity act, answer a WHERE act.activity_type = %s AND act.object_id = a.id AND act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15)
+ query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM "+
+ "activity act, answer a WHERE act.activity_type = %s AND "+
+ "act.object_id = a.id AND "+
+ "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15)
cursor = connection.cursor()
try:
cursor.execute(query)
@@ -257,7 +264,11 @@ def first_answer_be_voted_10(self):
"""
(32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0)
"""
- query = "SELECT act.user_id, act.object_id FROM activity act, answer a WHERE act.object_id = a.id AND act.activity_type = %s AND a.vote_up_count >= 10 AND act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32)
+ query = "SELECT act.user_id, act.object_id FROM "+
+ "activity act, answer a WHERE act.object_id = a.id AND "+
+ "act.activity_type = %s AND "+
+ "a.vote_up_count >= 10 AND "+
+ "act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32)
cursor = connection.cursor()
try:
cursor.execute(query)
@@ -281,23 +292,35 @@ def vote_count_300(self):
"""
(26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0)
"""
- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26)
+ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
+ "activity_type = %s OR "+
+ "activity_type = %s AND "+
+ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
+ "GROUP BY user_id HAVING vote_count >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26)
self.__award_for_count_num(query, 26)
def edit_count_100(self):
"""
(27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0)
"""
- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27)
+ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
+ "activity_type = %s OR "+
+ "activity_type = %s AND "+
+ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
+ "GROUP BY user_id HAVING vote_count >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27)
self.__award_for_count_num(query, 27)
def comment_count_10(self):
"""
(5, '评论家', 3, '评论家', '评论10次以上', 0, 0),
"""
- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5)
+ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
+ "activity_type = %s OR "+
+ "activity_type = %s AND "+
+ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
+ "GROUP BY user_id HAVING vote_count >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5)
self.__award_for_count_num(query, 5)
def __award_for_count_num(self, query, badge):
View
@@ -4,8 +4,29 @@
from django.db import connection, models, transaction
from django.db.models import Q
from forum.models import *
+from urllib import quote, unquote
class QuestionManager(models.Manager):
+ def get_translation_questions(self, orderby, page_size):
+ questions = self.filter(deleted=False, author__id__in=[28,29]).order_by(orderby)[:page_size]
+ return questions
+
+ def get_questions_by_pagesize(self, orderby, page_size):
+ questions = self.filter(deleted=False).order_by(orderby)[:page_size]
+ return questions
+
+ def get_questions_by_tag(self, tagname, orderby):
+ questions = self.filter(deleted=False, tags__name = unquote(tagname)).order_by(orderby)
+ return questions
+
+ def get_unanswered_questions(self, orderby):
+ questions = self.filter(deleted=False, answer_count=0).order_by(orderby)
+ return questions
+
+ def get_questions(self, orderby):
+ questions = self.filter(deleted=False).order_by(orderby)
+ return questions
+
def update_tags(self, question, tagnames, user):
"""
Updates Tag associations for a question to match the given
@@ -92,7 +113,12 @@ class TagManager(models.Manager):
'WHERE tag_id = tag.id'
') '
'WHERE id IN (%s)')
-
+
+ def get_valid_tags(self, page_size):
+ from forum.models import Tag
+ tags = Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("-id")[:page_size]
+ return tags
+
def get_or_create_multiple(self, names, user):
"""
Fetches a list of Tags with the given names, creating any Tags
@@ -123,6 +149,19 @@ def update_use_counts(self, tags):
query = self.UPDATE_USED_COUNTS_QUERY % ','.join(['%s'] * len(tags))
cursor.execute(query, [tag.id for tag in tags])
transaction.commit_unless_managed()
+
+ def get_tags_by_questions(self, questions):
+ question_ids = []
+ for question in questions:
+ question_ids.append(question.id)
+
+ question_ids_str = ','.join([str(id) for id in question_ids])
+ related_tags = self.extra(
+ tables=['tag', 'question_tags'],
+ where=["tag.id = question_tags.tag_id AND question_tags.question_id IN (" + question_ids_str + ")"]
+ ).distinct()
+
+ return related_tags
class AnswerManager(models.Manager):
GET_ANSWERS_FROM_USER_QUESTIONS = u'SELECT answer.* FROM answer INNER JOIN question ON answer.question_id = question.id WHERE question.author_id =%s AND answer.author_id <> %s'
@@ -205,4 +244,16 @@ def get_reputation_by_upvoted_today(self, user):
return row[0]
else:
- return 0
+ return 0
+class AwardManager(models.Manager):
+ def get_recent_awards(self):
+ awards = super(AwardManager, self).extra(
+ select={'badge_id': 'badge.id', 'badge_name':'badge.name',
+ 'badge_description': 'badge.description', 'badge_type': 'badge.type',
+ 'user_id': 'auth_user.id', 'user_name': 'auth_user.username'
+ },
+ tables=['award', 'badge', 'auth_user'],
+ order_by=['-awarded_at'],
+ where=['auth_user.id=award.user_id AND badge_id=badge.id'],
+ ).values('badge_id', 'badge_name', 'badge_description', 'badge_type', 'user_id', 'user_name')
+ return awards
View
@@ -351,7 +351,8 @@ class Award(models.Model):
content_object = generic.GenericForeignKey('content_type', 'object_id')
awarded_at = models.DateTimeField(default=datetime.datetime.now)
notified = models.BooleanField(default=False)
-
+ objects = AwardManager()
+
def __unicode__(self):
return u'[%s] is awarded a badge [%s] at %s' % (self.user.username, self.badge.name, self.awarded_at)
@@ -1,4 +1,4 @@
-import time
+import time
import datetime
import math
import re
@@ -50,10 +50,10 @@ def tag_font_size(max_size, min_size, current_size):
weight = 0
return MIN_FONTSIZE + round((MAX_FONTSIZE - MIN_FONTSIZE) * weight)
-
+
LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 5
LEADING_PAGE_RANGE = TRAILING_PAGE_RANGE = 4
-NUM_PAGES_OUTSIDE_RANGE = 1
+NUM_PAGES_OUTSIDE_RANGE = 1
ADJACENT_PAGES = 2
@register.inclusion_tag("paginator.html")
def cnprog_paginator(context):
@@ -65,10 +65,10 @@ def cnprog_paginator(context):
" Initialize variables "
in_leading_range = in_trailing_range = False
pages_outside_leading_range = pages_outside_trailing_range = range(0)
-
+
if (context["pages"] <= LEADING_PAGE_RANGE_DISPLAYED):
in_leading_range = in_trailing_range = True
- page_numbers = [n for n in range(1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
+ page_numbers = [n for n in range(1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
elif (context["page"] <= LEADING_PAGE_RANGE):
in_leading_range = True
page_numbers = [n for n in range(1, LEADING_PAGE_RANGE_DISPLAYED + 1) if n > 0 and n <= context["pages"]]
@@ -77,11 +77,11 @@ def cnprog_paginator(context):
in_trailing_range = True
page_numbers = [n for n in range(context["pages"] - TRAILING_PAGE_RANGE_DISPLAYED + 1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)]
- else:
+ else:
page_numbers = [n for n in range(context["page"] - ADJACENT_PAGES, context["page"] + ADJACENT_PAGES + 1) if n > 0 and n <= context["pages"]]
pages_outside_leading_range = [n + context["pages"] for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)]
pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)]
-
+
extend_url = context.get('extend_url', '')
return {
"base_url": context["base_url"],
@@ -205,12 +205,12 @@ def format_number(value):
m = re.match(pattern, strValue)
return first + result
-@register.simple_tag
+@register.simple_tag
def convert2tagname_list(question):
question['tagnames'] = [name for name in question['tagnames'].split(u' ')]
return ''
-@register.simple_tag
+@register.simple_tag
def diff_date(date, limen=2):
current_time = datetime.datetime(*time.localtime()[0:6])
diff = current_time - date
@@ -237,4 +237,4 @@ def get_latest_changed_timestamp():
timestr = strftime("%H:%M %b-%d-%Y %Z", localtime(latest))
except:
timestr = ''
- return timestr
+ return timestr
View
@@ -1,3 +1,4 @@
+# coding=utf-8
from django.utils.translation import ugettext as _
class UserView:
def __init__(self, id, tab_title, tab_description, page_title, view_name, template_file, data_size=0):
Oops, something went wrong.

0 comments on commit 464c14f

Please sign in to comment.