From 104cf2a32ab4e4d2af218a8f3a5116cb33b47d99 Mon Sep 17 00:00:00 2001 From: James Turk Date: Wed, 19 Aug 2009 12:18:57 -0400 Subject: [PATCH] attempt to merge brainstorm with what was anthill.ideas --- brainstorm/feeds.py | 14 ++++--- brainstorm/models.py | 27 ++++++++++++- brainstorm/urls.py | 33 +++++++++------- brainstorm/views.py | 94 ++++++++++++++++++-------------------------- setup.py | 2 +- 5 files changed, 92 insertions(+), 78 deletions(-) diff --git a/brainstorm/feeds.py b/brainstorm/feeds.py index 2f0000a..5296188 100644 --- a/brainstorm/feeds.py +++ b/brainstorm/feeds.py @@ -3,25 +3,29 @@ from brainstorm.models import Subsite class SubsiteFeed(Feed): - description_template = 'feedback/idea_rss_description.html' + title_template = 'brainstorm/feed_title.html' + description_template = 'brainstorm/feed_description.html' def get_object(self, bits): return Subsite.objects.get(slug__exact=bits[0]) def title(self, obj): - return '%s' % obj.name + return 'Latest ideas submitted for %s' % obj.name + + def description(self, obj): + return 'Latest ideas submitted for %s' % obj.name def link(self, obj): if not obj: raise FeedDoesNotExist return obj.get_absolute_url() - def description(self, obj): - return 'Latest ideas submitted for %s' % obj.name - def items(self, obj): return obj.ideas.order_by('-submit_date')[:30] + def item_link(self, item): + return item.get_absolute_url() + def item_author_name(self, item): return item.user diff --git a/brainstorm/models.py b/brainstorm/models.py index 1804ca0..008a9ba 100644 --- a/brainstorm/models.py +++ b/brainstorm/models.py @@ -3,7 +3,6 @@ from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.contrib.contenttypes import generic from django.contrib.comments.models import Comment -import secretballot ALLOW_ALL, REQUIRE_LOGIN, DISALLOW_ALL = range(3) SUBSITE_POST_STATUS = ( @@ -36,10 +35,16 @@ class Subsite(models.Model): elif self.post_status == REQUIRE_LOGIN: return not user.is_anonymous() +class IdeaManager(models.Manager): + + def with_user_vote(self, user): + return self.extra(select={'user_vote':'SELECT value FROM brainstorm_vote WHERE idea_id=ideas_idea.id AND user_id=%s'}, select_params=[user.id]) + class Idea(models.Model): title = models.CharField(max_length=100) description = models.TextField() + score = models.IntegerField(default=0) submit_date = models.DateTimeField(auto_now_add=True) @@ -48,10 +53,28 @@ class Idea(models.Model): comments = generic.GenericRelation(Comment, object_id_field='object_pk') + objects = IdeaManager() + def __unicode__(self): return self.title def get_absolute_url(self): return reverse('idea', args=[self.subsite_id, self.id]) -secretballot.enable_voting_on(Idea) +class Vote(models.Model): + user = models.ForeignKey(User, related_name='idea_votes') + idea = models.ForeignKey(Idea, related_name='votes') + value = models.IntegerField() + timestamp = models.DateTimeField(auto_now_add=True) + + def __unicode__(self): + return '%s %s on %s' % (self.user, self.value, self.idea) + + class Meta: + unique_together = (('user', 'idea'),) + +def update_idea_votes(sender, instance, created, **kwargs): + score = instance.idea.votes.aggregate(score=models.Sum('value'))['score'] + instance.idea.score = score + instance.idea.save() +post_save.connect(update_idea_votes, sender=Vote) diff --git a/brainstorm/urls.py b/brainstorm/urls.py index c69a11a..b62dada 100644 --- a/brainstorm/urls.py +++ b/brainstorm/urls.py @@ -3,6 +3,8 @@ from django.contrib.contenttypes.models import ContentType from brainstorm.models import Idea from brainstorm.feeds import SubsiteFeed +BRAINSTORM_USE_SECRETBALLOT = False + feeds = { 'latest': SubsiteFeed, } @@ -14,22 +16,23 @@ urlpatterns = patterns('', ) urlpatterns += patterns('brainstorm.views', - url(r'^submit_comment/$', 'submit_comment', name='submit_idea_comment'), - url(r'^(?P[\w-]+)/$', 'idea_list', {'ordering': 'most_popular'}, name='subsite'), - url(r'^(?P[\w-]+)/latest/$', 'idea_list', {'ordering': 'latest'}, name='subsite_latest'), - url(r'^(?P[\w-]+)/(?P\d+)/$', 'idea_detail', name='idea'), + url(r'^(?P[\w-]+)/$', 'idea_list', {'ordering': 'most_popular'}, name='ideas_popular'), + url(r'^(?P[\w-]+)/latest/$', 'idea_list', {'ordering': 'latest'}, name='ideas_latest'), + url(r'^(?P[\w-]+)/(?P\d+)/$', 'idea_detail', name='idea_detail'), url(r'^(?P[\w-]+)/new_idea/$', 'new_idea', name='new_idea'), + url(r'^vote/$', 'vote', name='idea_vote'), ) -urlpatterns = patterns('secretballot.views', - url(r'^vote_up/(?P\d+)/$', 'vote', - {'content_type': ContentType.objects.get_for_model(Idea), 'vote': 1}, - name='vote_up'), - url(r'^vote_down/(?P\d+)/$', 'vote', - {'content_type': ContentType.objects.get_for_model(Idea), 'vote': -1}, - name='vote_down'), - url(r'^unvote/(?P\d+)/$', 'vote', - {'content_type': ContentType.objects.get_for_model(Idea), 'vote': 0}, - name='unvote'), -) + urlpatterns +if BRAINSTORM_USE_SECRETBALLOT: + urlpatterns = patterns('secretballot.views', + url(r'^vote_up/(?P\d+)/$', 'vote', + {'content_type': ContentType.objects.get_for_model(Idea), 'vote': 1}, + name='vote_up'), + url(r'^vote_down/(?P\d+)/$', 'vote', + {'content_type': ContentType.objects.get_for_model(Idea), 'vote': -1}, + name='vote_down'), + url(r'^unvote/(?P\d+)/$', 'vote', + {'content_type': ContentType.objects.get_for_model(Idea), 'vote': 0}, + name='unvote'), + ) + urlpatterns diff --git a/brainstorm/views.py b/brainstorm/views.py index 8682afa..074e0db 100644 --- a/brainstorm/views.py +++ b/brainstorm/views.py @@ -1,45 +1,28 @@ import datetime from django.template import RequestContext -from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.urlresolvers import reverse -from django.shortcuts import get_object_or_404, render_to_response -from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render_to_response, redirect +from django.http import HttpResponse from django.contrib.comments.models import Comment from django.contrib.contenttypes.models import ContentType +from django.views.generic import list_detail from django.views.decorators.http import require_POST -from brainstorm.models import Subsite, Idea +from django.contrib.auth.decorators import login_required +from django.conf import settings +from anthill.ideas.models import Subsite, Idea, Vote def idea_list(request, slug, ordering='-total_upvotes'): - subsite = get_object_or_404(Subsite, pk=slug) - ordering_db = {'most_popular': '-total_upvotes', + ordering_db = {'most_popular': '-score', 'latest': '-submit_date'}[ordering] - paginator = Paginator(Idea.objects.from_request(request).filter(subsite=subsite).order_by(ordering_db), - subsite.ideas_per_page) - - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - try: - ideas = paginator.page(page) - except (EmptyPage, InvalidPage): - ideas = paginator.page(paginator.num_pages) - - return render_to_response('brainstorm/index.html', - {'subsite':subsite, 'ideas': ideas, - 'ordering': ordering, - 'user_can_post': subsite.user_can_post(request.user)}, - context_instance=RequestContext(request)) + return list_detail.object_list(request, + queryset=Idea.objects.filter(subsite__slug=slug).with_user_vote(request.user).select_related().order_by(ordering_db), + extra_context={'ordering': ordering, 'subsite':slug}, paginate_by=10, + template_object_name='idea') def idea_detail(request, slug, id): - subsite = get_object_or_404(Subsite, pk=slug) - idea = get_object_or_404(Idea.objects.from_request(request), - subsite=slug, pk=id) - - return render_to_response('brainstorm/idea.html', - {'subsite':subsite, 'idea': idea, - 'user_can_post': subsite.user_can_post(request.user)}, + idea = get_object_or_404(Idea.objects.with_user_vote(request.user), pk=id, subsite__slug=slug) + return render_to_response('ideas/idea_detail.html', + {'idea': idea}, context_instance=RequestContext(request)) @require_POST @@ -49,29 +32,30 @@ def new_idea(request, slug): return HttpResponseRedirect(subsite.get_absolute_url()) title = request.POST['title'] description = request.POST['description'] - if request.user.is_anonymous(): - user = None - else: - user = request.user - idea = Idea.objects.create(title=title, description=description, - user=user, subsite=subsite) - return HttpResponseRedirect(idea.get_absolute_url()) + user = request.user + idea = Idea.objects.create(title=title, description=description, user=user, + subsite=subsite) + return redirect(idea) @require_POST -def submit_comment(request): - from django.conf import settings - content_type = ContentType.objects.get_for_model(Idea).id - site = settings.SITE_ID - object_pk = request.POST['idea_id'] - name = request.POST.get('name', 'anonymous') - email = request.POST.get('email', '') - url = request.POST.get('url', '') - comment = request.POST['comment'] - date = datetime.datetime.now() - ip = request.META['REMOTE_ADDR'] - c = Comment.objects.create(user_name=name, user_email=email, user_url=url, - comment=comment, submit_date=date, ip_address=ip, - site_id=site, content_type_id=content_type, object_pk=object_pk) - idea = Idea.objects.get(pk=object_pk) - linkback = '%s#c%s' % (idea.get_absolute_url(), c.id) - return HttpResponseRedirect(linkback) +@login_required +def vote(request): + idea_id = int(request.POST.get('idea')) + score = int(request.POST.get('score')) + if score not in (0,1): + score = 0 + idea = get_object_or_404(Idea, pk=idea_id) + score_diff = score + vote, created = Vote.objects.get_or_create(user=request.user, idea=idea, + defaults={'value':score}) + if not created: + new_score = idea.score + (score-vote.value) + vote.value = score + vote.save() + else: + new_score = idea.score + + if request.is_ajax(): + return HttpResponse("{'score':%d}" % new_score) + + return redirect(idea) diff --git a/setup.py b/setup.py index 32da86b..22ef670 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = open('README.rst').read() setup( name='django-brainstorm', - version="0.1", + version="0.2.0", package_dir={'brainstorm': 'brainstorm'}, packages=['brainstorm'], package_data={'brainstorm': ['templates/brainstorm/*.html']},