From: hernani Date: Fri, 7 May 2010 01:15:39 +0000 (+0000) Subject: Merging the experimental branch back to trunk. X-Git-Tag: live~973 X-Git-Url: https://git.openstreetmap.org./osqa.git/commitdiff_plain/410bfa05ee36ed1d99356c443a5f3f6aa3ee9578 Merging the experimental branch back to trunk. git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@156 0cfe37f9-358a-4d5e-be75-b63607b5c754 --- diff --git a/forum/actions/__init__.py b/forum/actions/__init__.py new file mode 100644 index 0000000..a681069 --- /dev/null +++ b/forum/actions/__init__.py @@ -0,0 +1,3 @@ +from meta import * +from node import * +from user import * \ No newline at end of file diff --git a/forum/actions/meta.py b/forum/actions/meta.py new file mode 100644 index 0000000..a45fe58 --- /dev/null +++ b/forum/actions/meta.py @@ -0,0 +1,207 @@ +from django.utils.translation import ugettext as _ +from django.db.models import F +from forum.models.action import ActionProxy, DummyActionProxy +from forum.models import Vote, Flag +import settings + +class VoteAction(ActionProxy): + def update_node_score(self, inc): + self.node.score = F('score') + inc + self.node.save() + + def process_vote_action(self, value): + self.update_node_score(value) + vote = Vote(node=self.node, user=self.user, action=self, value=value) + vote.save() + + def cancel_action(self): + vote = self.vote.all()[0] + self.update_node_score(-vote.value) + vote.delete() + + @classmethod + def get_for(cls, user, node): + try: + vote = Vote.objects.get(user=user, node=node) + return vote.value + except: + return None + + def describe_vote(self, vote_desc, viewer=None): + return _("%(user)s %(vote_desc)s %(post_desc)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'vote_desc': vote_desc, 'post_desc': self.describe_node(viewer, self.node) + } + + +class VoteUpAction(VoteAction): + def repute_users(self): + self.repute(self.node.author, int(settings.REP_GAIN_BY_UPVOTED)) + + def process_action(self): + self.process_vote_action(1) + self.user.reset_vote_up_count_cache() + + def cancel_action(self): + super(VoteUpAction, self).cancel_action() + self.user.reset_vote_up_count_cache() + + def describe(self, viewer=None): + return self.describe_vote(_("voted up"), viewer) + +class VoteDownAction(VoteAction): + def repute_users(self): + self.repute(self.node.author, -int(settings.REP_LOST_BY_DOWNVOTED)) + self.repute(self.user, -int(settings.REP_LOST_BY_DOWNVOTING)) + + def process_action(self): + self.process_vote_action(-1) + self.user.reset_vote_down_count_cache() + + def cancel_action(self): + super(VoteDownAction, self).cancel_action() + self.user.reset_vote_down_count_cache() + + def describe(self, viewer=None): + return self.describe_vote(_("voted down"), viewer) + + +class VoteUpCommentAction(VoteUpAction): + def repute_users(self): + pass + + def process_action(self): + self.process_vote_action(1) + + def cancel_action(self): + super(VoteUpAction, self).cancel_action() + + def describe(self, viewer=None): + return self.describe_vote(_("liked"), viewer) + + +class FlagAction(ActionProxy): + def repute_users(self): + self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED)) + + def process_action(self): + flag = Flag(user=self.user, node=self.node, action=self, reason=self.extra) + flag.save() + self.node.reset_flag_count_cache() + + if self.node.flag_count == int(settings.FLAG_COUNT_TO_HIDE_POST): + self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_3_TIMES)) + + if self.node.flag_count == int(settings.FLAG_COUNT_TO_DELETE_POST): + self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_5_TIMES)) + if not self.node.deleted: + DeleteAction(node=self.node, user=self.user, extra="BYFLAGGED").save() + + def cancel_action(self): + self.flag.all()[0].delete() + self.node.reset_flag_count_cache() + + @classmethod + def get_for(cls, user, node): + try: + flag = Flag.objects.get(user=user, node=node) + return flag.reason or _("No reason given") + except: + return None + + def describe(self, viewer=None): + return _("%(user)s flagged %(post_desc)s: %(reason)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node), 'reason': self.extra + } + + +class AcceptAnswerAction(ActionProxy): + def repute_users(self): + if (self.user == self.node.parent.author) and (not self.user == self.node.author): + self.repute(self.user, int(settings.REP_GAIN_BY_ACCEPTING)) + + if self.user != self.node.author: + self.repute(self.node.author, int(settings.REP_GAIN_BY_ACCEPTED)) + + def process_action(self): + self.node.parent.extra_ref = self.node + self.node.parent.save() + self.node.marked = True + self.node.extra_action = self + self.node.save() + + def cancel_action(self): + self.node.parent.extra_ref = None + self.node.parent.save() + self.node.marked = False + self.node.extra_action = None + self.node.save() + + def describe(self, viewer=None): + answer = self.node + question = answer.parent + + if self.user == question.author: + asker = (self.user == viewer) and _("your") or _("his") + else: + asker = self.hyperlink(question.author.get_profile_url(), question.author.username) + + return _("%(user)s accepted %(answerer)s answer on %(asker)s question %(question)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'answerer': self.hyperlink(answer.author.get_profile_url(), self.friendly_username(viewer, answer.author)), + 'asker': asker, + 'question': self.hyperlink(question.get_absolute_url(), question.title) + } + + +class FavoriteAction(ActionProxy): + def process_action(self): + self.node.reset_favorite_count_cache() + + def cancel_action(self): + self.process_action() + + def describe(self, viewer=None): + return _("%(user)s marked %(post_desc)s as favorite") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node), + } + + +class DeleteAction(ActionProxy): + def process_action(self): + self.node.deleted = self + self.node.save() + + if self.node.node_type == "answer": + self.node.question.reset_answer_count_cache() + + def cancel_action(self): + self.node.deleted = None + self.node.save() + + if self.node.node_type == "answer": + self.node.question.reset_answer_count_cache() + + def describe(self, viewer=None): + return _("%(user)s deleted %(post_desc)s: %(reason)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node), 'reason': self.reason(), + } + + def reason(self): + if self.extra != "BYFLAGGED": + return self.extra + else: + return _("flagged by multiple users: ") + "; ".join([f.extra for f in FlagAction.objects.filter(node=self.node)]) + + +class QuestionViewAction(DummyActionProxy): + def __init__(self, question, user): + self.viewuser = user + self.question = question + + def process_action(self): + self.question.extra_count = F('extra_count') + 1 + self.question.save() diff --git a/forum/actions/node.py b/forum/actions/node.py new file mode 100644 index 0000000..d7f9383 --- /dev/null +++ b/forum/actions/node.py @@ -0,0 +1,115 @@ +from django.utils.html import strip_tags +from django.utils.translation import ugettext as _ +from forum.models.action import ActionProxy +from forum.models import Comment, Question, Answer, NodeRevision + +class NodeEditAction(ActionProxy): + def create_revision_data(self, initial=False, **data): + revision_data = dict(summary=data.get('summary', (initial and _('Initial revision' or ''))), body=data['text']) + + if data.get('title', None): + revision_data['title'] = strip_tags(data['title'].strip()) + + if data.get('tags', None): + revision_data['tagnames'] = data['tags'].strip() + + return revision_data + +class AskAction(NodeEditAction): + def process_data(self, **data): + question = Question(author=self.user, **self.create_revision_data(True, **data)) + question.save() + self.node = question + + def describe(self, viewer=None): + return _("%(user)s asked %(question)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'question': self.hyperlink(self.node.get_absolute_url(), self.node.title) + } + +class AnswerAction(NodeEditAction): + def process_data(self, **data): + answer = Answer(author=self.user, parent=data['question'], **self.create_revision_data(True, **data)) + answer.save() + self.node = answer + + def process_action(self): + self.node.question.reset_answer_count_cache() + + def describe(self, viewer=None): + question = self.node.parent + return _("%(user)s answered %(asker)s %(question)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'asker': self.hyperlink(question.author.get_profile_url(), self.friendly_username(viewer, question.author)), + 'question': self.hyperlink(self.node.get_absolute_url(), question.title) + } + +class CommentAction(ActionProxy): + def process_data(self, text='', parent=None): + comment = Comment(author=self.user, parent=parent, body=text) + comment.save() + self.node = comment + + def describe(self, viewer=None): + return _("%(user)s commented on %(post_desc)s") % { + 'user': self.hyperlink(self.node.author.get_profile_url(), self.friendly_username(viewer, self.node.author)), + 'post_desc': self.describe_node(viewer, self.node.parent) + } + +class ReviseAction(NodeEditAction): + def process_data(self, **data): + revision_data = self.create_revision_data(**data) + revision = self.node.create_revision(self.user, action=self, **revision_data) + self.extra = revision.revision + + def describe(self, viewer=None): + return _("%(user)s edited %(post_desc)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node) + } + +class RetagAction(ActionProxy): + def process_data(self, tagnames=''): + active = self.node.active_revision + revision_data = dict(summary=_('Retag'), title=active.title, tagnames=strip_tags(tagnames.strip()), body=active.body) + self.node.create_revision(self.user, action=self, **revision_data) + + def describe(self, viewer=None): + return _("%(user)s retagged %(post_desc)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node) + } + +class RollbackAction(ActionProxy): + def process_data(self, activate=None): + previous = self.node.active_revision + self.node.activate_revision(self.user, activate, self) + self.extra = "%d:%d" % (previous.revision, activate.revision) + + def describe(self, viewer=None): + revisions = [NodeRevision.objects.get(node=self.node, revision=int(n)) for n in self.extra.split(':')] + + return _("%(user)s reverted %(post_desc)s from revision %(initial)d (%(initial_sum)s) to revision %(final)d (%(final_sum)s)") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node), + 'initial': revisions[0].revision, 'initial_sum': revisions[0].summary, + 'final': revisions[1].revision, 'final_sum': revisions[1].summary, + } + +class CloseAction(ActionProxy): + def process_action(self): + self.node.extra_action = self + self.node.marked = True + self.node.save() + + def cancel_action(self): + self.node.extra_action = None + self.node.marked = False + self.node.save() + + def describe(self, viewer=None): + return _("%(user)s closed %(post_desc)s: %(reason)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'post_desc': self.describe_node(viewer, self.node), + 'reason': self.extra + } \ No newline at end of file diff --git a/forum/actions/user.py b/forum/actions/user.py new file mode 100644 index 0000000..2695f9f --- /dev/null +++ b/forum/actions/user.py @@ -0,0 +1,53 @@ +from django.utils.translation import ugettext as _ +from django.db.models import F +from forum.models.action import ActionProxy +from forum.models import Award +from forum import settings + +class UserJoinsAction(ActionProxy): + def repute_users(self): + self.repute(self.user, int(settings.INITIAL_REP)) + +class EditProfileAction(ActionProxy): + pass + +class AwardAction(ActionProxy): + def process_data(self, badge, trigger): + self.__dict__['_badge'] = badge + self.__dict__['_trigger'] = trigger + + def process_action(self): + badge = self.__dict__['_badge'] + trigger = self.__dict__['_trigger'] + + award = Award(user=self.user, badge=badge, trigger=trigger, action=self) + if self.node: + award.node = self.node + + award.save() + award.badge.awarded_count = F('awarded_count') + 1 + award.badge.save() + self.user.message_set.create(message=_("Congratulations, you have received a badge '%(badge_name)s'. " \ + + u"Check out your profile.") % dict(badge_name=award.badge.name, + profile_url=self.user.get_profile_url())) + + def cancel_action(self): + award = self.award + badge = award.badge + badge.awarded_count = F('awarded_count') - 1 + badge.save() + award.delete() + + @classmethod + def get_for(cls, user, node, badge): + try: + award = Award.objects.get(user=user, node=node, badge=badge) + return award.action + except: + return None + + def describe(self, viewer=None): + return _("%(user)s was awarded the %(badge_name)s badge") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'badge_name': self.award.all()[0].badge.name, + } \ No newline at end of file diff --git a/forum/activity.py b/forum/activity.py deleted file mode 100644 index 1687798..0000000 --- a/forum/activity.py +++ /dev/null @@ -1,121 +0,0 @@ -import datetime -from django.db.models.signals import post_save -from forum.models import * -from forum.models.base import marked_deleted, mark_canceled -from forum.models.node import node_create -from forum.models.answer import answer_accepted -from forum.authentication import user_updated -from forum.const import * - -def record_ask_event(instance, **kwargs): - activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ASK_QUESTION) - activity.save() - -node_create.connect(record_ask_event, sender=Question) - - -def record_answer_event(instance, **kwargs): - activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ANSWER) - activity.save() - -node_create.connect(record_answer_event, sender=Answer) - - -def record_comment_event(instance, **kwargs): - act_type = (instance.content_object.__class__ is Question) and TYPE_ACTIVITY_COMMENT_QUESTION or TYPE_ACTIVITY_COMMENT_ANSWER - activity = Activity(user=instance.user, active_at=instance.added_at, content_object=instance, activity_type=act_type) - activity.save() - -node_create.connect(record_comment_event, sender=Comment) - - -def record_revision_event(instance, created, **kwargs): - if created and instance.revision <> 1 and instance.node.node_type in ('question', 'answer',): - activity_type = instance.node.node_type == 'question' and TYPE_ACTIVITY_UPDATE_QUESTION or TYPE_ACTIVITY_UPDATE_ANSWER - activity = Activity(user=instance.author, active_at=instance.revised_at, content_object=instance, activity_type=activity_type) - activity.save() - -post_save.connect(record_revision_event, sender=NodeRevision) - - -def record_award_event(instance, created, **kwargs): - if created: - activity = Activity(user=instance.user, active_at=instance.awarded_at, content_object=instance, - activity_type=TYPE_ACTIVITY_PRIZE) - activity.save() - -post_save.connect(record_award_event, sender=Award) - - -def record_answer_accepted(answer, user, **kwargs): - activity = Activity(user=user, active_at=datetime.datetime.now(), content_object=answer, activity_type=TYPE_ACTIVITY_MARK_ANSWER) - activity.save() - -answer_accepted.connect(record_answer_accepted) - - -def update_last_seen(instance, **kwargs): - user = instance.user - user.last_seen = datetime.datetime.now() - user.save() - -post_save.connect(update_last_seen, sender=Activity) - - -def record_vote(instance, created, **kwargs): - if created: - act_type = (instance.vote == 1) and TYPE_ACTIVITY_VOTE_UP or TYPE_ACTIVITY_VOTE_DOWN - - activity = Activity(user=instance.user, active_at=instance.voted_at, content_object=instance, activity_type=act_type) - activity.save() - -post_save.connect(record_vote, sender=Vote) - - -def record_cancel_vote(instance, **kwargs): - act_type = (instance.vote == 1) and TYPE_ACTIVITY_CANCEL_VOTE_UP or TYPE_ACTIVITY_CANCEL_VOTE_DOWN - activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance, activity_type=act_type) - activity.save() - -mark_canceled.connect(record_cancel_vote, sender=Vote) - - -def record_delete_post(instance, **kwargs): - act_type = (instance.__class__ is Question) and TYPE_ACTIVITY_DELETE_QUESTION or TYPE_ACTIVITY_DELETE_ANSWER - activity = Activity(user=instance.deleted_by, active_at=datetime.datetime.now(), content_object=instance, activity_type=act_type) - activity.save() - -marked_deleted.connect(record_delete_post, sender=Question) -marked_deleted.connect(record_delete_post, sender=Answer) - - -def record_update_tags(instance, created, **kwargs): - if not created and 'tagnames' in instance.get_dirty_fields(): - activity = Activity(user=instance.author, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_UPDATE_TAGS) - activity.save() - -post_save.connect(record_update_tags, sender=Question) - - -def record_mark_offensive(instance, created, **kwargs): - if created: - activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance.content_object, activity_type=TYPE_ACTIVITY_MARK_OFFENSIVE) - activity.save() - -post_save.connect(record_mark_offensive, sender=FlaggedItem) - - -def record_favorite_question(instance, created, **kwargs): - if created: - activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_FAVORITE) - activity.save() - -post_save.connect(record_favorite_question, sender=FavoriteQuestion) - - -def record_user_full_updated(instance, **kwargs): - activity = Activity(user=instance, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_USER_FULL_UPDATED) - activity.save() - -user_updated.connect(record_user_full_updated, sender=User) - diff --git a/forum/admin.py b/forum/admin.py index 3afa224..e770806 100644 --- a/forum/admin.py +++ b/forum/admin.py @@ -6,7 +6,7 @@ from models import * class AnonymousQuestionAdmin(admin.ModelAdmin): """AnonymousQuestion admin class""" -class QuestionAdmin(admin.ModelAdmin): +class NodeAdmin(admin.ModelAdmin): """Question admin class""" class TagAdmin(admin.ModelAdmin): @@ -42,7 +42,7 @@ class BadgeAdmin(admin.ModelAdmin): class ReputeAdmin(admin.ModelAdmin): """ admin class""" -class ActivityAdmin(admin.ModelAdmin): +class ActionAdmin(admin.ModelAdmin): """ admin class""" #class BookAdmin(admin.ModelAdmin): @@ -54,19 +54,13 @@ class ActivityAdmin(admin.ModelAdmin): #class BookAuthorRssAdmin(admin.ModelAdmin): # """ admin class""" -admin.site.register(Question, QuestionAdmin) +admin.site.register(Node, NodeAdmin) admin.site.register(Tag, TagAdmin) -admin.site.register(Answer, Answerdmin) -admin.site.register(Comment, CommentAdmin) -admin.site.register(Vote, VoteAdmin) -admin.site.register(FlaggedItem, FlaggedItemAdmin) -admin.site.register(FavoriteQuestion, FavoriteQuestionAdmin) admin.site.register(QuestionRevision, QuestionRevisionAdmin) admin.site.register(AnswerRevision, AnswerRevisionAdmin) admin.site.register(Badge, BadgeAdmin) admin.site.register(Award, AwardAdmin) -admin.site.register(Repute, ReputeAdmin) -admin.site.register(Activity, ActivityAdmin) +admin.site.register(Action, ActionAdmin) #admin.site.register(Book, BookAdmin) #admin.site.register(BookAuthorInfo, BookAuthorInfoAdmin) #admin.site.register(BookAuthorRss, BookAuthorRssAdmin) diff --git a/forum/akismet.py b/forum/akismet.py index 940e5dd..4138d5a 100644 --- a/forum/akismet.py +++ b/forum/akismet.py @@ -119,8 +119,8 @@ class Akismet(object): if agent is None: agent = DEFAULTAGENT % __version__ self.user_agent = user_agent % (agent, __version__) - self.key = settings.WORDPRESS_API_KEY - self.blog_url = settings.WORDPRESS_BLOG_URL + self.key = str(settings.WORDPRESS_API_KEY) + self.blog_url = str(settings.WORDPRESS_BLOG_URL) def _getURL(self): diff --git a/forum/authentication/__init__.py b/forum/authentication/__init__.py index f6e14b7..08ea03f 100644 --- a/forum/authentication/__init__.py +++ b/forum/authentication/__init__.py @@ -34,7 +34,6 @@ AUTH_PROVIDERS = dict([ #todo: probably this don't belong here, also this post_stored routine needs a lot of work user_logged_in = django.dispatch.Signal(providing_args=["user", "old_session"]) -user_updated = django.dispatch.Signal(providing_args=["instance", "updated_by"]) #def post_stored_anonymous_content(user,old_session,**kwargs): # from forum.models import AnonymousQuestion, AnonymousAnswer diff --git a/forum/badges/__init__.py b/forum/badges/__init__.py index 421348f..935effd 100644 --- a/forum/badges/__init__.py +++ b/forum/badges/__init__.py @@ -1,10 +1,3 @@ -import re +from forum.modules import get_modules_script -from forum.badges.base import AbstractBadge -from forum.modules import get_modules_script_classes - -ALL_BADGES = [ - cls() for name, cls - in get_modules_script_classes('badges', AbstractBadge).items() - if not re.search('AbstractBadge$', name) - ] +get_modules_script('badges') diff --git a/forum/badges/base.py b/forum/badges/base.py index 63b6b0b..fce6b6e 100644 --- a/forum/badges/base.py +++ b/forum/badges/base.py @@ -4,111 +4,66 @@ from string import lower from django.contrib.contenttypes.models import ContentType from django.db.models.signals import post_save -from forum.models.user import activity_record -from forum.models.base import denorm_update -from forum.models import Badge, Award, Activity, Node +from forum.models import Badge, Node +from forum.actions import AwardAction import logging -class AbstractBadge(object): - - _instance = None - - @property - def name(self): - return " ".join(re.findall(r'([A-Z][a-z1-9]+)', re.sub('Badge', '', self.__class__.__name__))) - - @property - def description(self): - raise NotImplementedError - - def __new__(cls, *args, **kwargs): - if cls._instance is None: - cls.badge = "-".join(map(lower, re.findall(r'([A-Z][a-z1-9]+)', re.sub('Badge', '', cls.__name__)))) - cls._instance = super(AbstractBadge, cls).__new__(cls, *args, **kwargs) - - return cls._instance - - def install(self): - try: - installed = Badge.objects.get(slug=self.badge) - except: - badge = Badge(name=self.name, description=self.description, slug=self.badge, type=self.type) - badge.save() - - def award_badge(self, user, obj=None, award_once=False): - try: - badge = Badge.objects.get(slug=self.badge) - except: - logging.log(1, 'Trying to award a badge not installed in the database.') - return - - content_type = ContentType.objects.get_for_model(obj.__class__) - - awarded = user.awards.filter(badge=badge) +installed = dict([(b.cls, b) for b in Badge.objects.all()]) - if not award_once: - awarded = awarded.filter(content_type=content_type, object_id=obj.id) +class BadgesMeta(type): + by_class = {} + by_id = {} - if len(awarded): - logging.log(1, 'Trying to award badged already awarded.') - return - - award = Award(user=user, badge=badge, content_type=content_type, object_id=obj.id) - award.save() + def __new__(mcs, name, bases, dic): + badge = type.__new__(mcs, name, bases, dic) -class CountableAbstractBadge(AbstractBadge): + if not dic.get('abstract', False): + if not name in installed: + badge.ondb = Badge(cls=name, type=dic.get('type', Badge.BRONZE)) + badge.ondb.save() + else: + badge.ondb = installed[name] - def __init__(self, model, field, expected_value, handler): - def wrapper(instance, sfield, old, new, **kwargs): - if sfield == field and (new == expected_value) or (old < expected_value and new > expected_value): - handler(instance=instance) - - denorm_update.connect(wrapper, sender=model, weak=False) + inst = badge() -class PostCountableAbstractBadge(CountableAbstractBadge): - def __init__(self, model, field, expected_value): + def hook(action, new): + user = inst.award_to(action) - def handler(instance): - self.award_badge(instance.author, instance) + if user: + badge.award(user, action, badge.award_once) - super(PostCountableAbstractBadge, self).__init__(model, field, expected_value, handler) + for action in badge.listen_to: + action.hook(hook) -class NodeCountableAbstractBadge(CountableAbstractBadge): - def __init__(self, node_type, field, expected_value): + BadgesMeta.by_class[name] = badge + badge.ondb.__dict__['_class'] = inst + BadgesMeta.by_id[badge.ondb.id] = badge - def handler(instance): - if instance.node_type == node_type: - self.award_badge(instance.author, instance) + return badge - super(NodeCountableAbstractBadge, self).__init__(Node, field, expected_value, handler) - -class ActivityAbstractBadge(AbstractBadge): - - def __init__(self, activity_type, handler): - - def wrapper(sender, **kwargs): - handler(instance=kwargs['instance']) - - activity_record.connect(wrapper, sender=activity_type, weak=False) - - -class ActivityCountAbstractBadge(AbstractBadge): +class AbstractBadge(object): + __metaclass__ = BadgesMeta - def __init__(self, activity_type, count): + abstract = True + award_once = False - def handler(sender, **kwargs): - instance = kwargs['instance'] - if Activity.objects.filter(user=instance.user, activity_type__in=activity_type).count() == count: - self.award_badge(instance.user, instance.content_object) + @property + def name(self): + raise NotImplementedError - if not isinstance(activity_type, (tuple, list)): - activity_type = (activity_type, ) + @property + def description(self): + raise NotImplementedError - for type in activity_type: - activity_record.connect(handler, sender=type, weak=False) + @classmethod + def award(cls, user, action, once=False): + if once: + node = None + else: + node = action.node -class FirstActivityAbstractBadge(ActivityCountAbstractBadge): + awarded = AwardAction.get_for(user, node, cls.ondb) - def __init__(self, activity_type): - super(FirstActivityAbstractBadge, self).__init__(activity_type, 1) + if not awarded: + AwardAction(user=user, node=node, ip=action.ip).save(data=dict(badge=cls.ondb, trigger=action)) \ No newline at end of file diff --git a/forum/feed.py b/forum/feed.py index 0a08825..4017d61 100644 --- a/forum/feed.py +++ b/forum/feed.py @@ -34,7 +34,7 @@ class RssLastestQuestionsFeed(Feed): return item.added_at def items(self, item): - return Question.objects.filter(deleted=False).order_by('-last_activity_at')[:30] + return Question.objects.filter(deleted=None).order_by('-last_activity_at')[:30] def main(): pass diff --git a/forum/forms.py b/forum/forms.py index 35c6083..70466b5 100644 --- a/forum/forms.py +++ b/forum/forms.py @@ -101,18 +101,6 @@ class SummaryField(forms.CharField): self.label = _('update summary:') self.help_text = _('enter a brief summary of your revision (e.g. fixed spelling, grammar, improved style, this field is optional)') -class ModerateUserForm(forms.ModelForm): - is_approved = forms.BooleanField(label=_("Automatically accept user's contributions for the email updates"), - required=False) - - def clean_is_approved(self): - if 'is_approved' not in self.cleaned_data: - self.cleaned_data['is_approved'] = False - return self.cleaned_data['is_approved'] - - class Meta: - model = User - fields = ('is_approved',) class FeedbackForm(forms.Form): name = forms.CharField(label=_('Your name:'), required=False) diff --git a/forum/management/__init__.py b/forum/management/__init__.py index 49ad8d5..b654caa 100644 --- a/forum/management/__init__.py +++ b/forum/management/__init__.py @@ -1,13 +1,3 @@ from forum.modules import get_modules_script -from django.db.models.signals import post_syncdb -import forum.models - -def setup_badges(sender, **kwargs): - from forum.badges import ALL_BADGES - - for badge in ALL_BADGES: - badge.install() - -post_syncdb.connect(setup_badges, sender=forum.models) get_modules_script('management') \ No newline at end of file diff --git a/forum/migrations/0014_auto__add_field_question_accepted_answer.py b/forum/migrations/0014_auto__add_field_question_accepted_answer.py index 54ef078..e73c960 100644 --- a/forum/migrations/0014_auto__add_field_question_accepted_answer.py +++ b/forum/migrations/0014_auto__add_field_question_accepted_answer.py @@ -12,10 +12,9 @@ class Migration(SchemaMigration): # Adding field 'Question.accepted_answer' db.add_column(u'question', 'accepted_answer', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Answer'], unique=True, null=True), keep_default=False) - if db.backend_name == "postgres" and not "pgfulltext" in settings.DISABLED_MODULES: - pass - db.execute("DROP TRIGGER tsvectorupdate ON question;") - db.execute("ALTER TABLE question DROP COLUMN tsv;") + #if db.backend_name == "postgres" and not "pgfulltext" in settings.DISABLED_MODULES: + # db.execute("DROP TRIGGER tsvectorupdate ON question;") + # db.execute("ALTER TABLE question DROP COLUMN tsv;") def backwards(self, orm): diff --git a/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py b/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py new file mode 100644 index 0000000..87b792e --- /dev/null +++ b/forum/migrations/0022_auto__add_actionrepute__add_action__add_favoritenode__del_field_node_v.py @@ -0,0 +1,463 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + print "# Adding model 'ActionRepute'" + db.create_table('forum_actionrepute', ( + ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', to=orm['forum.Action'])), + ('by_canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('value', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])), + )) + db.send_create_signal('forum', ['ActionRepute']) + + print "# Adding model 'Action'" + db.create_table('forum_action', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True)), + ('extra', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('canceled_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='canceled_actions', null=True, to=orm['forum.User'])), + ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('action_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='actions', to=orm['forum.User'])), + ('action_type', self.gf('django.db.models.fields.CharField')(max_length=16)), + ('canceled_at', self.gf('django.db.models.fields.DateTimeField')(null=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('ip', self.gf('django.db.models.fields.CharField')(max_length=16, null=True)), + )) + db.send_create_signal('forum', ['Action']) + + print "# Deleting field 'Node.vote_up_count'" + db.delete_column('forum_node', 'vote_up_count') + + print "# Deleting field 'Node.comment_count'" + db.delete_column('forum_node', 'comment_count') + + print "# Deleting field 'Node.offensive_flag_count'" + db.delete_column('forum_node', 'offensive_flag_count') + + print "# Deleting field 'Node.vote_down_count'" + db.delete_column('forum_node', 'vote_down_count') + + print "# Adding field 'Node.wiki'" + db.add_column('forum_node', 'wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + print "# Adding field 'Node.marked'" + db.add_column('forum_node', 'marked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + print "# Adding field 'Node.extra_count'" + db.add_column('forum_node', 'extra_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) + + print "# Adding field 'Node.last_activity_by'" + db.add_column('forum_node', 'last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True), keep_default=False) + + print "# Adding field 'Node.extra_ref'" + db.add_column('forum_node', 'extra_ref', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True), keep_default=False) + + print "# Adding field 'Node.last_activity_at'" + db.add_column('forum_node', 'last_activity_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False) + + # Changing field 'Answer.node_ptr' + #db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)) + + print "# Changing field 'QuestionSubscription.question'" + db.alter_column('forum_questionsubscription', 'question_id', self.gf('django.db.models.fields.IntegerField')()) + + # Removing unique constraint on 'Award', fields ['badge', 'object_id', 'content_type', 'user'] + #db.delete_unique(u'award', ['badge_id', 'object_id', 'content_type_id', 'user_id']) + + print "# Changing field 'User.gold'" + db.alter_column('forum_user', 'gold', self.gf('django.db.models.fields.PositiveIntegerField')()) + + print "# Changing field 'User.silver'" + db.alter_column('forum_user', 'silver', self.gf('django.db.models.fields.PositiveIntegerField')()) + + print "# Changing field 'User.bronze'" + db.alter_column('forum_user', 'bronze', self.gf('django.db.models.fields.PositiveIntegerField')()) + + print "# Deleting field 'Question.answer_count'" + db.delete_column(u'question', 'answer_count') + + print "# Deleting field 'Question.favourite_count'" + db.delete_column(u'question', 'favourite_count') + + # Changing field 'Question.node_ptr' + #db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)) + + + def backwards(self, orm): + + # Deleting model 'ActionRepute' + db.delete_table('forum_actionrepute') + + # Deleting model 'Action' + db.delete_table('forum_action') + + # Deleting model 'FavoriteNode' + db.delete_table('forum_favoritenode') + + # Adding field 'Node.vote_up_count' + db.add_column('forum_node', 'vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) + + # Adding field 'Node.comment_count' + db.add_column('forum_node', 'comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False) + + # Adding field 'Node.offensive_flag_count' + db.add_column('forum_node', 'offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0), keep_default=False) + + # Adding field 'Node.vote_down_count' + db.add_column('forum_node', 'vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) + + # Deleting field 'Node.wiki' + db.delete_column('forum_node', 'wiki') + + # Deleting field 'Node.marked' + db.delete_column('forum_node', 'marked') + + # Deleting field 'Node.extra_count' + db.delete_column('forum_node', 'extra_count') + + # Deleting field 'Node.last_activity_by' + db.delete_column('forum_node', 'last_activity_by_id') + + # Deleting field 'Node.extra_ref' + db.delete_column('forum_node', 'extra_ref_id') + + # Deleting field 'Node.last_activity_at' + db.delete_column('forum_node', 'last_activity_at') + + # Changing field 'Answer.node_ptr' + db.alter_column(u'answer', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True)) + + # Adding unique constraint on 'Award', fields ['badge', 'object_id', 'content_type', 'user'] + db.create_unique(u'award', ['badge_id', 'object_id', 'content_type_id', 'user_id']) + + # Changing field 'User.gold' + db.alter_column('forum_user', 'gold', self.gf('django.db.models.fields.SmallIntegerField')()) + + # Changing field 'User.silver' + db.alter_column('forum_user', 'silver', self.gf('django.db.models.fields.SmallIntegerField')()) + + # Changing field 'User.bronze' + db.alter_column('forum_user', 'bronze', self.gf('django.db.models.fields.SmallIntegerField')()) + + # Adding field 'Question.answer_count' + db.add_column(u'question', 'answer_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0), keep_default=False) + + # Adding field 'Question.favourite_count' + db.add_column(u'question', 'favourite_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) + + # Changing field 'Question.node_ptr' + db.alter_column(u'question', 'node_ptr_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True)) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.anonymousnode': { + 'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']}, + 'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}), + 'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.favoritequestion': { + 'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}), + 'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 27, 11, 37, 29, 356000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 11, 37, 29, 624000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}), + 'vote': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0023_flaten_node_inheritance_create_actions.py b/forum/migrations/0023_flaten_node_inheritance_create_actions.py new file mode 100644 index 0000000..d4b081b --- /dev/null +++ b/forum/migrations/0023_flaten_node_inheritance_create_actions.py @@ -0,0 +1,685 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.migrations import ProgressBar + +GAIN_BY_UPVOTED = 1 +GAIN_BY_ANSWER_ACCEPTED = 2 +GAIN_BY_ACCEPTING_ANSWER = 3 +GAIN_BY_DOWNVOTE_CANCELED = 4 +GAIN_BY_CANCELING_DOWNVOTE = 5 +LOST_BY_CANCELLING_ACCEPTED_ANSWER = -1 +LOST_BY_ACCEPTED_ANSWER_CANCELED = -2 +LOST_BY_DOWNVOTED = -3 +LOST_BY_FLAGGED = -4 +LOST_BY_DOWNVOTING = -5 +LOST_BY_FLAGGED_3_TIMES = -6 +LOST_BY_FLAGGED_5_TIMES = -7 +LOST_BY_UPVOTE_CANCELED = -8 + +class Migration(DataMigration): + + def forwards(self, orm): + rephist = dict([(t, []) for t in range(-8, 6) if t != 0]) + + r_count = orm.Repute.objects.count() + print "\nCalculating rep gain/losses history through %d records:" % r_count + progress = ProgressBar(r_count) + + for r in orm.Repute.objects.all(): + l = rephist.get(r.reputation_type, None) + if l is None: continue + + if (len(l) == 0) or (l[-1][1] != r.value): + l.append((r.reputed_at, r.value)) + + progress.update() + + print "\n...done\n" + + + def repval_at(reptype, repdate, default): + l = rephist.get(reptype, None) + + if l is None: return 0 + if len(l) == 0: return default + + for r in l: + if r[0] <= repdate: + return r[1] or default + + + q_count = orm.Question.objects.count() + print "\nConverting %d questions:" % q_count + progress = ProgressBar(q_count) + + for q in orm.Question.objects.all(): + n = q.node_ptr + n.last_activity_at = q.last_activity_at + n.last_activity_by = q.last_activity_by + + if q.accepted_answer: + n.extra_ref = q.accepted_answer.node_ptr + + n.extra_count = q.view_count + + n.marked = q.closed + n.wiki = q.wiki + + n.save() + + ask = orm.Action( + user = n.author, + action_date = n.added_at, + node = n, + action_type = "ask", + extra = '' + ) + + ask.save() + + if n.deleted: + action = orm.Action( + user = n.deleted_by, + node = n, + action_type = "delete", + action_date = n.deleted_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + + if n.marked: + action = orm.Action( + user = q.closed_by, + node = n, + action_type = "close", + extra = q.close_reason, + action_date = q.closed_at or datetime.datetime.now(), + ) + + action.save() + + if n.wiki: + action = orm.Action( + user = n.author, + node = n, + action_type = "wikify", + action_date = q.wikified_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + progress.update() + + print "\n...done\n" + + a_count = orm.Answer.objects.count() + print "\nConverting %d answers:" % a_count + progress = ProgressBar(a_count) + + for a in orm.Answer.objects.all(): + n = a.node_ptr + + n.marked = a.accepted + n.wiki = a.wiki + + n.save() + + ans = orm.Action( + user = n.author, + action_date = n.added_at, + node = n, + action_type = "answer", + extra = '' + ) + + ans.save() + + if n.deleted: + action = orm.Action( + user = n.deleted_by, + node = n, + action_type = "delete", + action_date = n.deleted_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + if a.accepted: + action = orm.Action( + user = a.accepted_by, + node = n, + action_type = "acceptanswer", + action_date = a.accepted_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + if not a.wiki or a.wikified_at > action.action_date: + if action.user == n.author: + rep = orm.ActionRepute( + action = action, + user = action.user, + value = repval_at(GAIN_BY_ACCEPTING_ANSWER, action.action_date, 2) + ) + rep.save() + + if n.author != n.parent.author: + rep = orm.ActionRepute( + action = action, + user = n.author, + value = repval_at(GAIN_BY_ANSWER_ACCEPTED, action.action_date, 15) + ) + rep.save() + + if n.wiki: + action = orm.Action( + user = n.author, + node = n, + action_type = "wikify", + action_date = a.wikified_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + progress.update() + + print "\n...done\n" + + v_count = orm.Vote.objects.count() + print "\nConverting %d votes:" % v_count + progress = ProgressBar(v_count) + + for v in orm.Vote.objects.exclude(canceled=True): + a = orm.Action( + action_type = (v.vote == 1) and ((v.node.node_type == "comment") and "voteupcomment" or "voteup") or "votedown", + user = v.user, + node = v.node, + action_date = v.voted_at, + canceled = v.canceled, + extra = '' + ) + + a.save() + + def impl(node): + if node.node_type == "question": + return orm.Question.objects.get(node_ptr=node) + else: + return orm.Answer.objects.get(node_ptr=node) + + if a.node.node_type in ("question", "answer") and (not a.node.wiki or impl(a.node).wikified_at > a.action_date): + reptype, default = (v.vote == 1) and (GAIN_BY_UPVOTED, 10) or (LOST_BY_DOWNVOTED, 2) + rep = orm.ActionRepute( + action = a, + user = a.node.author, + value = repval_at(reptype, a.action_date, default) or default + ) + rep.save() + + if v.vote == -1: + rep = orm.ActionRepute( + action = a, + user = a.node.author, + value = repval_at(LOST_BY_DOWNVOTING, a.action_date, 1) or default + ) + rep.save() + + progress.update() + + print "\n...done\n" + + f_count = orm.FlaggedItem.objects.count() + print "\nConverting %d flags:" % f_count + progress = ProgressBar(f_count) + + for f in orm.FlaggedItem.objects.all(): + a = orm.Action( + action_type = "flag", + user = f.user, + node = f.node, + action_date = f.flagged_at, + extra = f.reason or '' + ) + + a.save() + + rep = orm.ActionRepute( + action = a, + user = a.node.author, + value = repval_at(LOST_BY_FLAGGED, a.action_date, 2) or 2 + ) + rep.save() + + progress.update() + + print "\n...done\n" + + n_count = orm.Node.objects.all().count() + print "\nChecking flag count of %d nodes:" % n_count + progress = ProgressBar(n_count) + + for n in orm.Node.objects.all(): + flags = list(orm.Action.objects.filter(action_type="flag", node=n, canceled=False).order_by('-action_date')) + + if len(flags) >= 3: + a = flags[2] + rep = orm.ActionRepute( + action = a, + user = n.author, + value = repval_at(LOST_BY_FLAGGED_3_TIMES, a.action_date, 30) + ) + rep.save() + + + if len(flags) >= 5: + a = flags[4] + rep = orm.ActionRepute( + action = a, + user = n.author, + value = repval_at(LOST_BY_FLAGGED_5_TIMES, a.action_date, 100) + ) + rep.save() + + progress.update() + + print "\n...done\n" + + c_count = orm.Node.objects.filter(node_type="comment").count() + print "\nCreating %d comment actions:" % c_count + progress = ProgressBar(c_count) + + for c in orm.Node.objects.filter(node_type="comment").all(): + a = orm.Action( + action_type = "comment", + user = c.author, + node = c, + action_date = c.added_at, + extra = '' + ) + + a.save() + + if c.deleted: + action = orm.Action( + user = c.deleted_by, + node = c, + action_type = "delete", + action_date = c.deleted_at or datetime.datetime.now(), + extra = '' + ) + + action.save() + + progress.update() + + print "\n...done\n" + + + r_count = orm.NodeRevision.objects.exclude(revision=1).count() + print "\nCreating %d edit actions:" % r_count + progress = ProgressBar(r_count) + + for r in orm.NodeRevision.objects.exclude(revision=1): + a = orm.Action( + action_type = "revise", + user = r.author, + node = r.node, + action_date = r.revised_at, + extra = r.revision + ) + + a.save() + progress.update() + + print "\n...done\n" + + u_count = orm.User.objects.all().count() + print "\nCreating %d user join actions and reputation recalculation:" % u_count + progress = ProgressBar(u_count) + + for u in orm.User.objects.all(): + a = orm.Action( + user = u, + action_date = u.date_joined, + action_type = "userjoins", + ) + + a.save() + + rep = orm.ActionRepute( + action = a, + user = u, + value = 1 + ) + rep.save() + + new_rep = orm.ActionRepute.objects.filter(user=u).aggregate(reputation=models.Sum('value'))['reputation'] + + if new_rep < 0: + new_rep = 1 + + u.reputation = new_rep + u.save() + + progress.update() + + print "\n...done\n" + + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.anonymousnode': { + 'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']}, + 'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}), + 'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.favoritequestion': { + 'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'node_ptr': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True', 'primary_key': 'True'}), + 'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 27, 11, 40, 32, 68000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 11, 40, 32, 153000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"}, + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}), + 'vote': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py b/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py new file mode 100644 index 0000000..38a7604 --- /dev/null +++ b/forum/migrations/0024_auto__del_repute__del_vote__del_answer__del_flaggeditem__del_anonymous.py @@ -0,0 +1,377 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting model 'Repute' + db.delete_table(u'repute') + + # Deleting model 'Vote' + db.delete_table(u'vote') + + # Deleting model 'Answer' + db.delete_table(u'answer') + + # Deleting model 'FlaggedItem' + db.delete_table(u'flagged_item') + + # Deleting model 'AnonymousNode' + db.delete_table('forum_anonymousnode') + + # Deleting model 'FavoriteQuestion' + db.delete_table(u'favorite_question') + + # Deleting model 'Question' + db.delete_table(u'question') + + # Deleting field 'Node.deleted_at' + db.delete_column('forum_node', 'deleted_at') + + # Deleting field 'Node.last_edited_by' + db.delete_column('forum_node', 'last_edited_by_id') + + # Deleting field 'Node.deleted' + db.delete_column('forum_node', 'deleted') + + # Deleting field 'Node.deleted_by' + db.delete_column('forum_node', 'deleted_by_id') + + # Deleting field 'Node.last_edited_at' + db.delete_column('forum_node', 'last_edited_at') + + + def backwards(self, orm): + + # Adding model 'Repute' + db.create_table(u'repute', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', null=True, to=orm['forum.Node'])), + ('reputed_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])), + ('value', self.gf('django.db.models.fields.SmallIntegerField')(default=0)), + ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('reputation_type', self.gf('django.db.models.fields.SmallIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', to=orm['forum.User'])), + ('user_previous_rep', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['Repute']) + + # Adding model 'Vote' + db.create_table(u'vote', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', null=True, to=orm['forum.Node'])), + ('vote', self.gf('django.db.models.fields.SmallIntegerField')()), + ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', to=orm['forum.User'])), + ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['Vote']) + + # Adding model 'Answer' + db.create_table(u'answer', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('accepted_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'], null=True)), + ('accepted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('node_ptr', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)), + ('accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + )) + db.send_create_signal('forum', ['Answer']) + + # Adding model 'FlaggedItem' + db.create_table(u'flagged_item', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', null=True, to=orm['forum.Node'])), + ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('reason', self.gf('django.db.models.fields.CharField')(max_length=300, null=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', to=orm['forum.User'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['FlaggedItem']) + + # Adding model 'AnonymousNode' + db.create_table('forum_anonymousnode', ( + ('convertible_to', self.gf('django.db.models.fields.CharField')(default='node', max_length=16)), + ('validation_hash', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_content', to=orm['forum.Node'])), + ('node_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['forum.Node'], unique=True, primary_key=True)), + )) + db.send_create_signal('forum', ['AnonymousNode']) + + # Adding model 'FavoriteQuestion' + db.create_table(u'favorite_question', ( + ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['forum.Question'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_favorite_questions', to=orm['forum.User'])), + )) + db.send_create_signal('forum', ['FavoriteQuestion']) + + # Adding model 'Question' + db.create_table(u'question', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_active_in_questions', null=True, to=orm['forum.User'])), + ('close_reason', self.gf('django.db.models.fields.SmallIntegerField')(null=True, blank=True)), + ('last_activity_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('view_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('node_ptr', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'], null=True, primary_key=True)), + ('accepted_answer', self.gf('django.db.models.fields.related.OneToOneField')(related_name='question_accepting', unique=True, null=True, to=orm['forum.Answer'])), + ('closed', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('closed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('closed_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='closed_questions', null=True, to=orm['forum.User'], blank=True)), + )) + db.send_create_signal('forum', ['Question']) + + # Adding field 'Node.deleted_at' + db.add_column('forum_node', 'deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False) + + # Adding field 'Node.last_edited_by' + db.add_column('forum_node', 'last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_edited_nodes', null=True, to=orm['forum.User'], blank=True), keep_default=False) + + # Adding field 'Node.deleted' + db.add_column('forum_node', 'deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + # Adding field 'Node.deleted_by' + db.add_column('forum_node', 'deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_nodes', null=True, to=orm['forum.User'], blank=True), keep_default=False) + + # Adding field 'Node.last_edited_at' + db.add_column('forum_node', 'last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 43, 52, 301000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 43, 52, 512000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py b/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py new file mode 100644 index 0000000..2cf638c --- /dev/null +++ b/forum/migrations/0025_auto__add_field_node_extra_action__add_field_node_deleted__add_field_n.py @@ -0,0 +1,267 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Node.extra_action' + db.add_column('forum_node', 'extra_action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='extra_node', null=True, to=orm['forum.Action']), keep_default=False) + + # Adding field 'Node.deleted' + db.add_column('forum_node', 'deleted', self.gf('django.db.models.fields.related.ForeignKey')(related_name='deleted_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False) + + # Adding field 'Node.last_edited' + db.add_column('forum_node', 'last_edited', self.gf('django.db.models.fields.related.ForeignKey')(related_name='edited_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Node.extra_action' + db.delete_column('forum_node', 'extra_action_id') + + # Deleting field 'Node.deleted' + db.delete_column('forum_node', 'deleted_id') + + # Deleting field 'Node.last_edited' + db.delete_column('forum_node', 'last_edited_id') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 49, 37, 322000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 49, 37, 506000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0026_reset_deleted_and_lastedited_flags.py b/forum/migrations/0026_reset_deleted_and_lastedited_flags.py new file mode 100644 index 0000000..8521ffd --- /dev/null +++ b/forum/migrations/0026_reset_deleted_and_lastedited_flags.py @@ -0,0 +1,278 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.migrations import ProgressBar + +class Migration(DataMigration): + + def forwards(self, orm): + n_count = orm.Node.objects.all().count() + print "\nReseting %d nodes:" % n_count + progress = ProgressBar(n_count) + + for n in orm.Node.objects.all(): + try: + d = orm.Action.objects.get(node=n, action_type="delete", canceled=False) + n.deleted_id = d.id + except Exception, e: + n.deleted = None + + if orm.Action.objects.filter(node=n, action_type="revise").count() > 0: + n.last_edited_id = orm.Action.objects.filter(node=n, action_type="revise").order_by('-action_date')[0].id + else: + n.last_edited = None + + + if n.node_type == "answer" and n.marked: + n.extra_action_id = orm.Action.objects.get(node=n, action_type="acceptanswer", canceled=False).id + + if n.node_type == "question" and n.marked: + n.extra_action_id = orm.Action.objects.get(node=n, action_type="close", canceled=False).id + + n.save() + + progress.update() + + print "\n...done\n" + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 28, 23, 55, 36, 647000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 23, 55, 36, 708000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0027_auto__del_activity.py b/forum/migrations/0027_auto__del_activity.py new file mode 100644 index 0000000..589b5bb --- /dev/null +++ b/forum/migrations/0027_auto__del_activity.py @@ -0,0 +1,254 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting model 'Activity' + db.delete_table(u'activity') + + + def backwards(self, orm): + + # Adding model 'Activity' + db.create_table(u'activity', ( + ('is_auditted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('active_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('activity_type', self.gf('django.db.models.fields.SmallIntegerField')()), + )) + db.send_create_signal('forum', ['Activity']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 1, 30, 30, 35000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 1, 30, 30, 211000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py b/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py new file mode 100644 index 0000000..1170bf7 --- /dev/null +++ b/forum/migrations/0028_auto__add_field_action_canceled_ip__add_field_actionrepute_date.py @@ -0,0 +1,253 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Action.canceled_ip' + db.add_column('forum_action', 'canceled_ip', self.gf('django.db.models.fields.CharField')(default='', max_length=16), keep_default=False) + + # Adding field 'ActionRepute.date' + db.add_column('forum_actionrepute', 'date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Action.canceled_ip' + db.delete_column('forum_action', 'canceled_ip') + + # Deleting field 'ActionRepute.date' + db.delete_column('forum_actionrepute', 'date') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 21, 20, 24, 880000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 21, 20, 35, 361000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0029_repute_dates.py b/forum/migrations/0029_repute_dates.py new file mode 100644 index 0000000..14d6e62 --- /dev/null +++ b/forum/migrations/0029_repute_dates.py @@ -0,0 +1,259 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.migrations import ProgressBar + +class Migration(DataMigration): + + def forwards(self, orm): + r_count = orm.ActionRepute.objects.count() + print "\nAdding dates to %d repute actions:" % r_count + progress = ProgressBar(r_count) + + for r in orm.ActionRepute.objects.all(): + a = r.action + + if r.by_canceled: + r.date = a.canceled_at + else: + r.date = a.action_date + + r.save() + + progress.update() + + print "\n...done\n" + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 29, 21, 21, 16, 237000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 21, 21, 16, 298000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py b/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py new file mode 100644 index 0000000..cd4e1f1 --- /dev/null +++ b/forum/migrations/0030_auto__chg_field_action_extra__chg_field_keyvalue_value.py @@ -0,0 +1,253 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Changing field 'Action.extra' + db.alter_column('forum_action', 'extra', self.gf('forum.models.utils.PickledObjectField')(null=True)) + + # Changing field 'KeyValue.value' + db.alter_column('forum_keyvalue', 'value', self.gf('forum.models.utils.PickledObjectField')(null=True)) + + + def backwards(self, orm): + + # Changing field 'Action.extra' + db.alter_column('forum_action', 'extra', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'KeyValue.value' + db.alter_column('forum_keyvalue', 'value', self.gf('forum.models.utils.PickledObjectField')()) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 30, 23, 58, 8, 677000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 1, 23, 58, 8, 841000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0031_alter_pickle_storage.py b/forum/migrations/0031_alter_pickle_storage.py new file mode 100644 index 0000000..5c8bb7b --- /dev/null +++ b/forum/migrations/0031_alter_pickle_storage.py @@ -0,0 +1,274 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.migrations import ProgressBar +from forum.models.utils import dbsafe_encode + +try: + from cPickle import loads, dumps +except ImportError: + from pickle import loads, dumps + +class Migration(DataMigration): + + def forwards(self, orm): + k_count = orm.KeyValue.objects.count() + print "\nConverting %d keyvalue objects:" % k_count + progress = ProgressBar(k_count) + + for kv in orm.KeyValue.objects.all(): + try: + o = loads(kv.value.encode('utf-8')) + except: + o = kv.value + + kv.value = dbsafe_encode(o, compress_object=True) + kv.save() + progress.update() + + print "\n...done\n" + + a_count = orm.Action.objects.count() + print "\nConverting %d actions extra fields:" % a_count + progress = ProgressBar(a_count) + + for a in orm.Action.objects.all(): + a.extra = dbsafe_encode(a.extra, compress_object=True) + a.save() + progress.update() + + print "\n...done\n" + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 1, 0, 0, 32, 37000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 2, 0, 0, 32, 86000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py b/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py new file mode 100644 index 0000000..7a15772 --- /dev/null +++ b/forum/migrations/0032_auto__del_field_user_hide_ignored_questions__del_field_user_questions_.py @@ -0,0 +1,263 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting field 'User.hide_ignored_questions' + db.delete_column('forum_user', 'hide_ignored_questions') + + # Deleting field 'User.questions_per_page' + db.delete_column('forum_user', 'questions_per_page') + + # Deleting field 'User.email_key' + db.delete_column('forum_user', 'email_key') + + # Adding field 'Node.in_moderation' + db.add_column('forum_node', 'in_moderation', self.gf('django.db.models.fields.related.ForeignKey')(related_name='moderated_node', unique=True, null=True, to=orm['forum.Action']), keep_default=False) + + + def backwards(self, orm): + + # Adding field 'User.hide_ignored_questions' + db.add_column('forum_user', 'hide_ignored_questions', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + # Adding field 'User.questions_per_page' + db.add_column('forum_user', 'questions_per_page', self.gf('django.db.models.fields.SmallIntegerField')(default=10), keep_default=False) + + # Adding field 'User.email_key' + db.add_column('forum_user', 'email_key', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False) + + # Deleting field 'Node.in_moderation' + db.delete_column('forum_node', 'in_moderation_id') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 2, 4, 54, 13, 72000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 4, 54, 13, 256000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py b/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py new file mode 100644 index 0000000..f2b38e8 --- /dev/null +++ b/forum/migrations/0033_auto__add_flag__add_vote__add_field_badge_cls__del_unique_badge_type_n.py @@ -0,0 +1,333 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.rename_table('award', 'forum_award') + db.rename_table('badge', 'forum_badge') + db.rename_table('tag', 'forum_tag') + + # Adding model 'Flag' + db.create_table('forum_flag', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'])), + ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flag', unique=True, to=orm['forum.Action'])), + ('reason', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])), + ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + )) + #db.send_create_signal('forum', ['Flag']) + + # Adding model 'Vote' + db.create_table('forum_vote', ( + ('node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Node'])), + ('action', self.gf('django.db.models.fields.related.ForeignKey')(related_name='vote', unique=True, to=orm['forum.Action'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('value', self.gf('django.db.models.fields.SmallIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.User'])), + ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + )) + #db.send_create_signal('forum', ['Vote']) + + # Adding field 'Badge.cls' + db.add_column('forum_badge', 'cls', self.gf('django.db.models.fields.CharField')(max_length=50, null=True), keep_default=False) + + # Removing unique constraint on 'Badge', fields ['type', 'name'] + db.delete_unique(u'forum_badge', ['type', 'name']) + + # Deleting field 'Award.notified' + db.delete_column(u'forum_award', 'notified') + + # Adding field 'Award.node' + db.add_column('forum_award', 'node', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['forum.Node'], null=True), keep_default=False) + + # Adding field 'Award.trigger' + db.add_column('forum_award', 'trigger', self.gf('django.db.models.fields.related.ForeignKey')(related_name='awards', null=True, to=orm['forum.Action']), keep_default=False) + + # Adding field 'Award.action' + db.add_column('forum_award', 'action', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='award', to=orm['forum.Action']), keep_default=False) + + # Adding unique constraint on 'Award', fields ['node', 'badge', 'user'] + #db.create_unique('forum_award', ['node_id', 'badge_id', 'user_id']) + + + def backwards(self, orm): + + # Deleting model 'Flag' + db.delete_table('forum_flag') + + # Deleting model 'Vote' + db.delete_table('forum_vote') + + # Deleting field 'Badge.cls' + db.delete_column('forum_badge', 'cls') + + # Adding unique constraint on 'Badge', fields ['type', 'name'] + db.create_unique(u'badge', ['type', 'name']) + + # Adding field 'Award.notified' + db.add_column(u'award', 'notified', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + # Deleting field 'Award.node' + db.delete_column('forum_award', 'node_id') + + # Deleting field 'Award.trigger' + db.delete_column('forum_award', 'trigger_id') + + # Deleting field 'Award.action' + db.delete_column('forum_award', 'action_id') + + # Removing unique constraint on 'Award', fields ['node', 'badge', 'user'] + db.delete_unique('forum_award', ['node_id', 'badge_id', 'user_id']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'to': "orm['forum.Action']"}), + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'object_name': 'Badge'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.flag': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 41, 55, 831000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 41, 59, 140000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0034_new_badge_and_award.py b/forum/migrations/0034_new_badge_and_award.py new file mode 100644 index 0000000..89399f9 --- /dev/null +++ b/forum/migrations/0034_new_badge_and_award.py @@ -0,0 +1,344 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.migrations import ProgressBar +from forum.models.utils import dbsafe_decode + +class Migration(DataMigration): + + def forwards(self, orm): + b_count = orm.Badge.objects.count() + print "\nConverting %d badges:" % b_count + progress = ProgressBar(b_count) + + for b in orm.Badge.objects.all(): + b.cls = "".join([s[0].upper() + s[1:] for s in b.slug.split('-')]) + b.save() + + progress.update() + + print "\n...done\n" + + ctypes = dict([(ct.name, ct.id) for ct in orm['contenttypes.ContentType'].objects.all()]) + + a_count = orm.Award.objects.count() + print "\nConverting %d awards:" % a_count + progress = ProgressBar(a_count) + + for a in orm.Award.objects.all(): + if a.content_type.id == ctypes['user']: + a.node = None + else: + try: + a.node = orm.Node.objects.get(id=a.object_id) + except: + a.delete() + continue + + action = orm.Action( + user = a.user, + node = a.node, + action_type = "award", + action_date = a.awarded_at, + ) + + action.save() + + a.action = action + a.save() + + progress.update() + + print "\n...done\n" + + + a_count = orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment")).count() + print "\nConverting %d votes:" % a_count + progress = ProgressBar(a_count) + + for a in orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment"), canceled=False): + v = orm.Vote( + user = a.user, + node = a.node, + value = (a.action_type in ("voteup", "voteupcomment")) and 1 or -1, + action = a, + voted_at = a.action_date + ) + + v.save() + + progress.update() + + print "\n...done\n" + + a_count = orm.Action.objects.filter(action_type__in=("voteup", "votedown", "voteupcomment")).count() + print "\nConverting %d votes:" % a_count + progress = ProgressBar(a_count) + + for a in orm.Action.objects.filter(action_type="flag", canceled=False): + f = orm.Flag( + user = a.user, + node = a.node, + reason = a.extra, + action = a, + flagged_at = a.action_date + ) + + f.save() + + progress.update() + + print "\n...done\n" + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'to': "orm['forum.Action']"}), + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'object_name': 'Badge'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.flag': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 43, 54, 540000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 43, 54, 592000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py b/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py new file mode 100644 index 0000000..b566ef0 --- /dev/null +++ b/forum/migrations/0035_auto__del_field_award_object_id__del_field_award_content_type__add_uni.py @@ -0,0 +1,296 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting field 'Award.object_id' + db.delete_column('forum_award', 'object_id') + + # Deleting field 'Award.content_type' + db.delete_column('forum_award', 'content_type_id') + + # Adding unique constraint on 'Award', fields ['action'] + db.create_unique('forum_award', ['action_id']) + + # Deleting field 'Badge.multiple' + db.delete_column('forum_badge', 'multiple') + + # Deleting field 'Badge.name' + db.delete_column('forum_badge', 'name') + + # Deleting field 'Badge.slug' + db.delete_column('forum_badge', 'slug') + + # Deleting field 'Badge.description' + db.delete_column('forum_badge', 'description') + + + def backwards(self, orm): + + # Adding field 'Award.object_id' + db.add_column('forum_award', 'object_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=1), keep_default=False) + + # Adding field 'Award.content_type' + db.add_column('forum_award', 'content_type', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['contenttypes.ContentType']), keep_default=False) + + # Removing unique constraint on 'Award', fields ['action'] + db.delete_unique('forum_award', ['action_id']) + + # Adding field 'Badge.multiple' + db.add_column('forum_badge', 'multiple', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False) + + # Adding field 'Badge.name' + db.add_column('forum_badge', 'name', self.gf('django.db.models.fields.CharField')(default=1, max_length=50), keep_default=False) + + # Adding field 'Badge.slug' + db.add_column('forum_badge', 'slug', self.gf('django.db.models.fields.SlugField')(blank=True, default=1, max_length=50, db_index=True), keep_default=False) + + # Adding field 'Badge.description' + db.add_column('forum_badge', 'description', self.gf('django.db.models.fields.CharField')(default=1, max_length=300), keep_default=False) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Badge']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'object_name': 'Badge'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}), + 'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.flag': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'deleted': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'deleted_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'extra_node'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_moderation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'moderated_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 3, 11, 46, 22, 80000)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'object_name': 'Tag'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 4, 11, 46, 28, 428000)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + } + } + + complete_apps = ['forum'] diff --git a/forum/models/__init__.py b/forum/models/__init__.py index 5b6414a..2c9c997 100644 --- a/forum/models/__init__.py +++ b/forum/models/__init__.py @@ -1,11 +1,11 @@ -from question import Question ,QuestionRevision, FavoriteQuestion, QuestionSubscription +from question import Question ,QuestionRevision, QuestionSubscription from answer import Answer, AnswerRevision from tag import Tag, MarkedTag -from meta import Vote, FlaggedItem -from user import User, Activity, ValidationHash, AuthKeyUserAssociation, SubscriptionSettings -from repute import Badge, Award, Repute -from node import Node, NodeRevision, NodeMetaClass, AnonymousNode +from user import User, ValidationHash, AuthKeyUserAssociation, SubscriptionSettings +from node import Node, NodeRevision, NodeMetaClass from comment import Comment +from action import Action, ActionRepute +from meta import Vote, Flag, Badge, Award from utils import KeyValue try: @@ -16,20 +16,13 @@ except: from base import * -def is_new(sender, instance, **kwargs): - try: - instance._is_new = not bool(instance.id) - except: - pass - -pre_save.connect(is_new) - __all__ = [ - 'Node', 'NodeRevision', 'AnonymousNode', - 'Question', 'FavoriteQuestion', 'QuestionSubscription', 'QuestionRevision', + 'Node', 'NodeRevision', + 'Question', 'QuestionSubscription', 'QuestionRevision', 'Answer', 'AnswerRevision', - 'Tag', 'Comment', 'Vote', 'FlaggedItem', 'MarkedTag', 'Badge', 'Award', 'Repute', - 'Activity', 'ValidationHash', 'AuthKeyUserAssociation', 'SubscriptionSettings', 'KeyValue', 'User', + 'Tag', 'Comment', 'MarkedTag', 'Badge', 'Award', + 'ValidationHash', 'AuthKeyUserAssociation', 'SubscriptionSettings', 'KeyValue', 'User', + 'Action', 'ActionRepute', 'Vote', 'Flag' ] @@ -40,4 +33,5 @@ for k, v in get_modules_script_classes('models', models.Model).items(): __all__.append(k) exec "%s = v" % k -NodeMetaClass.setup_relations() \ No newline at end of file +NodeMetaClass.setup_relations() +BaseMetaClass.setup_denormalizes() \ No newline at end of file diff --git a/forum/models/action.py b/forum/models/action.py new file mode 100644 index 0000000..10eb165 --- /dev/null +++ b/forum/models/action.py @@ -0,0 +1,268 @@ +from django.utils.translation import ugettext as _ +from utils import PickledObjectField +from threading import Thread +from base import * +import re + +class ActionManager(models.Manager): + use_for_related_fields = True + + def get_query_set(self): + qs = super(ActionManager, self).get_query_set().filter(canceled=False) + + if self.model is not Action: + return qs.filter(action_type=self.model.get_type()) + else: + return qs + + def get(self, *args, **kwargs): + action = super(ActionManager, self).get(*args, **kwargs) + if self.model == Action: + return action.leaf() + return action + + def get_for_types(self, types, *args, **kwargs): + kwargs['action_type__in'] = [t.get_type() for t in types] + return self.get(*args, **kwargs) + + + +class Action(models.Model): + user = models.ForeignKey('User', related_name="actions") + ip = models.CharField(max_length=16) + node = models.ForeignKey('Node', null=True, related_name="actions") + action_type = models.CharField(max_length=16) + action_date = models.DateTimeField(default=datetime.datetime.now) + + extra = PickledObjectField() + + canceled = models.BooleanField(default=False) + canceled_by = models.ForeignKey('User', null=True, related_name="canceled_actions") + canceled_at = models.DateTimeField(null=True) + canceled_ip = models.CharField(max_length=16) + + hooks = {} + + objects = ActionManager() + + @property + def at(self): + return self.action_date + + @property + def by(self): + return self.user + + def repute_users(self): + pass + + def process_data(self, **data): + pass + + def process_action(self): + pass + + def cancel_action(self): + pass + + def describe(self, viewer=None): + return "" + + def repute(self, user, value): + repute = ActionRepute(action=self, user=user, value=value) + repute.save() + return repute + + def cancel_reputes(self): + for repute in self.reputes.all(): + cancel = ActionRepute(action=self, user=repute.user, value=(-repute.value), by_canceled=True) + cancel.save() + + def leaf(self): + leaf_cls = ActionProxyMetaClass.types.get(self.action_type, None) + + if leaf_cls is None: + return self + + leaf = leaf_cls() + leaf.__dict__ = self.__dict__ + return leaf + + @classmethod + def get_type(cls): + return re.sub(r'action$', '', cls.__name__.lower()) + + def save(self, data=None, *args, **kwargs): + isnew = False + + if not self.id: + self.action_type = self.__class__.get_type() + isnew = True + + if data: + self.process_data(**data) + + super(Action, self).save(*args, **kwargs) + + if isnew: + if (self.node is None) or (not self.node.wiki): + self.repute_users() + self.process_action() + self.trigger_hooks(True) + + return self + + def delete(self): + self.cancel_action() + super(Action, self).delete() + + def cancel(self, user=None, ip=None): + if not self.canceled: + self.canceled = True + self.canceled_at = datetime.datetime.now() + self.canceled_by = (user is None) and self.user or user + if ip: + self.canceled_ip = ip + self.save() + self.cancel_reputes() + self.cancel_action() + #self.trigger_hooks(False) + + @classmethod + def get_current(cls, **kwargs): + kwargs['canceled'] = False + + try: + return cls.objects.get(**kwargs) + except cls.MultipleObjectsReturned: + logging.error("Got multiple values for action %s with args %s", cls.__name__, + ", ".join(["%s='%s'" % i for i in kwargs.items()])) + raise + except cls.DoesNotExist: + return None + + @classmethod + def hook(cls, fn): + if not Action.hooks.get(cls, None): + Action.hooks[cls] = [] + + Action.hooks[cls].append(fn) + + def trigger_hooks(self, new=True): + thread = Thread(target=trigger_hooks_threaded, args=[self, Action.hooks, new]) + thread.setDaemon(True) + thread.start() + + class Meta: + app_label = 'forum' + +def trigger_hooks_threaded(action, hooks, new): + for cls, hooklist in hooks.items(): + if isinstance(action, cls): + for hook in hooklist: + try: + hook(action=action, new=new) + except Exception, e: + logging.error("Error in %s hook: %s" % (cls.__name__, str(e))) + +class ActionProxyMetaClass(models.Model.__metaclass__): + types = {} + + def __new__(cls, *args, **kwargs): + new_cls = super(ActionProxyMetaClass, cls).__new__(cls, *args, **kwargs) + cls.types[new_cls.get_type()] = new_cls + + class Meta: + proxy = True + + new_cls.Meta = Meta + return new_cls + +class ActionProxy(Action): + __metaclass__ = ActionProxyMetaClass + + def friendly_username(self, viewer, user): + return (viewer == user) and _('You') or user.username + + def friendly_ownername(self, owner, user): + return (owner == user) and _('your') or user.username + + def hyperlink(self, url, title, **attrs): + return '%s' % (url, " ".join('%s="%s"' % i for i in attrs.items()), title) + + def describe_node(self, viewer, node): + node_link = self.hyperlink(node.get_absolute_url(), node.headline) + + if node.parent: + node_desc = _("on %(link)s") % {'link': node_link} + else: + node_desc = node_link + + return _("%(user)s %(node_name)s %(node_desc)s") % { + 'user': self.hyperlink(node.author.get_profile_url(), self.friendly_ownername(viewer, node.author)), + 'node_name': node.friendly_name, 'node_desc': node_desc, + } + + class Meta: + proxy = True + +class DummyActionProxy(Action): + __metaclass__ = ActionProxyMetaClass + + hooks = [] + + def process_data(self, **data): + pass + + def process_action(self): + pass + + def save(self, data=None): + self.process_action() + + if data: + self.process_data(**data) + + for hook in self.__class__.hooks: + hook(self, True) + + @classmethod + def get_type(cls): + return re.sub(r'action$', '', cls.__name__.lower()) + + @classmethod + def hook(cls, fn): + cls.hooks.append(fn) + + + +class ActionRepute(models.Model): + action = models.ForeignKey(Action, related_name='reputes') + date = models.DateTimeField(default=datetime.datetime.now) + user = models.ForeignKey('User', related_name='reputes') + value = models.IntegerField(default=0) + by_canceled = models.BooleanField(default=False) + + @property + def positive(self): + if self.value > 0: return self.value + return 0 + + @property + def negative(self): + if self.value < 0: return self.value + return 0 + + def save(self, *args, **kwargs): + super(ActionRepute, self).save(*args, **kwargs) + self.user.reputation = models.F('reputation') + self.value + self.user.save() + + def delete(self): + self.user.reputation = models.F('reputation') - self.value + self.user.save() + super(ActionRepute, self).delete() + + class Meta: + app_label = 'forum' + diff --git a/forum/models/answer.py b/forum/models/answer.py index 01e0aae..090e19d 100644 --- a/forum/models/answer.py +++ b/forum/models/answer.py @@ -1,79 +1,23 @@ from base import * +from django.utils.translation import ugettext as _ -from question import Question +class Answer(Node): + friendly_name = _("answer") -class Answer(QandA): - accepted = models.BooleanField(default=False) - accepted_at = models.DateTimeField(null=True, blank=True) - accepted_by = models.ForeignKey(User, null=True) + class Meta(Node.Meta): + proxy = True - class Meta(QandA.Meta): - db_table = u'answer' + @property + def accepted(self): + return self.extra_action @property def headline(self): return self.question.headline - def mark_accepted(self, user): - if not self.accepted and not self.question.answer_accepted: - self.accepted = True - self.accepted_at = datetime.datetime.now() - self.accepted_by = user - self.save() - self.question.accepted_answer = self - self.question.save() - answer_accepted.send(sender=Answer, answer=self, user=user) - return True - - return False - - def unmark_accepted(self, user): - if self.accepted: - self.accepted = False - self.save() - self.question.accepted_answer = None - self.question.save() - answer_accepted_canceled.send(sender=Answer, answer=self, user=user) - return True - - return False - - def _update_question_answer_count(self, diff): - self.question.answer_count = self.question.answer_count + diff - self.question.save() - - def activate_revision(self, user, revision): - super(Answer, self).activate_revision(user, revision) - self.question.update_last_activity(user) - - def mark_deleted(self, user): - if super(Answer, self).mark_deleted(user): - self._update_question_answer_count(-1) - - def unmark_deleted(self): - if super(Answer, self).unmark_deleted(): - self._update_question_answer_count(1) - - def get_latest_revision(self): - return self.revisions.all()[0] - - def get_question_title(self): - return self.question.title - def get_absolute_url(self): return '%s#%s' % (self.question.get_absolute_url(), self.id) - def save(self, *args, **kwargs): - super(Answer, self).save(*args, **kwargs) - - if self._is_new: - self._update_question_answer_count(1) - - def __unicode__(self): - return self.html - -answer_accepted = django.dispatch.Signal(providing_args=['answer', 'user']) -answer_accepted_canceled = django.dispatch.Signal(providing_args=['answer', 'user']) class AnswerRevision(NodeRevision): class Meta: diff --git a/forum/models/base.py b/forum/models/base.py index 43668d9..56124a8 100644 --- a/forum/models/base.py +++ b/forum/models/base.py @@ -20,15 +20,43 @@ import logging from forum.const import * +class LazyQueryList(object): + def __init__(self, model, items): + self.model = model + self.items = items + + def __getitem__(self, k): + return self.model.objects.get(id=self.items[k]) + + def __iter__(self): + for id in self.items: + yield self.model.objects.get(id=id) + + def __len__(self): + return len(self.items) + +class CachedQuerySet(models.query.QuerySet): + def lazy(self): + if len(self.query.extra) == 0: + return LazyQueryList(self.model, list(self.values_list('id', flat=True))) + else: + return self + +from action import Action + class CachedManager(models.Manager): use_for_related_fields = True int_cache_re = re.compile('^_[\w_]+cache$') + def get_query_set(self): + return CachedQuerySet(self.model) + def cache_obj(self, obj): int_cache_keys = [k for k in obj.__dict__.keys() if self.int_cache_re.match(k)] - + d = obj.__dict__ for k in int_cache_keys: - del obj.__dict__[k] + if not isinstance(obj.__dict__[k], Action): + del obj.__dict__[k] cache.set(self.model.cache_key(obj.id), obj, 60 * 60) @@ -59,19 +87,54 @@ class CachedManager(models.Manager): except: return super(CachedManager, self).get_or_create(*args, **kwargs) -denorm_update = django.dispatch.Signal(providing_args=["instance", "field", "old", "new"]) -class DenormalizedField(models.IntegerField): - __metaclass__ = models.SubfieldBase +class DenormalizedField(object): + def __init__(self, manager, **kwargs): + self.manager = manager + self.filter = kwargs + + def setup_class(self, cls, name): + dict_name = '_%s_cache_' % name + + def getter(inst): + val = inst.__dict__.get(dict_name, None) + + if val is None: + val = getattr(inst, self.manager).filter(**self.filter).count() + inst.__dict__[dict_name] = val + inst.__class__.objects.cache_obj(inst) + + return val + + def reset_cache(inst): + inst.__dict__.pop(dict_name, None) + inst.__class__.objects.cache_obj(inst) + + cls.add_to_class(name, property(getter)) + cls.add_to_class("reset_%s_cache" % name, reset_cache) + + +class BaseMetaClass(models.Model.__metaclass__): + to_denormalize = [] + + def __new__(cls, *args, **kwargs): + new_cls = super(BaseMetaClass, cls).__new__(cls, *args, **kwargs) - def contribute_to_class(self, cls, name): - super (DenormalizedField, self).contribute_to_class(cls, name) - if not hasattr(cls, '_denormalizad_fields'): - cls._denormalizad_fields = [] + BaseMetaClass.to_denormalize.extend( + [(new_cls, name, field) for name, field in new_cls.__dict__.items() if isinstance(field, DenormalizedField)] + ) + + return new_cls + + @classmethod + def setup_denormalizes(cls): + for new_cls, name, field in BaseMetaClass.to_denormalize: + field.setup_class(new_cls, name) - cls._denormalizad_fields.append(name) class BaseModel(models.Model): + __metaclass__ = BaseMetaClass + objects = CachedManager() class Meta: @@ -92,35 +155,29 @@ class BaseModel(models.Model): if self._original_state.get(k, missing) == missing or self._original_state[k] != v]) def save(self, *args, **kwargs): - put_back = None - - if hasattr(self.__class__, '_denormalizad_fields'): - dirty = self.get_dirty_fields() - put_back = [f for f in self.__class__._denormalizad_fields if f in dirty] - - if put_back: - for n in put_back: - self.__dict__[n] = models.F(n) + (self.__dict__[n] - dirty[n]) - - super(BaseModel, self).save(*args, **kwargs) + put_back = [k for k, v in self.__dict__.items() if isinstance(v, models.expressions.ExpressionNode)] + super(BaseModel, self).save() if put_back: try: self.__dict__.update( self.__class__.objects.filter(id=self.id).values(*put_back)[0] ) - for f in put_back: - denorm_update.send(sender=self.__class__, instance=self, field=f, - old=self._original_state[f], new=self.__dict__[f]) except: - #todo: log this properly - pass + logging.error("Unable to read %s from %s" % (", ".join(put_back), self.__class__.__name__)) + self.uncache() self._original_state = dict(self.__dict__) + self.cache() + + def cache(self): self.__class__.objects.cache_obj(self) - def delete(self): + def uncache(self): cache.delete(self.cache_key(self.pk)) + + def delete(self): + self.uncache() super(BaseModel, self).delete() @@ -170,8 +227,6 @@ class UserContent(models.Model): app_label = 'forum' -marked_deleted = django.dispatch.Signal(providing_args=["instance", "deleted_by"]) - class DeletableContent(models.Model): deleted = models.BooleanField(default=False) deleted_at = models.DateTimeField(null=True, blank=True) @@ -189,7 +244,6 @@ class DeletableContent(models.Model): self.deleted_at = datetime.datetime.now() self.deleted_by = user self.save() - marked_deleted.send(sender=self.__class__, instance=self, deleted_by=user) return True else: return False @@ -223,19 +277,6 @@ class CancelableContent(models.Model): from node import Node, NodeRevision -class QandA(Node): - wiki = models.BooleanField(default=False) - wikified_at = models.DateTimeField(null=True, blank=True) - - class Meta: - abstract = True - app_label = 'forum' - - def wikify(self): - if not self.wiki: - self.wiki = True - self.wikified_at = datetime.datetime.now() - self.save() diff --git a/forum/models/comment.py b/forum/models/comment.py index a2e7425..a70d474 100644 --- a/forum/models/comment.py +++ b/forum/models/comment.py @@ -1,7 +1,10 @@ from base import * +from django.utils.translation import ugettext as _ import re class Comment(Node): + friendly_name = _("comment") + class Meta(Node.Meta): ordering = ('-added_at',) proxy = True @@ -13,7 +16,10 @@ class Comment(Node): @property def comment(self): - return self.body + if settings.FORM_ALLOW_MARKDOWN_IN_COMMENTS: + return self.as_markdown('limitedsyntax') + else: + return self.body @property def headline(self): @@ -26,21 +32,16 @@ class Comment(Node): def save(self, *args, **kwargs): super(Comment,self).save(*args, **kwargs) - if self._is_new: - self._update_parent_comment_count(1) - - try: - ping_google() - except Exception: - logging.debug('problem pinging google did you register your sitemap with google?') + if not self.id: + self.parent.reset_comment_count_cache() def mark_deleted(self, user): if super(Comment, self).mark_deleted(user): - self._update_parent_comment_count(-1) + self.parent.reset_comment_count_cache() def unmark_deleted(self): if super(Comment, self).unmark_deleted(): - self._update_parent_comment_count(1) + self.parent.reset_comment_count_cache() def is_reply_to(self, user): inreply = re.search('@\w+', self.body) diff --git a/forum/models/meta.py b/forum/models/meta.py index 86a479c..1498935 100644 --- a/forum/models/meta.py +++ b/forum/models/meta.py @@ -1,75 +1,86 @@ -from base import * - -class Vote(MetaContent, CancelableContent, UserContent): - VOTE_UP = +1 - VOTE_DOWN = -1 - VOTE_CHOICES = ( - (VOTE_UP, u'Up'), - (VOTE_DOWN, u'Down'), - ) - - vote = models.SmallIntegerField(choices=VOTE_CHOICES) - voted_at = models.DateTimeField(default=datetime.datetime.now) - - active = ActiveObjectManager() - - class Meta(MetaContent.Meta): - db_table = u'vote' - - def __unicode__(self): - return '[%s] voted at %s: %s' %(self.user, self.voted_at, self.vote) - - def _update_post_vote_count(self, diff): - post = self.node.leaf - field = self.vote == 1 and 'vote_up_count' or 'vote_down_count' - post.__dict__[field] = post.__dict__[field] + diff - post.save() - - def cancel(self): - if super(Vote, self).cancel(): - self._update_post_vote_count(-1) - - def save(self, *args, **kwargs): - super(Vote, self).save(*args, **kwargs) - if self._is_new: - self._update_post_vote_count(1) - - def is_upvote(self): - return self.vote == self.VOTE_UP - - def is_downvote(self): - return self.vote == self.VOTE_DOWN - - -class FlaggedItem(MetaContent, UserContent): - flagged_at = models.DateTimeField(default=datetime.datetime.now) - reason = models.CharField(max_length=300, null=True) - canceled = models.BooleanField(default=False) - - active = ActiveObjectManager() - - class Meta(MetaContent.Meta): - db_table = u'flagged_item' - - def __unicode__(self): - return '[%s] flagged at %s' %(self.user, self.flagged_at) - - def _update_post_flag_count(self, diff): - post = self.node - post.offensive_flag_count = post.offensive_flag_count + diff - post.save() - - def save(self, *args, **kwargs): - super(FlaggedItem, self).save(*args, **kwargs) - if self._is_new: - self._update_post_flag_count(1) - - def cancel(self): - if not self.canceled: - self.canceled = True - self.save() - self._update_post_flag_count(-1) - - - - +from django.utils.translation import ugettext as _ +from base import * + +class Vote(models.Model): + user = models.ForeignKey(User, related_name="votes") + node = models.ForeignKey(Node, related_name="votes") + value = models.SmallIntegerField() + action = models.ForeignKey(Action, unique=True, related_name="vote") + voted_at = models.DateTimeField(default=datetime.datetime.now) + + class Meta: + app_label = 'forum' + unique_together = ('user', 'node') + + +class Flag(models.Model): + user = models.ForeignKey(User, related_name="flags") + node = models.ForeignKey(Node, related_name="flags") + reason = models.CharField(max_length=300) + action = models.ForeignKey(Action, unique=True, related_name="flag") + flagged_at = models.DateTimeField(default=datetime.datetime.now) + + class Meta: + app_label = 'forum' + unique_together = ('user', 'node') + +class BadgeManager(models.Manager): + use_for_related_fields = True + + def get(self, *args, **kwargs): + try: + pk = [v for (k,v) in kwargs.items() if k in ('pk', 'pk__exact', 'id', 'id__exact')][0] + except: + return super(BadgeManager, self).get(*args, **kwargs) + + from forum.badges.base import BadgesMeta + badge = BadgesMeta.by_id.get(pk, None) + if not badge: + return super(BadgeManager, self).get(*args, **kwargs) + return badge.ondb + +class Badge(models.Model): + GOLD = 1 + SILVER = 2 + BRONZE = 3 + + type = models.SmallIntegerField() + cls = models.CharField(max_length=50, null=True) + awarded_count = models.PositiveIntegerField(default=0) + + awarded_to = models.ManyToManyField(User, through='Award', related_name='badges') + + objects = BadgeManager() + + @property + def name(self): + cls = self.__dict__.get('_class', None) + return cls and cls.name or _("Unknown") + + @property + def description(self): + cls = self.__dict__.get('_class', None) + return cls and cls.description or _("No description available") + + @models.permalink + def get_absolute_url(self): + return ('badge', [], {'id': self.id, 'slug': slugify(self.name)}) + + class Meta: + app_label = 'forum' + + +class Award(models.Model): + user = models.ForeignKey(User) + badge = models.ForeignKey('Badge', related_name="awards") + node = models.ForeignKey(Node, null=True) + + awarded_at = models.DateTimeField(default=datetime.datetime.now) + + trigger = models.ForeignKey(Action, related_name="awards", null=True) + action = models.ForeignKey(Action, related_name="award", unique=True) + + + class Meta: + unique_together = ('user', 'badge', 'node') + app_label = 'forum' \ No newline at end of file diff --git a/forum/models/node.py b/forum/models/node.py index a92dee9..a7e122e 100644 --- a/forum/models/node.py +++ b/forum/models/node.py @@ -1,8 +1,9 @@ -from akismet import * +from forum.akismet import * from base import * from tag import Tag import markdown +from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe from django.utils.html import strip_tags from forum.utils.html import sanitize_html @@ -19,7 +20,10 @@ class NodeContent(models.Model): @property def html(self): - return mark_safe(sanitize_html(markdown.markdown(self.body))) + return self.as_markdown() + + def as_markdown(self, *extensions): + return mark_safe(sanitize_html(markdown.markdown(self.body, extensions=extensions))) @property def headline(self): @@ -38,14 +42,14 @@ class NodeContent(models.Model): abstract = True app_label = 'forum' -class NodeMetaClass(models.Model.__metaclass__): +class NodeMetaClass(BaseMetaClass): types = {} def __new__(cls, *args, **kwargs): new_cls = super(NodeMetaClass, cls).__new__(cls, *args, **kwargs) if not new_cls._meta.abstract and new_cls.__name__ is not 'Node': - NodeMetaClass.types[new_cls.__name__.lower()] = new_cls + NodeMetaClass.types[new_cls.get_type()] = new_cls return new_cls @@ -59,10 +63,7 @@ class NodeMetaClass(models.Model.__metaclass__): name = node_cls.__name__.lower() def children(self): - if node_cls._meta.proxy: - return node_cls.objects.filter(node_type=name, parent=self) - else: - return node_cls.objects.filter(parent=self) + return node_cls.objects.filter(parent=self) def parent(self): p = self.__dict__.get('_%s_cache' % name, None) @@ -77,35 +78,82 @@ class NodeMetaClass(models.Model.__metaclass__): Node.add_to_class(name, property(parent)) -node_create = django.dispatch.Signal(providing_args=['instance']) -node_edit = django.dispatch.Signal(providing_args=['instance']) +class NodeManager(CachedManager): + use_for_related_fields = True -class Node(BaseModel, NodeContent, DeletableContent): - __metaclass__ = NodeMetaClass + def get_query_set(self): + qs = super(NodeManager, self).get_query_set() + + if self.model is not Node: + return qs.filter(node_type=self.model.get_type()) + else: + return qs + + def get(self, *args, **kwargs): + node = super(NodeManager, self).get(*args, **kwargs) + cls = NodeMetaClass.types.get(node.node_type, None) + + if cls and node.__class__ is not cls: + return node.leaf + return node + + def get_for_types(self, types, *args, **kwargs): + kwargs['node_type__in'] = [t.get_type() for t in types] + return self.get(*args, **kwargs) - node_type = models.CharField(max_length=16, default='node') - parent = models.ForeignKey('Node', related_name='children', null=True) - abs_parent = models.ForeignKey('Node', related_name='all_children', null=True) - added_at = models.DateTimeField(default=datetime.datetime.now) +class Node(BaseModel, NodeContent): + __metaclass__ = NodeMetaClass - tags = models.ManyToManyField('Tag', related_name='%(class)ss') + node_type = models.CharField(max_length=16, default='node') + parent = models.ForeignKey('Node', related_name='children', null=True) + abs_parent = models.ForeignKey('Node', related_name='all_children', null=True) - score = DenormalizedField(default=0) - vote_up_count = DenormalizedField(default=0) - vote_down_count = models.IntegerField(default=0) + added_at = models.DateTimeField(default=datetime.datetime.now) + score = models.IntegerField(default=0) - comment_count = DenormalizedField(default=0) - offensive_flag_count = DenormalizedField(default=0) + deleted = models.ForeignKey('Action', null=True, unique=True, related_name="deleted_node") + in_moderation = models.ForeignKey('Action', null=True, unique=True, related_name="moderated_node") + last_edited = models.ForeignKey('Action', null=True, unique=True, related_name="edited_node") - last_edited_at = models.DateTimeField(null=True, blank=True) - last_edited_by = models.ForeignKey(User, null=True, blank=True, related_name='last_edited_%(class)ss') + last_activity_by = models.ForeignKey(User, null=True) + last_activity_at = models.DateTimeField(null=True, blank=True) + tags = models.ManyToManyField('Tag', related_name='%(class)ss') active_revision = models.OneToOneField('NodeRevision', related_name='active', null=True) + extra_ref = models.ForeignKey('Node', null=True) + extra_count = models.IntegerField(default=0) + extra_action = models.ForeignKey('Action', null=True, related_name="extra_node") + + marked = models.BooleanField(default=False) + wiki = models.BooleanField(default=False) + + comment_count = DenormalizedField("children", node_type="comment", canceled=False) + flag_count = DenormalizedField("flags") + + friendly_name = _("post") + + objects = NodeManager() + + @classmethod + def cache_key(cls, pk): + return '%s.node:%s' % (settings.APP_URL, pk) + + @classmethod + def get_type(cls): + return cls.__name__.lower() + @property def leaf(self): - return NodeMetaClass.types[self.node_type].objects.get(id=self.id) + leaf_cls = NodeMetaClass.types.get(self.node_type, None) + + if leaf_cls is None: + return self + + leaf = leaf_cls() + leaf.__dict__ = self.__dict__ + return leaf @property def absolute_parent(self): @@ -118,40 +166,40 @@ class Node(BaseModel, NodeContent, DeletableContent): def summary(self): return strip_tags(self.html)[:300] - def create_revision(self, user, **kwargs): - revision = NodeRevision(author=user, **kwargs) - - if not self.id: - self.author = user - self.save() - revision.revision = 1 - else: - revision.revision = self.revisions.aggregate(last=models.Max('revision'))['last'] + 1 + def update_last_activity(self, user): + self.last_activity_by = user + self.last_activity_at = datetime.datetime.now() - revision.node_id = self.id + if self.parent: + self.parent.update_last_activity(user) + + def _create_revision(self, user, number, **kwargs): + revision = NodeRevision(author=user, revision=number, node=self, **kwargs) revision.save() - self.activate_revision(user, revision) + return revision + + def create_revision(self, user, action=None, **kwargs): + number = self.revisions.aggregate(last=models.Max('revision'))['last'] + 1 + revision = self._create_revision(user, number, **kwargs) + self.activate_revision(user, revision, action) + return revision - def activate_revision(self, user, revision): + def activate_revision(self, user, revision, action=None): self.title = revision.title self.tagnames = revision.tagnames self.body = revision.body - old_revision = self.active_revision self.active_revision = revision + self.update_last_activity(user) - if not old_revision: - signal = node_create - else: - self.last_edited_at = datetime.datetime.now() - self.last_edited_by = user - signal = node_edit + if action: + self.last_edited = action self.save() - signal.send(sender=self.__class__, instance=self) def get_tag_list_if_changed(self): dirty = self.get_dirty_fields() + active_user = self.last_edited and self.last_edited.by or self.author if 'tagnames' in dirty: new_tags = self.tagname_list() @@ -168,7 +216,7 @@ class Node(BaseModel, NodeContent, DeletableContent): try: tag = Tag.objects.get(name=name) except: - tag = Tag.objects.create(name=name, created_by=self.last_edited_by or self.author) + tag = Tag.objects.create(name=name, created_by=active_user or self.author) tag_list.append(tag) @@ -182,7 +230,7 @@ class Node(BaseModel, NodeContent, DeletableContent): tag = Tag.objects.get(name=name) tag.used_count = tag.used_count - 1 if tag.used_count == 0: - tag.mark_deleted(self.last_edited_by or self.author) + tag.mark_deleted(active_user) tag.save() return tag_list @@ -191,13 +239,14 @@ class Node(BaseModel, NodeContent, DeletableContent): def save(self, *args, **kwargs): if not self.id: - self.node_type = self.__class__.__name__.lower() + self.node_type = self.get_type() + super(BaseModel, self).save(*args, **kwargs) + self.active_revision = self._create_revision(self.author, 1, title=self.title, tagnames=self.tagnames, body=self.body) + self.update_last_activity(self.author) if self.parent_id and not self.abs_parent_id: self.abs_parent = self.parent.absolute_parent - - self.__dict__['score'] = self.__dict__['vote_up_count'] - self.__dict__['vote_down_count'] - + tags = self.get_tag_list_if_changed() super(Node, self).save(*args, **kwargs) if tags is not None: self.tags = tags @@ -205,8 +254,9 @@ class Node(BaseModel, NodeContent, DeletableContent): @staticmethod def isSpam(comment, data): api = Akismet() - if api.key is None: - print "problem" # raise APIKeyError + + if not api.key: + return False else: if api.comment_check(comment, data): return True @@ -229,11 +279,3 @@ class NodeRevision(BaseModel, NodeContent): app_label = 'forum' -from user import ValidationHash - -class AnonymousNode(Node): - validation_hash = models.ForeignKey(Node, related_name='anonymous_content') - convertible_to = models.CharField(max_length=16, default='node') - - class Meta: - app_label = 'forum' \ No newline at end of file diff --git a/forum/models/question.py b/forum/models/question.py index da8083f..5484016 100644 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -4,29 +4,26 @@ from django.utils.translation import ugettext as _ question_view = django.dispatch.Signal(providing_args=['instance', 'user']) -class Question(QandA): - accepted_answer = models.OneToOneField('Answer', null=True, related_name="question_accepting") - closed = models.BooleanField(default=False) - closed_by = models.ForeignKey(User, null=True, blank=True, related_name='closed_questions') - closed_at = models.DateTimeField(null=True, blank=True) - close_reason = models.SmallIntegerField(choices=CLOSE_REASONS, null=True, blank=True) - subscribers = models.ManyToManyField(User, related_name='subscriptions', through='QuestionSubscription') - - # Denormalised data - answer_count = models.PositiveIntegerField(default=0) - view_count = models.IntegerField(default=0) - favourite_count = models.IntegerField(default=0) - last_activity_at = models.DateTimeField(default=datetime.datetime.now) - last_activity_by = models.ForeignKey(User, related_name='last_active_in_questions', null=True) - - favorited_by = models.ManyToManyField(User, through='FavoriteQuestion', related_name='favorite_questions') - - class Meta(QandA.Meta): - db_table = u'question' +class Question(Node): + class Meta(Node.Meta): + proxy = True + + answer_count = DenormalizedField("children", node_type="answer", deleted=None) + favorite_count = DenormalizedField("actions", action_type="favorite", canceled=False) + + friendly_name = _("question") + + @property + def closed(self): + return self.extra_action + + @property + def view_count(self): + return self.extra_count @property def headline(self): - if self.closed: + if self.marked: return _('[closed] ') + self.title if self.deleted: @@ -36,43 +33,16 @@ class Question(QandA): @property def answer_accepted(self): - return self.accepted_answer is not None + return self.extra_ref is not None - def save(self, *args, **kwargs): - if not self.last_activity_by: - self.last_activity_by = self.author - super(Question, self).save(*args, **kwargs) - - def update_last_activity(self, user): - self.last_activity_by = user - self.last_activity_at = datetime.datetime.now() - self.save() - - def activate_revision(self, user, revision): - super(Question, self).activate_revision(user, revision) - self.update_last_activity(user) + @property + def accepted_answer(self): + return self.extra_ref @models.permalink def get_absolute_url(self): return ('question', (), {'id': self.id, 'slug': django_urlquote(slugify(self.title))}) - def get_answer_count_by_user(self, user_id): - from answer import Answer - query_set = Answer.objects.filter(author__id=user_id) - return query_set.filter(question=self).count() - - def get_question_title(self): - if self.closed: - attr = CONST['closed'] - elif self.deleted: - attr = CONST['deleted'] - else: - attr = None - if attr is not None: - return u'%s %s' % (self.title, attr) - else: - return self.title - def get_revision_url(self): return reverse('question_revisions', args=[self.id]) @@ -82,49 +52,22 @@ class Question(QandA): if related_list is None: related_list = Question.objects.values('id').filter(tags__id__in=[t.id for t in self.tags.all()] - ).exclude(id=self.id).exclude(deleted=True).annotate(frequency=models.Count('id')).order_by('-frequency')[:count] + ).exclude(id=self.id).filter(deleted=None).annotate(frequency=models.Count('id')).order_by('-frequency')[:count] cache.set(cache_key, related_list, 60 * 60) return [Question.objects.get(id=r['id']) for r in related_list] - def __unicode__(self): - return self.title def question_viewed(instance, **kwargs): - instance.view_count += 1 + instance.extra_count += 1 instance.save() question_view.connect(question_viewed) -class FavoriteQuestion(models.Model): - question = models.ForeignKey('Question') - user = models.ForeignKey(User, related_name='user_favorite_questions') - added_at = models.DateTimeField(default=datetime.datetime.now) - - class Meta: - unique_together = ('question', 'user') - app_label = 'forum' - db_table = u'favorite_question' - - def __unicode__(self): - return '[%s] favorited at %s' %(self.user, self.added_at) - - def _update_question_fav_count(self, diff): - self.question.favourite_count = self.question.favourite_count + diff - self.question.save() - - def save(self, *args, **kwargs): - super(FavoriteQuestion, self).save(*args, **kwargs) - if self._is_new: - self._update_question_fav_count(1) - - def delete(self): - self._update_question_fav_count(-1) - super(FavoriteQuestion, self).delete() class QuestionSubscription(models.Model): user = models.ForeignKey(User) - question = models.ForeignKey(Question) + question = models.ForeignKey(Node) auto_subscription = models.BooleanField(default=True) last_view = models.DateTimeField(default=datetime.datetime.now()) diff --git a/forum/models/repute.py b/forum/models/repute.py deleted file mode 100644 index 0c54c1b..0000000 --- a/forum/models/repute.py +++ /dev/null @@ -1,127 +0,0 @@ -from base import * -from django.contrib.contenttypes.models import ContentType -from forum.models import User - -from django.utils.translation import ugettext as _ - -class Badge(BaseModel): - """Awarded for notable actions performed on the site by Users.""" - GOLD = 1 - SILVER = 2 - BRONZE = 3 - TYPE_CHOICES = ( - (GOLD, _('gold')), - (SILVER, _('silver')), - (BRONZE, _('bronze')), - ) - - name = models.CharField(max_length=50) - type = models.SmallIntegerField(choices=TYPE_CHOICES) - slug = models.SlugField(max_length=50, blank=True) - description = models.CharField(max_length=300) - multiple = models.BooleanField(default=False) - # Denormalised data - awarded_count = models.PositiveIntegerField(default=0) - awarded_to = models.ManyToManyField(User, through='Award', related_name='badges') - - class Meta: - app_label = 'forum' - db_table = u'badge' - ordering = ('name',) - unique_together = ('name', 'type') - - def __unicode__(self): - return u'%s: %s' % (self.get_type_display(), self.name) - - def save(self, *args, **kwargs): - if not self.slug: - self.slug = self.name#slugify(self.name) - super(Badge, self).save(*args, **kwargs) - - def get_absolute_url(self): - return '%s%s/' % (reverse('badge', args=[self.id]), self.slug) - - -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 - -class Award(GenericContent, UserContent): - """The awarding of a Badge to a User.""" - badge = models.ForeignKey('Badge', related_name='award_badge') - 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) - - def save(self, *args, **kwargs): - super(Award, self).save(*args, **kwargs) - - if self._is_new: - self.badge.awarded_count += 1 - self.badge.save() - - if self.badge.type == Badge.GOLD: - self.user.gold += 1 - if self.badge.type == Badge.SILVER: - self.user.silver += 1 - if self.badge.type == Badge.BRONZE: - self.user.bronze += 1 - self.user.save() - - class Meta: - #unique_together = ('content_type', 'object_id', 'user', 'badge') - app_label = 'forum' - db_table = u'award' - - -class Repute(MetaContent, CancelableContent, UserContent): - value = models.SmallIntegerField(default=0) - question = models.ForeignKey('Question') - reputed_at = models.DateTimeField(default=datetime.datetime.now) - reputation_type = models.SmallIntegerField(choices=TYPE_REPUTATION) - user_previous_rep = models.IntegerField(default=0) - - def __unicode__(self): - return u'[%s]\' reputation changed at %s' % (self.user.username, self.reputed_at) - - @property - def positive(self): - if self.value > 0: return self.value - return 0 - - @property - def negative(self): - if self.value < 0: return self.value - return 0 - - @property - def reputation(self): - return self.user_previous_rep + self.value - - def cancel(self): - if super(Repute, self).cancel(): - self.user.reputation = self.user.reputation - self.value - self.user.save() - - def save(self, *args, **kwargs): - self.user_previous_rep = self.user.reputation - self.user.reputation = self.user.reputation + self.value - self.user.save() - super(Repute, self).save(*args, **kwargs) - - class Meta: - app_label = 'forum' - db_table = u'repute' diff --git a/forum/models/tag.py b/forum/models/tag.py index 50eb5aa..16f1c6c 100644 --- a/forum/models/tag.py +++ b/forum/models/tag.py @@ -18,7 +18,6 @@ class Tag(BaseModel, DeletableContent): active = ActiveTagManager() class Meta(DeletableContent.Meta): - db_table = u'tag' ordering = ('-used_count', 'name') def __unicode__(self): diff --git a/forum/models/user.py b/forum/models/user.py index abb3989..53b5ee2 100644 --- a/forum/models/user.py +++ b/forum/models/user.py @@ -6,7 +6,8 @@ from django.db.models import Q try: from hashlib import md5 except: - import md5 + from md5 import new as md5 + import string from random import Random @@ -26,7 +27,7 @@ class UserManager(CachedManager): class AnonymousUser(DjangoAnonymousUser): def get_visible_answers(self, question): - return question.answers.filter(deleted=False) + return question.answers.filter(deleted=None) def can_view_deleted_post(self, post): return False @@ -76,18 +77,19 @@ class AnonymousUser(DjangoAnonymousUser): def can_upload_files(self): return False +def true_if_is_super_or_staff(fn): + def decorated(self, *args, **kwargs): + return self.is_superuser or self.is_staff or fn(self, *args, **kwargs) + return decorated + class User(BaseModel, DjangoUser): is_approved = models.BooleanField(default=False) email_isvalid = models.BooleanField(default=False) - email_key = models.CharField(max_length=32, null=True) - reputation = DenormalizedField(default=1) - gold = DenormalizedField(default=0) - silver = DenormalizedField(default=0) - bronze = DenormalizedField(default=0) - - questions_per_page = models.SmallIntegerField(choices=QUESTIONS_PER_PAGE_CHOICES, default=10) - hide_ignored_questions = models.BooleanField(default=False) + reputation = models.PositiveIntegerField(default=0) + gold = models.PositiveIntegerField(default=0) + silver = models.PositiveIntegerField(default=0) + bronze = models.PositiveIntegerField(default=0) last_seen = models.DateTimeField(default=datetime.datetime.now) real_name = models.CharField(max_length=100, blank=True) @@ -95,7 +97,12 @@ class User(BaseModel, DjangoUser): location = models.CharField(max_length=100, blank=True) date_of_birth = models.DateField(null=True, blank=True) about = models.TextField(blank=True) - + + subscriptions = models.ManyToManyField('Node', related_name='subscribers', through='QuestionSubscription') + + vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup") + vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown") + objects = UserManager() @property @@ -104,10 +111,16 @@ class User(BaseModel, DjangoUser): def save(self, *args, **kwargs): if self.reputation < 0: - self.reputation = 1 + self.reputation = 0 + + new = not bool(self.id) super(User, self).save(*args, **kwargs) + if new: + sub_settings = SubscriptionSettings(user=self) + sub_settings.save() + def get_absolute_url(self): return self.get_profile_url() @@ -127,15 +140,13 @@ class User(BaseModel, DjangoUser): profile_link = u'%s' % (self.get_profile_url(),self.username) return mark_safe(profile_link) + def get_visible_answers(self, question): + return question.answers.filter(deleted=None, in_moderation=None) + def get_vote_count_today(self): today = datetime.date.today() - return self.votes.filter(voted_at__range=(today - datetime.timedelta(days=1), today)).count() - - def get_up_vote_count(self): - return self.votes.filter(vote=1).count() - - def get_down_vote_count(self): - return self.votes.filter(vote=-1).count() + return self.actions.filter(canceled=False, action_type__in=("voteup", "votedown"), + action_date__range=(today - datetime.timedelta(days=1), today)).count() def get_reputation_by_upvoted_today(self): today = datetime.datetime.now() @@ -149,130 +160,87 @@ class User(BaseModel, DjangoUser): def get_flagged_items_count_today(self): today = datetime.date.today() - return self.flaggeditems.filter(flagged_at__range=(today - datetime.timedelta(days=1), today)).count() - - def get_visible_answers(self, question): - if self.is_superuser: - return question.answers - else: - return question.answers.filter(models.Q(deleted=False) | models.Q(deleted_by=self)) + return self.actions.filter(canceled=False, action_type="flag", + action_date__range=(today - datetime.timedelta(days=1), today)).count() + @true_if_is_super_or_staff def can_view_deleted_post(self, post): - return self.is_superuser or post.author == self + return post.author == self + @true_if_is_super_or_staff def can_vote_up(self): - return self.reputation >= int(settings.REP_TO_VOTE_UP) or self.is_superuser + return self.reputation >= int(settings.REP_TO_VOTE_UP) + @true_if_is_super_or_staff def can_vote_down(self): - return self.reputation >= int(settings.REP_TO_VOTE_DOWN) or self.is_superuser + return self.reputation >= int(settings.REP_TO_VOTE_DOWN) def can_flag_offensive(self, post=None): if post is not None and post.author == self: return False - return self.is_superuser or self.reputation >= int(settings.REP_TO_FLAG) + return self.is_superuser or self.is_staff or self.reputation >= int(settings.REP_TO_FLAG) + @true_if_is_super_or_staff def can_view_offensive_flags(self, post=None): if post is not None and post.author == self: return True - return self.is_superuser or self.reputation >= int(settings.REP_TO_VIEW_FLAGS) + return self.reputation >= int(settings.REP_TO_VIEW_FLAGS) + @true_if_is_super_or_staff def can_comment(self, post): return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT - ) or self.is_superuser or (post.__class__.__name__ == "Answer" and self == post.question.author) + ) or (post.__class__.__name__ == "Answer" and self == post.question.author) + @true_if_is_super_or_staff def can_like_comment(self, comment): - return self != comment.user and (self.reputation >= int(settings.REP_TO_LIKE_COMMENT) or self.is_superuser) + return self != comment.author and (self.reputation >= int(settings.REP_TO_LIKE_COMMENT)) + @true_if_is_super_or_staff def can_edit_comment(self, comment): - return (comment.user == self and comment.added_at >= datetime.datetime.now() - datetime.timedelta(minutes=60) + return (comment.author == self and comment.added_at >= datetime.datetime.now() - datetime.timedelta(minutes=60) ) or self.is_superuser + @true_if_is_super_or_staff def can_delete_comment(self, comment): - return self == comment.user or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS) or self.is_superuser + return self == comment.author or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS) + @true_if_is_super_or_staff def can_accept_answer(self, answer): - return self.is_superuser or self == answer.question.author + return self == answer.question.author + @true_if_is_super_or_staff def can_edit_post(self, post): - return self.is_superuser or self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS + return self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS ) or (post.wiki and self.reputation >= int(settings.REP_TO_EDIT_WIKI)) + @true_if_is_super_or_staff def can_retag_questions(self): return self.reputation >= int(settings.REP_TO_RETAG) + @true_if_is_super_or_staff def can_close_question(self, question): - return self.is_superuser or (self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN) + return (self == question.author and self.reputation >= int(settings.REP_TO_CLOSE_OWN) ) or self.reputation >= int(settings.REP_TO_CLOSE_OTHERS) + @true_if_is_super_or_staff def can_reopen_question(self, question): - return self.is_superuser or (self == question.author and self.reputation >= settings.REP_TO_REOPEN_OWN) + return self == question.author and self.reputation >= settings.REP_TO_REOPEN_OWN + @true_if_is_super_or_staff def can_delete_post(self, post): - return self.is_superuser or (self == post.author and (post.__class__.__name__ == "Answer" or - not post.answers.filter(~Q(author=self)).count())) + if post.node_type == "comment": + return self.can_delete_comment(post) + + return (self == post.author and (post.__class__.__name__ == "Answer" or + not post.answers.exclude(author=self).count())) + @true_if_is_super_or_staff def can_upload_files(self): - return self.is_superuser or self.reputation >= int(settings.REP_TO_UPLOAD) + return self.reputation >= int(settings.REP_TO_UPLOAD) class Meta: app_label = 'forum' -class Activity(GenericContent): - """ - We keep some history data for user activities - """ - user = models.ForeignKey(User) - activity_type = models.SmallIntegerField(choices=TYPE_ACTIVITY) - active_at = models.DateTimeField(default=datetime.datetime.now) - is_auditted = models.BooleanField(default=False) - - class Meta: - app_label = 'forum' - db_table = u'activity' - - def __unicode__(self): - return u'[%s] was active at %s' % (self.user.username, self.active_at) - - def save(self, *args, **kwargs): - super(Activity, self).save(*args, **kwargs) - if self._is_new: - activity_record.send(sender=self.activity_type, instance=self) - - @property - def node(self): - if self.activity_type in (const.TYPE_ACTIVITY_ANSWER, const.TYPE_ACTIVITY_ASK_QUESTION, - const.TYPE_ACTIVITY_MARK_ANSWER, const.TYPE_ACTIVITY_COMMENT_QUESTION, const.TYPE_ACTIVITY_COMMENT_ANSWER): - return self.content_object.leaf - - if self.activity_type in (const.TYPE_ACTIVITY_UPDATE_ANSWER, const.TYPE_ACTIVITY_UPDATE_QUESTION): - return self.content_object.node.leaf - - raise NotImplementedError() - - @property - def type_as_string(self): - if self.activity_type == const.TYPE_ACTIVITY_ASK_QUESTION: - return _("asked") - elif self.activity_type == const.TYPE_ACTIVITY_ANSWER: - return _("answered") - elif self.activity_type == const.TYPE_ACTIVITY_MARK_ANSWER: - return _("marked an answer") - elif self.activity_type == const.TYPE_ACTIVITY_UPDATE_QUESTION: - return _("edited a question") - elif self.activity_type == const.TYPE_ACTIVITY_COMMENT_QUESTION: - return _("commented a question") - elif self.activity_type == const.TYPE_ACTIVITY_COMMENT_ANSWER: - return _("commented an answer") - elif self.activity_type == const.TYPE_ACTIVITY_UPDATE_ANSWER: - return _("edited an answer") - elif self.activity_type == const.TYPE_ACTIVITY_PRIZE: - return _("received badge") - else: - raise NotImplementedError() - - -activity_record = django.dispatch.Signal(providing_args=['instance']) - class SubscriptionSettings(models.Model): user = models.OneToOneField(User, related_name='subscription_settings') diff --git a/forum/models/utils.py b/forum/models/utils.py index 984a55c..5ac8900 100644 --- a/forum/models/utils.py +++ b/forum/models/utils.py @@ -1,44 +1,84 @@ from django.db import models from django.core.cache import cache from django.conf import settings -#try: -# import cPickle as pickle -#except ImportError: -import pickle -import django.dispatch +from django.utils.encoding import force_unicode + +try: + from cPickle import loads, dumps +except ImportError: + from pickle import loads, dumps + +from copy import deepcopy +from base64 import b64encode, b64decode +from zlib import compress, decompress + class PickledObject(str): - pass + pass + +def dbsafe_encode(value, compress_object=True): + if not compress_object: + value = b64encode(dumps(deepcopy(value))) + else: + value = b64encode(compress(dumps(deepcopy(value)))) + return PickledObject(value) + +def dbsafe_decode(value, compress_object=True): + if not compress_object: + value = loads(b64decode(value)) + else: + value = loads(decompress(b64decode(value))) + return value class PickledObjectField(models.Field): __metaclass__ = models.SubfieldBase + def __init__(self, *args, **kwargs): + self.compress = kwargs.pop('compress', True) + self.protocol = kwargs.pop('protocol', 2) + kwargs.setdefault('null', True) + kwargs.setdefault('editable', False) + super(PickledObjectField, self).__init__(*args, **kwargs) + + def get_default(self): + if self.has_default(): + if callable(self.default): + return self.default() + return self.default + + return super(PickledObjectField, self).get_default() + def to_python(self, value): - if isinstance (value, PickledObject): - return value - - try: - return pickle.loads(value.encode('utf-8')) - except: - return value - - def get_db_prep_save(self, value): if value is not None: - if isinstance(value, PickledObject): - return str(value) - else: - value = pickle.dumps(value) + try: + value = dbsafe_decode(value, self.compress) + except: + if isinstance(value, PickledObject): + raise + return value + def get_db_prep_value(self, value): + if value is not None and not isinstance(value, PickledObject): + value = force_unicode(dbsafe_encode(value, self.compress)) return value + def value_to_string(self, obj): + value = self._get_val_from_obj(obj) + return self.get_db_prep_value(value) + def get_internal_type(self): return 'TextField' + def get_db_prep_lookup(self, lookup_type, value): + if lookup_type not in ['exact', 'in', 'isnull']: + raise TypeError('Lookup type %s is not supported.' % lookup_type) + return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value) + class KeyValueManager(models.Manager): def create_cache_key(self, key): - return "%s:key_value:%s" % (settings.APP_URL, key) + return "%s:keyvalue:%s" % (settings.APP_URL, key) def save_to_cache(self, instance): cache.set(self.create_cache_key(instance.key), instance, 2592000) diff --git a/forum/modules.py b/forum/modules/__init__.py similarity index 97% rename from forum/modules.py rename to forum/modules/__init__.py index 10bbf65..023b464 100644 --- a/forum/modules.py +++ b/forum/modules/__init__.py @@ -7,7 +7,7 @@ from django.conf import settings MODULES_PACKAGE = 'forum_modules' -MODULES_FOLDER = os.path.join(os.path.dirname(__file__), '../' + MODULES_PACKAGE) +MODULES_FOLDER = os.path.join(os.path.dirname(__file__), '../../' + MODULES_PACKAGE) DISABLED_MODULES = getattr(settings, 'DISABLED_MODULES', []) diff --git a/forum/modules/decorators.py b/forum/modules/decorators.py new file mode 100644 index 0000000..17d248b --- /dev/null +++ b/forum/modules/decorators.py @@ -0,0 +1,53 @@ +import inspect + +class DecoratableObject(object): + def __init__(self, fn): + self._callable = fn + + def decorate(self, fn, needs_origin): + origin = self._callable + + if needs_origin: + self._callable = lambda *args, **kwargs: fn(origin, *args, **kwargs) + else: + self._callable = lambda *args, **kwargs: fn(*args, **kwargs) + + def __call__(self, *args, **kwargs): + return self._callable(*args, **kwargs) + + +def decoratable(fn): + return DecoratableObject(fn) + +def decoratable_method(fn): + obj = DecoratableObject(fn) + def decorated(self, *args, **kwargs): + return obj(self, *args, **kwargs) + + decorated.__obj = obj + return decorated + +decoratable.method = decoratable_method + +def decorate(origin, needs_origin=True): + if not isinstance(origin, DecoratableObject): + if hasattr(origin, '__obj'): + def decorator(fn): + origin.__obj.decorate(fn, needs_origin) + return origin + return decorator + + raise Exception('Not an decoratable function: %s' % origin.name) + + def decorator(fn): + origin.decorate(fn, needs_origin) + return origin + + return decorator + + + + + + + diff --git a/forum/reputation.py b/forum/reputation.py deleted file mode 100644 index 71f9d65..0000000 --- a/forum/reputation.py +++ /dev/null @@ -1,101 +0,0 @@ -from django.db.models.signals import post_save -from forum.models.base import mark_canceled -from forum.models.answer import answer_accepted, answer_accepted_canceled - -from forum.models import * -from forum.const import * -import settings - -def on_flagged_item(instance, created, **kwargs): - if not created: - return - - post = instance.content_object.leaf - question = (post.__class__ == Question) and post or post.question - - post.author.reputes.create(value=-int(settings.REP_LOST_BY_FLAGGED), question=question, - reputation_type=TYPE_REPUTATION_LOST_BY_FLAGGED) - - - if post.offensive_flag_count == settings.FLAG_COUNT_TO_HIDE_POST: - post.author.reputes.create(value=-int(settings.REP_LOST_BY_FLAGGED_3_TIMES), - question=question, reputation_type=TYPE_REPUTATION_LOST_BY_FLAGGED_3_TIMES) - - if post.offensive_flag_count == settings.FLAG_COUNT_TO_DELETE_POST: - post.author.reputes.create(value=-int(settings.REP_LOST_BY_FLAGGED_5_TIMES), - question=question, reputation_type=TYPE_REPUTATION_LOST_BY_FLAGGED_5_TIMES) - - post.mark_deleted(User.objects.get_site_owner()) - -post_save.connect(on_flagged_item, sender=FlaggedItem) - -def on_answer_accepted(answer, user, **kwargs): - if user == answer.question.author and not user == answer.author: - user.reputes.create( - value=int(settings.REP_GAIN_BY_ACCEPTING), question=answer.question, - reputation_type=TYPE_REPUTATION_GAIN_BY_ACCEPTING_ANSWER) - - if not user == answer.author: - answer.author.reputes.create( - value=int(settings.REP_GAIN_BY_ACCEPTED), question=answer.question, - reputation_type=TYPE_REPUTATION_GAIN_BY_ANSWER_ACCEPTED) - -answer_accepted.connect(on_answer_accepted) - - -def on_answer_accepted_canceled(answer, user, **kwargs): - if user == answer.accepted_by: - user.reputes.create( - value=-int(settings.REP_LOST_BY_CANCELING_ACCEPTED), question=answer.question, - reputation_type=TYPE_REPUTATION_LOST_BY_CANCELLING_ACCEPTED_ANSWER) - - if not user == answer.author: - answer.author.reputes.create( - value=-int(settings.REP_LOST_BY_ACCEPTED_CANCELED), question=answer.question, - reputation_type=TYPE_REPUTATION_LOST_BY_ACCEPTED_ANSWER_CANCELED) - -answer_accepted_canceled.connect(on_answer_accepted) - - -def on_vote(instance, created, **kwargs): - if created and (instance.content_object.node_type in ("question", "answer") and not instance.content_object.wiki): - post = instance.content_object.leaf - question = (post.__class__ == Question) and post or post.question - - if instance.vote == -1: - instance.user.reputes.create(value=-int(settings.REP_LOST_BY_DOWNVOTING), - question=question, reputation_type=TYPE_REPUTATION_LOST_BY_DOWNVOTING) - - if instance.vote == 1 and post.author.get_reputation_by_upvoted_today() >= int(settings.MAX_REP_BY_UPVOTE_DAY): - return - - repute_type, repute_value = (instance.vote == 1) and ( - TYPE_REPUTATION_GAIN_BY_UPVOTED, int(settings.REP_GAIN_BY_UPVOTED)) or ( - TYPE_REPUTATION_LOST_BY_DOWNVOTED, -int(settings.REP_LOST_BY_DOWNVOTED)) - - post.author.reputes.create(value=repute_value, question=question, reputation_type=repute_type) - -post_save.connect(on_vote, sender=Vote) - - -def on_vote_canceled(instance, **kwargs): - if instance.content_object.node_type in ("question", "answer") and not instance.content_object.wiki: - post = instance.content_object.leaf - question = (post.__class__ == Question) and post or post.question - - if instance.vote == -1: - instance.user.reputes.create(value=int(settings.REP_GAIN_BY_CANCELING_DOWNVOTE), - question=question, reputation_type=TYPE_REPUTATION_GAIN_BY_CANCELING_DOWNVOTE) - - repute_type, repute_value = (instance.vote == 1) and ( - TYPE_REPUTATION_LOST_BY_UPVOTE_CANCELED, -int(settings.REP_LOST_BY_UPVOTE_CANCELED)) or ( - TYPE_REPUTATION_GAIN_BY_DOWNVOTE_CANCELED, int(settings.REP_GAIN_BY_DOWNVOTE_CANCELED)) - - post.author.reputes.create(value=repute_value, question=question, reputation_type=repute_type) - -mark_canceled.connect(on_vote_canceled, sender=Vote) - - - - - diff --git a/forum/settings/__init__.py b/forum/settings/__init__.py index 58ed460..a8530ee 100644 --- a/forum/settings/__init__.py +++ b/forum/settings/__init__.py @@ -18,6 +18,7 @@ from upload import * from about import * from faq import * from form import * +from moderation import * BADGES_SET = SettingSet('badges', _('Badges config'), _("Configure badges on your OSQA site."), 500) diff --git a/forum/settings/base.py b/forum/settings/base.py index dc01577..5bcf5fc 100644 --- a/forum/settings/base.py +++ b/forum/settings/base.py @@ -8,12 +8,32 @@ class SettingSet(list): self.description = description self.weight = weight self.markdown = markdown + class BaseSetting(object): - def __init__(self, name, default, field_context): + @classmethod + def add_to_class(cls, name): + def wrapper(self, *args, **kwargs): + return self.value.__getattribute__(name)(*args, **kwargs) + + setattr(cls, name, wrapper) + + def __init__(self, name, default, set=None, field_context=None): self.name = name self.default = default - self.field_context = field_context + self.field_context = field_context or {} + + if set is not None: + if not set.name in Setting.sets: + Setting.sets[set.name] = set + + Setting.sets[set.name].append(self) + + def __str__(self): + return str(self.value) + + def __unicode__(self): + return unicode(self.value) @property def value(self): @@ -29,112 +49,44 @@ class BaseSetting(object): def set_value(self, new_value): new_value = self._parse(new_value) + self.save(new_value) + + def save(self, value): from forum.models import KeyValue try: kv = KeyValue.objects.get(key=self.name) - old_value = kv.value except: kv = KeyValue(key=self.name) - old_value = self.default - kv.value = new_value + kv.value = value kv.save() - setting_update.send(sender=self, old_value=old_value, new_value=new_value) - def to_default(self): self.set_value(self.default) def _parse(self, value): return value - def __str__(self): - return str(self.value) - - def __unicode__(self): - return unicode(self.value) - - def __nonzero__(self): - return bool(self.value) - - -class StringSetting(BaseSetting): - def _parse(self, value): - if isinstance(value, unicode): - return value.encode('utf8') - else: - return str(value) - - def __unicode__(self): - return unicode(self.value.decode('utf8')) - - def __add__(self, other): - return "%s%s" % (unicode(self), other) - - def __cmp__(self, other): - return cmp(str(self), str(other)) - -class IntegerSetting(BaseSetting): - def _parse(self, value): - return int(value) - - def __int__(self): - return int(self.value) - - def __add__(self, other): - return int(self) + int(other) - - def __sub__(self, other): - return int(self) - int(other) - - def __cmp__(self, other): - return int(self) - int(other) - -class FloatSetting(BaseSetting): - def _parse(self, value): - return float(value) - - def __int__(self): - return int(self.value) - - def __float__(self): - return float(self.value) - - def __add__(self, other): - return float(self) + float(other) - - def __sub__(self, other): - return float(self) - float(other) - - def __cmp__(self, other): - return float(self) - float(other) - -class BoolSetting(BaseSetting): - def _parse(self, value): - return bool(value) class Setting(object): + emulators = {} sets = {} - def __new__(cls, name, default, set=None, field_context={}): - if isinstance(default, bool): - instance = BoolSetting(name, default, field_context) - elif isinstance(default, str): - instance = StringSetting(name, default, field_context) - elif isinstance(default, float): - instance = FloatSetting(name, default, field_context) - elif isinstance(default, int): - instance = IntegerSetting(name, default, field_context) + def __new__(cls, name, default, set=None, field_context=None): + deftype = type(default) + + if deftype in Setting.emulators: + emul = Setting.emulators[deftype] else: - instance = BaseSetting(name, default, field_context) + emul = type(deftype.__name__ + cls.__name__, (BaseSetting,), {}) + fns = [n for n, f in [(p, getattr(deftype, p)) for p in dir(deftype) if not p in dir(cls)] if callable(f)] - if set is not None: - if not set.name in cls.sets: - cls.sets[set.name] = set + for n in fns: + emul.add_to_class(n) + + Setting.emulators[deftype] = emul - cls.sets[set.name].append(instance) + return emul(name, default, set, field_context) - return instance -setting_update = django.dispatch.Signal(providing_args=['old_value', 'new_value']) diff --git a/forum/settings/basic.py b/forum/settings/basic.py index 80c8a62..23427ea 100644 --- a/forum/settings/basic.py +++ b/forum/settings/basic.py @@ -6,7 +6,7 @@ from forms import ImageFormWidget from django.utils.translation import ugettext_lazy as _ from django.forms.widgets import Textarea -BASIC_SET = SettingSet('basic', _('Basic Settings'), _("The basic settings for your application"), 1) +BASIC_SET = SettingSet('basic', _('Basic settings'), _("The basic settings for your application"), 1) APP_LOGO = Setting('APP_LOGO', '/m/default/media/images/logo.png', BASIC_SET, dict( label = _("Application logo"), diff --git a/forum/settings/email.py b/forum/settings/email.py index d95a164..fb49f99 100644 --- a/forum/settings/email.py +++ b/forum/settings/email.py @@ -2,7 +2,7 @@ from base import Setting, SettingSet from django.utils.translation import ugettext_lazy as _ from django.forms.widgets import PasswordInput -EMAIL_SET = SettingSet('email', _('Email Settings'), _("Email server and other email related settings."), 50) +EMAIL_SET = SettingSet('email', _('Email settings'), _("Email server and other email related settings."), 50) EMAIL_HOST = Setting('EMAIL_HOST', '', EMAIL_SET, dict( label = _("Email Server"), diff --git a/forum/settings/extkeys.py b/forum/settings/extkeys.py index a2e8222..abe860b 100644 --- a/forum/settings/extkeys.py +++ b/forum/settings/extkeys.py @@ -8,11 +8,10 @@ label = _("Google sitemap code"), help_text = _("This is the code you get when you register your site at Google webmaster central."), required=False)) -GOOGLE_ANALYTICS_KEY = Setting('GOOGLE_ANALYTICS_KEY', '', EXT_KEYS_SET, dict( +GOOGLE_ANALYTICS_KEY = Setting('GOOGLE_ANALYTICS_KEY', '', EXT_KEYS_SET, dict( label = _("Google analytics key"), help_text = _("Your Google analytics key. You can get one at the Google analytics official website"), required=False)) - WORDPRESS_API_KEY = Setting('WORDPRESS_API_KEY', '', EXT_KEYS_SET, dict( label = _("Wordpress API key"), help_text = _("Your Wordpress API key. You can get one at http://wordpress.com/"), diff --git a/forum/settings/form.py b/forum/settings/form.py index 5cb1aee..7329d5f 100644 --- a/forum/settings/form.py +++ b/forum/settings/form.py @@ -37,4 +37,14 @@ help_text = _("The minimum number of characters a user must enter into the body FORM_MAX_COMMENT_BODY = Setting('FORM_MAX_COMMENT_BODY', 600, FORUM_SET, dict( label = _("Maximum length of comment"), -help_text = _("The maximum number of characters a user can enter into the body of a comment."))) \ No newline at end of file +help_text = _("The maximum number of characters a user can enter into the body of a comment."))) + +FORM_ALLOW_MARKDOWN_IN_COMMENTS = Setting('FORM_ALLOW_MARKDOWN_IN_COMMENTS', True, FORUM_SET, dict( +label = _("Allow markdown in comments"), +help_text = _("Allow users to use markdown in comments."), +required=False)) + +FORM_GRAVATAR_IN_COMMENTS = Setting('FORM_GRAVATAR_IN_COMMENTS', False, FORUM_SET, dict( +label = _("Show author gravatar in comments"), +help_text = _("Show the gravatar image of a comment author."), +required=False)) \ No newline at end of file diff --git a/forum/settings/forms.py b/forum/settings/forms.py index 337dea1..aa5a352 100644 --- a/forum/settings/forms.py +++ b/forum/settings/forms.py @@ -1,9 +1,17 @@ import os from django import forms -from base import Setting, StringSetting, IntegerSetting, BoolSetting, FloatSetting +from base import Setting from django.utils.translation import ugettext as _ from django.core.files.storage import FileSystemStorage +class DummySetting: + pass + +class UnfilteredField(forms.CharField): + def clean(self, value): + return value + + class SettingsSetForm(forms.Form): def __init__(self, set, data=None, *args, **kwargs): if data is None: @@ -12,16 +20,16 @@ class SettingsSetForm(forms.Form): super(SettingsSetForm, self).__init__(data, *args, **kwargs) for setting in set: - if isinstance(setting, StringSetting): + if isinstance(setting, Setting.emulators.get(str, DummySetting)): field = forms.CharField(**setting.field_context) - elif isinstance(setting, FloatSetting): + elif isinstance(setting, Setting.emulators.get(float, DummySetting)): field = forms.FloatField(**setting.field_context) - elif isinstance(setting, IntegerSetting): + elif isinstance(setting, Setting.emulators.get(int, DummySetting)): field = forms.IntegerField(**setting.field_context) - elif isinstance(setting, BoolSetting): + elif isinstance(setting, Setting.emulators.get(bool, DummySetting)): field = forms.BooleanField(**setting.field_context) else: - field = forms.CharField(**setting.field_context) + field = UnfilteredField(**setting.field_context) self.fields[setting.name] = field @@ -60,4 +68,28 @@ class ImageFormWidget(forms.Widget): elif name in data: return data[name] +class StringListWidget(forms.Widget): + def render(self, name, value, attrs=None): + ret = "" + for s in value: + ret += """ +
+ + +
+ """ % {'name': name, 'value': s} + + return """ +
+ %(ret)s +
+
+ """ % dict(name=name, ret=ret) + + def value_from_datadict(self, data, files, name): + if 'submit' in data: + return data.getlist(name) + else: + return data[name] + diff --git a/forum/settings/moderation.py b/forum/settings/moderation.py new file mode 100644 index 0000000..6af5401 --- /dev/null +++ b/forum/settings/moderation.py @@ -0,0 +1,24 @@ +from base import Setting, SettingSet +from forms import StringListWidget + +from django.utils.translation import ugettext_lazy as _ +from django.forms.widgets import Textarea + +MODERATION_SET = SettingSet('moderation', _('Moderation settings'), _("Define the moderation workflow of your site"), 100) + +FLAG_TYPES = Setting('FLAG_TYPES', +["Spam", "Advertising", "Offensive, Abusive, or Inappropriate", "Content violates terms of use", "Copyright Violation", + "Misleading", "Someone is not being nice", "Not relevant/off-topic", "Other"], +MODERATION_SET, dict( +label = _("Flag Reasons"), +help_text = _("Create some flag reasons to use in the flag post popup."), +widget=StringListWidget)) + + +CLOSE_TYPES = Setting('CLOSE_TYPES', +["Duplicate Question", "Question is off-topic or not relevant", "Too subjective and argumentative", + "The question is answered, right answer was accepted", "Problem is not reproducible or outdated", "Other"], +MODERATION_SET, dict( +label = _("Close Reasons"), +help_text = _("Create some close reasons to use in the close question popup."), +widget=StringListWidget)) diff --git a/forum/skins/default/media/images/openid/aol.gif b/forum/skins/default/media/images/openid/aol.gif index decc4f1..dd629cb 100644 Binary files a/forum/skins/default/media/images/openid/aol.gif and b/forum/skins/default/media/images/openid/aol.gif differ diff --git a/forum/skins/default/media/images/openid/blogger.png b/forum/skins/default/media/images/openid/blogger.png new file mode 100644 index 0000000..3c46818 Binary files /dev/null and b/forum/skins/default/media/images/openid/blogger.png differ diff --git a/forum/skins/default/media/images/openid/claimid.png b/forum/skins/default/media/images/openid/claimid.png new file mode 100644 index 0000000..441c0ed Binary files /dev/null and b/forum/skins/default/media/images/openid/claimid.png differ diff --git a/forum/skins/default/media/images/openid/facebook.gif b/forum/skins/default/media/images/openid/facebook.gif index b997b35..9a32529 100644 Binary files a/forum/skins/default/media/images/openid/facebook.gif and b/forum/skins/default/media/images/openid/facebook.gif differ diff --git a/forum/skins/default/media/images/openid/flickr.png b/forum/skins/default/media/images/openid/flickr.png new file mode 100644 index 0000000..6c443e1 Binary files /dev/null and b/forum/skins/default/media/images/openid/flickr.png differ diff --git a/forum/skins/default/media/images/openid/google.gif b/forum/skins/default/media/images/openid/google.gif index 1b6cd07..be451e5 100644 Binary files a/forum/skins/default/media/images/openid/google.gif and b/forum/skins/default/media/images/openid/google.gif differ diff --git a/forum/skins/default/media/images/openid/livejournal.png b/forum/skins/default/media/images/openid/livejournal.png new file mode 100644 index 0000000..9f2f6dd Binary files /dev/null and b/forum/skins/default/media/images/openid/livejournal.png differ diff --git a/forum/skins/default/media/images/openid/myopenid.png b/forum/skins/default/media/images/openid/myopenid.png new file mode 100644 index 0000000..e5df78d Binary files /dev/null and b/forum/skins/default/media/images/openid/myopenid.png differ diff --git a/forum/skins/default/media/images/openid/technorati.png b/forum/skins/default/media/images/openid/technorati.png new file mode 100644 index 0000000..7216641 Binary files /dev/null and b/forum/skins/default/media/images/openid/technorati.png differ diff --git a/forum/skins/default/media/images/openid/twitter.png b/forum/skins/default/media/images/openid/twitter.png index 9a6552d..6178f9c 100644 Binary files a/forum/skins/default/media/images/openid/twitter.png and b/forum/skins/default/media/images/openid/twitter.png differ diff --git a/forum/skins/default/media/images/openid/verisign.png b/forum/skins/default/media/images/openid/verisign.png new file mode 100644 index 0000000..bc5c5f3 Binary files /dev/null and b/forum/skins/default/media/images/openid/verisign.png differ diff --git a/forum/skins/default/media/images/openid/wordpress.png b/forum/skins/default/media/images/openid/wordpress.png new file mode 100644 index 0000000..f261705 Binary files /dev/null and b/forum/skins/default/media/images/openid/wordpress.png differ diff --git a/forum/skins/default/media/images/openid/yahoo.gif b/forum/skins/default/media/images/openid/yahoo.gif index 0f0eb8e..1ebaa7f 100644 Binary files a/forum/skins/default/media/images/openid/yahoo.gif and b/forum/skins/default/media/images/openid/yahoo.gif differ diff --git a/forum/skins/default/media/js/jquery.openid.js b/forum/skins/default/media/js/jquery.openid.js index af7d8cb..a1316c1 100644 --- a/forum/skins/default/media/js/jquery.openid.js +++ b/forum/skins/default/media/js/jquery.openid.js @@ -57,11 +57,6 @@ var providers_small = { label: 'Your Verisign username', url: 'http://{username}.pip.verisignlabs.com/' }, - vidoop: { - name: 'Vidoop', - label: 'Your Vidoop username', - url: 'http://{username}.myvidoop.com/' - }, verisign: { name: 'Verisign', label: 'Your Verisign username', @@ -101,7 +96,7 @@ var openid = { if (providers_small) { openid_btns.append('
'); for (id in providers_small) { - openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico')); + openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.png')); } } diff --git a/forum/skins/default/media/js/osqa.admin.js b/forum/skins/default/media/js/osqa.admin.js new file mode 100644 index 0000000..ce0fc79 --- /dev/null +++ b/forum/skins/default/media/js/osqa.admin.js @@ -0,0 +1,21 @@ +$(function() { + $('.string_list_widget_button').live('click', function() { + $but = $(this); + + if ($but.is('.add')) { + $new = $("
" + + "" + + "" + + "
"); + + $but.before($new); + $new.slideDown('fast'); + } else { + $but.parent().slideUp('fast', function() { + $but.parent().remove(); + }); + } + + return false; + }) +}); \ No newline at end of file diff --git a/forum/skins/default/media/js/osqa.main.js b/forum/skins/default/media/js/osqa.main.js index 6264fb4..06b2cc9 100644 --- a/forum/skins/default/media/js/osqa.main.js +++ b/forum/skins/default/media/js/osqa.main.js @@ -1,4 +1,8 @@ var response_commands = { + refresh_page: function() { + window.location.reload(true) + }, + update_post_score: function(id, inc) { var $score_board = $('#post-' + id + '-score'); var current = parseInt($score_board.html()) @@ -68,7 +72,7 @@ var response_commands = { }); }, - insert_comment: function(post_id, comment_id, comment, username, profile_url, delete_url) { + insert_comment: function(post_id, comment_id, comment, username, profile_url, delete_url, edit_url) { var $container = $('#comments-container-' + post_id); var skeleton = $('#new-comment-skeleton-' + post_id).html().toString(); @@ -76,7 +80,8 @@ var response_commands = { .replace(new RegExp('%COMMENT%', 'g'), comment) .replace(new RegExp('%USERNAME%', 'g'), username) .replace(new RegExp('%PROFILE_URL%', 'g'), profile_url) - .replace(new RegExp('%DELETE_URL%', 'g'), delete_url); + .replace(new RegExp('%DELETE_URL%', 'g'), delete_url) + .replace(new RegExp('%EDIT_URL%', 'g'), edit_url); $container.append(skeleton); @@ -100,6 +105,16 @@ var response_commands = { } }, + unmark_deleted: function(post_type, post_id) { + if (post_type == 'answer') { + var $answer = $('#answer-container-' + post_id); + $answer.removeClass('deleted'); + } else { + var $container = $('#question-table'); + $container.removeClass('deleted'); + } + }, + set_subscription_button: function(text) { $('.subscription_switch').html(text); }, @@ -109,38 +124,127 @@ var response_commands = { } } -function show_message(object, msg) { +function show_message(object, msg, callback) { var div = $('

' + msg + '

(' + 'click to close' + ')
'); div.click(function(event) { - $(".vote-notification").fadeOut("fast", function() { $(this).remove(); }); + $(".vote-notification").fadeOut("fast", function() { + $(this).remove(); + if (callback) { + callback(); + } + }); }); object.parent().append(div); div.fadeIn("fast"); } -function process_ajax_response(data, el) { +function load_prompt(object, url) { + var $box = $('
' + + '' + + '
'); + + + object.parent().append($box); + $box.fadeIn("fast"); + + $box.load(url, function() { + $box.find('.prompt-cancel').click(function() { + $box.fadeOut('fast', function() { + $box.remove(); + }); + return false; + }); + + $box.find('.prompt-submit').click(function() { + start_command(); + $.post(url, {prompt: $box.find('textarea').val()}, function(data) { + $box.fadeOut('fast', function() { + $box.remove(); + }); + process_ajax_response(data, object); + }, 'json'); + return false; + }); + }); +} + +function show_prompt(object, msg, callback) { + var div = $('
' + msg + '
' + + '
' + + '' + + '' + + '
'); + + function fade_out() { + div.fadeOut("fast", function() { div.remove(); }); + } + + div.find('.prompt-cancel').click(fade_out); + + div.find('.prompt-ok').click(function(event) { + callback(div.find('.command-prompt').val()); + fade_out(); + }); + + object.parent().append(div); + div.fadeIn("fast"); +} + +function process_ajax_response(data, el, callback) { if (!data.success && data['error_message'] != undefined) { - show_message(el, data.error_message) + show_message(el, data.error_message, function() {if (callback) callback(true);}); + end_command(false); } else if (typeof data['commands'] != undefined){ for (var command in data.commands) { response_commands[command].apply(null, data.commands[command]) } if (data['message'] != undefined) { - show_message(el, data.message) + show_message(el, data.message, function() {if (callback) callback(false);}) + } else { + if (callback) callback(false); } + end_command(true); + } +} + +var running = false; + +function start_command() { + $('body').append($('
')); + running = true; +} + +function end_command(success) { + if (success) { + $('#command-loader').addClass('success'); + $('#command-loader').fadeOut("slow", function() { + $('#command-loader').remove(); + running = false; + }); + } else { + $('#command-loader').remove(); + running = false; } } $(function() { $('a.ajax-command').live('click', function() { + if (running) return false; + var el = $(this); - $.getJSON(el.attr('href'), function(data) { - process_ajax_response(data, el); - }); + + if (el.is('.withprompt')) { + load_prompt(el, el.attr('href')); + } else { + start_command(); + $.getJSON(el.attr('href'), function(data) { + process_ajax_response(data, el); + }); + } return false }); @@ -149,50 +253,105 @@ $(function() { var $container = $(this); var $form = $container.find('form'); var $textarea = $container.find('textarea'); - var $button = $container.find('input[type="submit"]'); - var $chars_left_message = $('.comment-chars-left'); + var textarea = $textarea.get(0); + var $button = $container.find('.comment-submit'); + var $cancel = $container.find('.comment-cancel'); + var $chars_left_message = $container.find('.comments-chars-left-msg'); + var $chars_togo_message = $container.find('.comments-chars-togo-msg'); var $chars_counter = $container.find('.comments-char-left-count'); var $comment_tools = $container.parent().find('.comment-tools'); var $add_comment_link = $comment_tools.find('.add-comment-link'); var $comments_container = $container.parent().find('.comments-container'); - var max_length = parseInt($chars_counter.html()); + var chars_limits = $chars_counter.html().split('|'); + + var min_length = parseInt(chars_limits[0]); + var max_length = parseInt(chars_limits[1]); + + var warn_length = max_length - 30; + var current_length = 0; var comment_in_form = false; + var interval = null; + + var hcheck = !($.browser.msie || $.browser.opera); + + $textarea.css("padding-top", 0).css("padding-bottom", 0).css("resize", "none"); + textarea.style.overflow = 'hidden'; + function cleanup_form() { $textarea.val(''); + $textarea.css('height', 80); $chars_counter.html(max_length); $chars_left_message.removeClass('warn'); comment_in_form = false; + current_length = 0; + + $chars_left_message.hide(); + $chars_togo_message.show(); + + $chars_counter.removeClass('warn'); + $chars_counter.html(min_length); + $button.attr("disabled","disabled"); + + interval = null; } cleanup_form(); - function calculate_chars_left() { + function process_form_changes() { var length = $textarea.val().length; - var allow = true; - if (length < max_length) { - if (length < max_length * 0.75) { - $chars_left_message.removeClass('warn'); - } else { - $chars_left_message.addClass('warn'); - } + if (current_length == length) + return; + + if (length < warn_length && current_length >= warn_length) { + $chars_counter.removeClass('warn'); + } else if (current_length < warn_length && length >= warn_length){ + $chars_counter.addClass('warn'); + } + + if (length < min_length) { + $chars_left_message.hide(); + $chars_togo_message.show(); + $chars_counter.html(min_length - length); + } else { + $chars_togo_message.hide(); + $chars_left_message.show(); + $chars_counter.html(max_length - length); + } + + if (length > max_length || length < min_length) { + $button.attr("disabled","disabled"); } else { - allow = false; + $button.removeAttr("disabled"); } - $chars_counter.html(max_length - length); - return allow; + var current_height = textarea.style.height; + if (hcheck) + textarea.style.height = "0px"; + + var h = Math.max(80, textarea.scrollHeight); + textarea.style.height = current_height; + $textarea.animate({height: h + 'px'}, 50); + + current_length = length; } function show_comment_form() { $container.slideDown('slow'); $add_comment_link.fadeOut('slow'); + window.setInterval(function() { + process_form_changes(); + }, 200); } function hide_comment_form() { + if (interval != null) { + window.clearInterval(interval); + interval = null; + } $container.slideUp('slow'); $add_comment_link.fadeIn('slow'); } @@ -213,37 +372,48 @@ $(function() { $('#' + $comments_container.attr('id') + ' .comment-edit').live('click', function() { var $link = $(this); var comment_id = /comment-(\d+)-edit/.exec($link.attr('id'))[1]; - var $comment = $link.parents('.comment'); - var comment_text = $comment.find('.comment-text').text().trim(); + var $comment = $('#comment-' + comment_id); comment_in_form = comment_id; - $textarea.val(comment_text); - calculate_chars_left(); + + $.get($link.attr('href'), function(data) { + $textarea.val(data); + }); + $comment.slideUp('slow'); show_comment_form(); return false; }); - $textarea.keyup(calculate_chars_left); - $button.click(function() { - if ($textarea.val().length > max_length) { - show_message($button, "Your comment exceeds the max number of characters allowed."); - } else { - var post_data = { - comment: $textarea.val() - } + if (running) return false; - if (comment_in_form) { - post_data['id'] = comment_in_form; - } + var post_data = { + comment: $textarea.val() + } - $.post($form.attr('action'), post_data, function(data) { - process_ajax_response(data, $button); - cleanup_form(); - }, "json") + if (comment_in_form) { + post_data['id'] = comment_in_form; } + start_command(); + $.post($form.attr('action'), post_data, function(data) { + process_ajax_response(data, $button, function(error) { + if (!error) { + cleanup_form(); + hide_comment_form(); + } + }); + + }, "json"); + + return false; + }); + + $cancel.click(function() { + if (comment_in_form) { + $comment = $('#comment-' + comment_in_form).slideDown('slow'); + } hide_comment_form(); return false; }); diff --git a/forum/skins/default/media/style/admin.css b/forum/skins/default/media/style/admin.css index 673e9b4..4fcfad5 100644 --- a/forum/skins/default/media/style/admin.css +++ b/forum/skins/default/media/style/admin.css @@ -2,7 +2,7 @@ border-spacing: 10px; } -#admin_form input[type="text"], #admin_form input[type="submit"], #admin_form textarea { +#admin_form input[type="text"], #admin_form input[type="submit"], #admin_form textarea, .string_list_widget_button { line-height: 22px; font-size: 140%; font-family: sans-serif; @@ -10,7 +10,7 @@ color: black; } -#admin_form input[type="text"], #admin_form input[type="submit"] { +#admin_form input[type="text"], #admin_form input[type="submit"], .string_list_widget_button { height: 28px; } @@ -30,4 +30,19 @@ #admin_page_description { color: gray; padding-bottom: 20px; +} + +.string_list_widget input[type=text] { + width: 520px; +} + +.string_list_widget_button { + width: 28px; + font-size: 20px; + font-weight: bold; +} + +.string_list_widget_button.add { + position: relative; + left: 554px; } \ No newline at end of file diff --git a/forum/skins/default/media/style/auth.css b/forum/skins/default/media/style/auth.css index 3370275..0734ce0 100644 --- a/forum/skins/default/media/style/auth.css +++ b/forum/skins/default/media/style/auth.css @@ -3,24 +3,42 @@ padding: 0px; width:600px; margin:0px 0px 5px 0px; + clear:both; } .provider_logo { - display: inline-block; - padding: 4px; + display: block; border: 1px solid #DDD; text-align: center; - vertical-align: middle; } .provider_logo.big { - height: 40px; - width: 90px; + display: block; + border:1px solid #DDDDDD; + float:left; + height:60px; + margin:3px; + width:110px; +} + +.provider_logo.big .inner { + display:block; + margin: 0px auto; + margin-top: 18px; } .provider_logo.small { - height: 32px; - width: 32px; + border:1px solid #DDDDDD; + float:left; + height:30px; + margin:3px; + width:30px; +} + +.provider_logo.small .inner { + display:block; + margin: 0px auto; + margin-top: 6px; } .provider_logo.selected { @@ -31,18 +49,36 @@ display: none; } +.signin_form { + clear:both; +} + +.signin_form fieldset { + padding: 10px; +} + .signin_form input[type="text"], .signin_form input[type="password"], .signin_form input[type="submit"] { height: 28px; line-height: 22px; font-size: 140%; border: 1px solid #999; + padding-left:5px; + margin-right:5px; +} + +.signin_form input[type="text"], .signin_form input[type="password"] { + padding-top:4px; /* balance of alignment between firefox/safari and IE */ } .signin_form .icon_input { padding-left: 20px; } +.signin_form #openid_identifier { + padding-left: 18px; +} + .or_label { margin-top: 20px; margin-bottom: 10px; -} \ No newline at end of file +} diff --git a/forum/skins/default/media/style/style.css b/forum/skins/default/media/style/style.css index dee175b..9932037 100644 --- a/forum/skins/default/media/style/style.css +++ b/forum/skins/default/media/style/style.css @@ -663,8 +663,6 @@ ul.errorlist li { margin-top: 5px; } -div.comments-container { padding: 0; } - .answer { border-bottom: 1px solid #CCCCCE; padding-top: 10px; @@ -677,13 +675,13 @@ div.comments-container { padding: 0; } min-height: 80px; } +.answered-by-owner { background: none repeat scroll 0 0 #E9E9FF; } + .accepted-answer { background-color: #EBFFE6; border-bottom-color: #9BD59B; } -.accepted-answer .comments-container { background-color: #CCFFBF; } - .answered { background: none repeat scroll 0 0 #E5EBF8; color: #314362; @@ -699,9 +697,6 @@ div.comments-container { padding: 0; } color: #6B2B28; } -.answered-by-owner { background: none repeat scroll 0 0 #E9E9FF; } -.answered-by-owner .comments-container { background-color: #E6ECFF; } - .tagsList { list-style-type: none; margin: 0; @@ -1111,7 +1106,6 @@ ul.form-horizontal-rows li input { } .post-controls { - float: left; font-size: 11px; line-height: 12px; margin-bottom: 5px; @@ -1120,11 +1114,6 @@ ul.form-horizontal-rows li input { #question-controls .tags { margin: 0 0 3px; } -.post-update-info-container { - float: right; - min-width: 190px; -} - .post-update-info { display: inline-block; float: right; @@ -1145,21 +1134,6 @@ ul.form-horizontal-rows li input { width: 32px; } -.comments-container { clear: both; } - -.admin { - background-color: #FFF380; - border: 1px solid darkred; - padding: 0 5px; -} - -.admin p { margin-bottom: 3px; } - -.admin #action_status { - font-weight: bold; - text-align: center; -} - #tagSelector { padding-bottom: 2px; } #hideIgnoredTagsControl { margin: 5px 0 0; } #hideIgnoredTagsCb { margin: 0 2px 0 1px; } @@ -1192,10 +1166,10 @@ a.post-vote.down.on,a.post-vote.down:hover { background: url("../images/vote-arr a.accept-answer { background: url("../images/vote-accepted.png") no-repeat scroll center center transparent; } a.accept-answer.on,a.accept-answer:hover { background: url("../images/vote-accepted-on.png") no-repeat scroll center center transparent; } -.post-score { +.post-score, .comments-char-left-count { color: #777777; font-family: Arial; - font-size: 140%; + font-size: 165%; font-weight: bold; padding: 0 0 3px; } @@ -1211,10 +1185,15 @@ a.accept-answer.on,a.accept-answer:hover { background: url("../images/vote-accep padding: 0; } +.comments-container { clear: both; } +.comments-container { padding: 0; } +.answered-by-owner .comments-container { background-color: #E6ECFF; } +.accepted-answer .comments-container { background-color: #CCFFBF; } + .comment { border-top: 1px dotted #CCCCCE; margin: 0; - width: 100%; + position: relative; } .comment.not_top_scorer { display: none; } @@ -1226,27 +1205,39 @@ a.accept-answer.on,a.accept-answer:hover { background: url("../images/vote-accep font-weight: bold; padding-top: 3px; vertical-align: top; + float: left; width: 22px; + height: 100%; + text-align: center; } .comment-text { color: #444444; - font-size: 11px; + font-size: 12px; margin: 0 0 0 22px; padding: 0; } +.comment-text p { + font-size: 12px; +} + .comment-info { font-size: 11px; - margin: 0; - text-align: right; + margin: 0 0 4px 0; + text-align: right; + height: 18px; + vertical-align: middle; } -a.comment-like,a.comment-delete,a.comment-edit { - float: right; +.comment-info * { + float: right; height: 18px; + margin-left: 4px; +} + +a.comment-like,a.comment-delete,a.comment-edit { margin-left: 2px; - position: relative; width: 18px; } @@ -1265,8 +1256,9 @@ a.comment-edit:hover { background: url("../images/comment-edit-hover.png") no-re .comment-form-widgets-container input { vertical-align: top; } .comment-form-widgets-container textarea { - height: 6em; + height: 80px; width: 80%; + float: left; } span.comment-chars-left { @@ -1312,3 +1304,69 @@ div.comment-tools a:hover { } .action-link-separator { color: #CCCCCC; } + +.deleted {background-color: #F4E7E7;} + +#command-loader { + position: fixed; + bottom: 0px; + left: 0px; + width: 24px; + height: 24px; + background: url('/m/default/media/images/indicator.gif') +} + +#command-loader.success { + background: url('/m/default/media/images/vote-accepted-on.png') +} + +.user-prompt { + width: 300px; +} + +.user-prompt select, .user-prompt textarea { + width: 100%; + padding: 0; + border: 0; +} + +.user-prompt .prompt-buttons { + text-align: right; +} + +.comment-form-buttons { + width: 18%; + height: 100%; + float: right; +} + +.comment-form-buttons input, .user-prompt .prompt-buttons button { + height: 16px; + line-height: 12px; + font-size: 110%; + border: 1px solid #999; +} + +.comment-form-buttons input { + width: 100%; + height: 22px; + vertical-align: center; + margin-top: 6px; +} + +.comments-char-left-count.warn { + color: orange; +} + +.moderation { + background-color: #FFF380; + border: 1px solid darkred; + padding: 0 5px; +} + +.moderation p { margin-bottom: 3px; } + +.moderation #action_status { + font-weight: bold; + text-align: center; +} \ No newline at end of file diff --git a/forum/skins/default/templates/ask.html b/forum/skins/default/templates/ask.html index a925e9d..35a6c2c 100644 --- a/forum/skins/default/templates/ask.html +++ b/forum/skins/default/templates/ask.html @@ -25,7 +25,7 @@ $('#pre-collapse').text(txt); }); - // Tags autocomplete action + //Tags autocomplete action $("#id_tags").autocomplete("/matching_tags", { minChars: 1, matchContains: true, diff --git a/forum/skins/default/templates/auth/signin.html b/forum/skins/default/templates/auth/signin.html index 798faeb..6f653f8 100644 --- a/forum/skins/default/templates/auth/signin.html +++ b/forum/skins/default/templates/auth/signin.html @@ -36,7 +36,10 @@

{% trans 'Or...' %}

{% endif %}
- {% trans "Click to sign in through any of these services." %} + {% blocktrans %} + External login services use OpenID technology, where your password always stays confidential between + you and your login provider and you don't have to remember another one. + {% endblocktrans %}
{% if request.user.is_anonymous %}
@@ -47,34 +50,38 @@
{% for provider in bigicon_providers %} {% endfor %}
{% for provider in smallicon_providers %} {% endfor %}
@@ -90,9 +97,11 @@ {% endfor %}

{% trans 'Or...' %}

-
- {% trans 'Click' %} here {% trans "if you're having troubles signing in." %} -
+
diff --git a/forum/skins/default/templates/node/post_controls.html b/forum/skins/default/templates/node/post_controls.html index 5b5fc86..c24660b 100644 --- a/forum/skins/default/templates/node/post_controls.html +++ b/forum/skins/default/templates/node/post_controls.html @@ -1,7 +1,7 @@ {% spaceless %} {% for control in controls %} - {{ control.text }} {% ifnotequal controls|last control %} diff --git a/forum/skins/default/templates/node/report.html b/forum/skins/default/templates/node/report.html new file mode 100644 index 0000000..dbc8630 --- /dev/null +++ b/forum/skins/default/templates/node/report.html @@ -0,0 +1,19 @@ +{% load i18n %} + +
+ {% trans "Please select a reason bellow or use the text box to input your own reason." %} + + +
+ +
+
+ \ No newline at end of file diff --git a/forum/skins/default/templates/osqaadmin/base.html b/forum/skins/default/templates/osqaadmin/base.html index e35a705..2acdc15 100644 --- a/forum/skins/default/templates/osqaadmin/base.html +++ b/forum/skins/default/templates/osqaadmin/base.html @@ -5,6 +5,7 @@ {% block forejs %} + {% block adminjs %}{% endblock %} {% endblock %} @@ -23,12 +24,12 @@ {% block sidebar %}
-

{% trans "Administration menu" %}

- +

{% trans "Administration menu" %}

+
{% if markdown %} @@ -65,5 +66,4 @@ {% endif %} {% endblock %} - - + diff --git a/forum/skins/default/templates/osqaadmin/index.html b/forum/skins/default/templates/osqaadmin/index.html index 9e35a35..64670f5 100644 --- a/forum/skins/default/templates/osqaadmin/index.html +++ b/forum/skins/default/templates/osqaadmin/index.html @@ -65,7 +65,7 @@

{% trans "Recent activity" %}

{% for activity in recent_activity %} - {% activity_item activity %} + {% activity_item activity request.user %} {% endfor %}
diff --git a/forum/skins/default/templates/post_contributor_info.html b/forum/skins/default/templates/post_contributor_info.html index 9997be5..2770644 100644 --- a/forum/skins/default/templates/post_contributor_info.html +++ b/forum/skins/default/templates/post_contributor_info.html @@ -35,20 +35,20 @@ {% get_score_badge post.author %}

{% endif %} {% else %} - {% if post.last_edited_at %} + {% if post.last_edited %}

{% ifequal post_type 'question' %} {% else %} {% endifequal %} - {% trans "updated" %} {% diff_date post.last_edited_at %} + {% trans "updated" %} {% diff_date post.last_edited.at %}

- {% if post.author != post.last_edited_by or wiki %} - {% gravatar post.last_edited_by 32 %} -

{{post.last_edited_by.get_profile_link}}
- {% get_score_badge post.last_edited_by %}

+ {% if post.author != post.last_edited.by or wiki %} + {% gravatar post.last_edited.by 32 %} +

{{post.last_edited.by.get_profile_link}}
+ {% get_score_badge post.last_edited.by %}

{% endif %} {% endif %} {% endifequal %} diff --git a/forum/skins/default/templates/question.html b/forum/skins/default/templates/question.html index 7a265c6..b6300d5 100644 --- a/forum/skins/default/templates/question.html +++ b/forum/skins/default/templates/question.html @@ -7,7 +7,7 @@ {% load humanize %} {% load i18n %} {% load cache %} -{% block title %}{% spaceless %}{{ question.get_question_title }}{% endspaceless %}{% endblock %} +{% block title %}{% spaceless %}{{ question.headline }}{% endspaceless %}{% endblock %} {% block forejs %} @@ -19,8 +19,6 @@ {% endif %} + + + + +