1. John Costa
  2. django-feature-request

Commits

John Costa  committed 0368e23

repackage

  • Participants
  • Parent commits 072e60b
  • Branches default

Comments (0)

Files changed (52)

File __init__.py

View file
  • Ignore whitespace
+VERSION = (0, 1, None)

File admin.py

View file
  • Ignore whitespace
+from django.contrib import admin
+from feature_request.models import FeatureRequest
+
+#===============================================================================
+class FeatureAdmin(admin.ModelAdmin):
+    
+    list_display = ('request_title', 'request', 'status', 'is_complete')
+
+#===============================================================================
+admin.site.register(FeatureRequest, FeatureAdmin)

File choices.py

View file
  • Ignore whitespace
+from feature_request.constants import EDITING, SUBMITTED, REVIEWING, APPROVED, DENIED, CONTENT, DUPLICATE
+
+STATUS_CHOICES =(
+    (EDITING, EDITING),
+    (SUBMITTED, SUBMITTED),
+    (REVIEWING, REVIEWING),
+    (APPROVED, APPROVED),
+    (DENIED, DENIED)
+)
+
+
+DECLINE_CHOICES = (
+   (CONTENT, CONTENT),
+   (DUPLICATE, DUPLICATE),
+)

File constants.py

View file
  • Ignore whitespace
+EDITING     = 'EDITING'
+SUBMITTED   = 'SUBMITTED'
+REVIEWING   = 'REVIEWING'
+APPROVED    = 'APPROVED'
+DENIED      = 'DENIED'
+CONTENT     = 'CONTENT'
+DUPLICATE   = 'DUPLICATE'

File feature_request/__init__.py

  • Ignore whitespace
-VERSION = (0, 1, None)

File feature_request/admin.py

  • Ignore whitespace
-from django.contrib import admin
-from feature_request.models import FeatureRequest
-
-#===============================================================================
-class FeatureAdmin(admin.ModelAdmin):
-    
-    list_display = ('request_title', 'request', 'status', 'is_complete')
-
-#===============================================================================
-admin.site.register(FeatureRequest, FeatureAdmin)

File feature_request/choices.py

  • Ignore whitespace
-from feature_request.constants import EDITING, SUBMITTED, REVIEWING, APPROVED, DENIED, CONTENT, DUPLICATE
-
-STATUS_CHOICES =(
-    (EDITING, EDITING),
-    (SUBMITTED, SUBMITTED),
-    (REVIEWING, REVIEWING),
-    (APPROVED, APPROVED),
-    (DENIED, DENIED)
-)
-
-
-DECLINE_CHOICES = (
-   (CONTENT, CONTENT),
-   (DUPLICATE, DUPLICATE),
-)

File feature_request/constants.py

  • Ignore whitespace
-EDITING     = 'EDITING'
-SUBMITTED   = 'SUBMITTED'
-REVIEWING   = 'REVIEWING'
-APPROVED    = 'APPROVED'
-DENIED      = 'DENIED'
-CONTENT     = 'CONTENT'
-DUPLICATE   = 'DUPLICATE'

File feature_request/forms.py

  • Ignore whitespace
-from django import forms
-
-from feature_request.models import FeatureRequest
-from django.contrib import messages
-
-class FeatureRequestForm(forms.ModelForm):
-
-    class Meta:
-        model = FeatureRequest
-        exclude = ('member','create_date','last_update',
-                   'is_complete', 'complete_date', 'complete_comments',
-                   'status', 'decline_type', 'decline_comments',
-                    'active')
-        
-    def save(self, request, member, submit=False, fr_id=None):
-        feature_request=super(FeatureRequestForm, self).save(commit=False)
-        if fr_id:
-            feature_request.id=fr_id
-        feature_request.member = member
-        feature_request.save()
-        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been saved.' % feature_request.request_title)
-        return feature_request

File feature_request/models.py

  • Ignore whitespace
-from django.db import models
-from django.contrib.auth.models import User
-
-from feature_request.choices import STATUS_CHOICES, DECLINE_CHOICES
-from feature_request.constants import SUBMITTED, EDITING, REVIEWING, APPROVED, DENIED
-from django.contrib import messages
-
-#===============================================================================
-class FeatureRequestManager(models.Manager):
-
-    #---------------------------------------------------------------------------
-    def get_my_completed_features(self, user):
-        return self.get_my_features(user).filter(is_complete=True)
-
-    #---------------------------------------------------------------------------
-    def get_my_submitted_features(self, user):
-        return self.get_my_features(user).filter(status__in=[SUBMITTED,REVIEWING,APPROVED,DENIED], is_complete=False)
-
-    #---------------------------------------------------------------------------
-    def get_my_unsubmitted_features(self, user):
-        return self.get_my_features(user).filter(status=EDITING, is_complete=False)
-
-    #---------------------------------------------------------------------------
-    def get_my_features(self, user):
-        return self.filter(active=True, member=user).order_by("is_complete")
-
-    #---------------------------------------------------------------------------
-    def get_features(self):
-        return self.filter(active=True).order_by("is_complete")
-
-    #---------------------------------------------------------------------------
-    def get_users_feature_request(self, feature_id, user, value=None):
-
-        try:
-            value=FeatureRequest.objects.get(id=feature_id, member=user, active=True)
-        except:
-            pass
-
-        return value
-
-    #---------------------------------------------------------------------------
-    def delete_request(self, request, feature_request):
-
-        if not feature_request:
-            log.error("Empty feature request passed to delete_request!")
-            return
-
-        feature_request.active=False
-        feature_request.save()
-        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been removed.' % feature_request.request_title)
-
-    #---------------------------------------------------------------------------
-    def submit_request(self, request, feature_request):
-
-        if not feature_request:
-            log.error("Empty feature request passed to submit_request!")
-            return
-
-        feature_request.status=SUBMITTED
-        feature_request.save()
-        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been submitted.' % feature_request.request_title)
-
-#===============================================================================
-class FeatureRequest(models.Model):
-    
-    member = models.ForeignKey(User)
-    create_date = models.DateTimeField(auto_now_add=True)
-    last_update = models.DateTimeField(auto_now=True)
-    request_title = models.CharField(max_length=50, blank=False)
-    request = models.TextField(max_length=5000,blank=True)
-
-    active = models.BooleanField(default=True, db_index=True)
-
-    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=EDITING)
-    decline_type = models.CharField(max_length=10, choices=DECLINE_CHOICES, blank=True, null=True)
-    decline_comments = models.TextField(max_length=100,blank=True, null=True)
-
-    is_complete = models.BooleanField(default=False)
-    complete_date = models.DateField(blank=True, null=True)
-    complete_comments = models.TextField(max_length=100,blank=True, null=True)
-
-    objects = FeatureRequestManager()
-
-    # --------------------------------------------------------------------------
-    def __unicode__(self):
-        return u'%s' % self.id
-
-    #---------------------------------------------------------------------------
-    @property
-    def is_editable(self, value=False):
-        if self.status == EDITING:
-            value=True
-        print "Status -->%s<--" % self.status
-        return value
-    
-    #---------------------------------------------------------------------------
-    @property
-    def score(self):
-        from voting.models import Vote
-        return Vote.objects.get_score(self).get('score', 0)

File feature_request/templates/feature_request/add.html

  • Ignore whitespace
-{% extends "base.html" %}
-
-{% block body %}
-
-<h1>Request a Feature</h1>
-<form method="post" action=".">
-<table>
-    {{form}}
-<tr><td colspan='2'><input type="submit" value="Save" /></td></tr>
-</table>
-</form>
-
-{% endblock body %}

File feature_request/templates/feature_request/delete.html

  • Ignore whitespace
-{% extends "base.html" %}
-
-{% block body %}
-
-<h1>Are you sure you want to remove your feature request?</h1>
-
-<form method="post" action=".">
-{% csrf_token %}
-<table>
-    {{form}}
-<tr><td colspan='2'><input type="submit" value="Delete" /></td></tr>
-</table>
-</form>
-
-{% endblock body %}

File feature_request/templates/feature_request/edit.html

  • Ignore whitespace
-{% extends "base.html" %}
-
-{% block body %}
-
-<h1>Edit a Feature</h1>
-<form method="post" action=".">
-<table>
-    {{form}}
-<tr><td colspan='2'><input type="submit" value="Save" /></td></tr>
-</table>
-</form>
-
-{% endblock body %}

File feature_request/templates/feature_request/submit.html

  • Ignore whitespace
-{% extends "base.html" %}
-
-{% block body %}
-
-<h1>Are you sure you want to submit your feature request?</h1>
-
-<form method="post" action=".">
-{% csrf_token %}
-<table>
-    {{form}}
-<tr><td colspan='2'><input type="submit" value="Submit" /></td></tr>
-</table>
-</form>
-
-{% endblock body %}

File feature_request/templates/feature_request/tags/list_completed_user_requests.html

  • Ignore whitespace
-<table border='1'>
-    <caption>My Completed Requests</caption>
-    <thead>
-        <tr>
-            <th>Date Requested</th>
-            <th>Member</th>
-            <th>Requested Feature</th>
-            <th>Completed Date</th>
-            <th>Completed Comments</th>
-            <th>Score</th>
-        </tr>
-    </thead>
-    <tbody>
-    {% for feature in user_requests %}
-        <tr>
-            <td>{{feature.create_date|date:"M dS Y"}}</td>
-            <td>{{feature.member}}</td>
-            <td>{{feature.request_title|linebreaksbr}}</td>
-            <td>{{feature.complete_date|date:"M dS Y"}}</td>
-            <td>{{feature.complete_comments}}
-            </td>
-            <td>{{ feature.score }}</td>            
-        </tr>
-    {% endfor %}
-    </tbody>
-</table>

File feature_request/templates/feature_request/tags/list_requests.html

  • Ignore whitespace
-<table border='1'>
-    <caption>All Requests</caption>
-    <thead>
-        <tr>
-            <th>Date Requested</th>
-            <th>Member</th>
-            <th>Requested Feature</th>
-            <th>Status</th>
-            <th>Score</th>
-            <th>Vote</th>
-        </tr>
-    </thead>
-    <tbody>
-    {% for feature in feature_requests %}
-        <tr>
-            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
-            <td>{% if feature.is_complete %}Complete
-                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
-                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
-                {% else %}
-                    {{  feature.status }}
-                {% endif %}
-            </td>
-            <td>{{ feature.score }}</td>
-            <td>
-                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
-                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
-                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
-            </td>            
-        </tr>
-    {% endfor %}
-    </tbody>
-</table>

File feature_request/templates/feature_request/tags/list_submitted_user_requests.html

  • Ignore whitespace
-<table border='1'>
-    <caption>My Submitted Requests</caption>
-    <thead>
-        <tr>
-            <th>Date Requested</th>
-            <th>Member</th>
-            <th>Requested Feature</th>
-            <th>Status</th>
-            <th>Score</th>
-            <th>Vote</th>
-            <th>Action</th>
-        </tr>
-    </thead>
-    <tbody>
-    {% for feature in user_requests %}
-        <tr>
-            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
-            <td>{% if feature.is_complete %}Complete
-                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
-                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
-                {% else %}
-                    {{  feature.status }}
-                {% endif %}
-            </td>
-            <td>{{ feature.score }}</td>
-            <td>
-                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
-                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
-                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
-            </td>
-            <td>
-                {% if feature.is_editable %}
-                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
-                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
-                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
-                {% endif %}
-            </td>
-        </tr>
-    {% endfor %}
-    </tbody>
-</table>

File feature_request/templates/feature_request/tags/list_unsubmitted_user_requests.html

  • Ignore whitespace
-<table border='1'>
-    <caption>My Unsubmitted Requests</caption>
-    <thead>
-        <tr>
-            <th>Date Requested</th>
-            <th>Member</th>
-            <th>Requested Feature</th>
-            <th>Status</th>
-            <th>Score</th>
-            <th>Vote</th>
-            <th>Action</th>
-        </tr>
-    </thead>
-    <tbody>
-    {% for feature in user_requests %}
-        <tr>
-            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
-            <td>{% if feature.is_complete %}Complete
-                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
-                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
-                {% else %}
-                    {{  feature.status }}
-                {% endif %}
-            </td>
-            <td>{{ feature.score }}</td>
-            <td>
-                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
-                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
-                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
-            </td>
-            <td>
-                {% if feature.is_editable %}
-                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
-                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
-                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
-                {% endif %}
-            </td>
-        </tr>
-    {% endfor %}
-    </tbody>
-</table>

File feature_request/templates/feature_request/tags/list_user_requests.html

  • Ignore whitespace
-<table border='1'>
-    <caption>My Requests</caption>
-    <thead>
-        <tr>
-            <th>Date Requested</th>
-            <th>Member</th>
-            <th>Requested Feature</th>
-            <th>Status</th>
-            <th>Score</th>
-            <th>Vote</th>
-            <th>Action</th>
-        </tr>
-    </thead>
-    <tbody>
-    {% for feature in user_requests %}
-        <tr>
-            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
-            <td>{% if feature.is_complete %}Complete
-                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
-                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
-                {% else %}
-                    {{  feature.status }}
-                {% endif %}
-            </td>
-            <td>{{ feature.score }}</td>
-            <td>
-                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
-                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
-                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
-            </td>
-            <td>
-                {% if feature.is_editable %}
-                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
-                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
-                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
-                {% endif %}
-            </td>
-        </tr>
-    {% endfor %}
-    </tbody>
-</table>

File feature_request/templates/feature_request/view_all.html

  • Ignore whitespace
-{% extends "base.html" %}
-{% load feature_request_tags %}
-{% block body %}
-
-{% list_feature_requests %}
-{% list_user_requests request.user %}
-    
-{% endblock body %}

File feature_request/templatetags/__init__.py

  • Ignore whitespace
Empty file removed.

File feature_request/templatetags/feature_request_tags.py

  • Ignore whitespace
-from django.template import Library
-
-from feature_request.models import FeatureRequest
-
-register = Library()
-
-# Make this accessible to the feature request tags
-
-@register.inclusion_tag('feature_request/tags/list_requests.html')
-def list_feature_requests():
-    feature_requests = FeatureRequest.objects.get_features()      
-    return { 'feature_requests' : feature_requests, }
-
-@register.inclusion_tag('feature_request/tags/list_user_requests.html')
-def list_user_requests(user):
-    user_requests = FeatureRequest.objects.get_my_features(user)
-    return { 'user_requests' : user_requests, }
-
-@register.inclusion_tag('feature_request/tags/list_unsubmitted_user_requests.html')
-def list_unsubmitted_user_requests(user):
-    user_requests = FeatureRequest.objects.get_my_unsubmitted_features(user)
-    return { 'user_requests' : user_requests, }
-
-@register.inclusion_tag('feature_request/tags/list_submitted_user_requests.html')
-def list_submitted_user_requests(user):
-    user_requests = FeatureRequest.objects.get_my_submitted_features(user)
-    return { 'user_requests' : user_requests, }
-
-@register.inclusion_tag('feature_request/tags/list_completed_user_requests.html')
-def list_completed_user_requests(user):
-    user_requests = FeatureRequest.objects.get_my_completed_features(user)
-    return { 'user_requests' : user_requests, }

File feature_request/urls.py

  • Ignore whitespace
-from django.conf.urls.defaults import *
-
-from feature_request import views
-from models import FeatureRequest
-from voting.views import vote_on_object
-
-urlpatterns = patterns('',
-     url(r'^add/$', views.add, name="feature_request_add"),
-     url(r'^edit/(?P<feature_id>\d+)/$',views.edit, name="feature_request_edit"),
-     url(r'^delete/(?P<feature_id>\d+)/$',views.delete, name="feature_request_delete"),
-     url(r'^submit/(?P<feature_id>\d+)/$',views.submit, name="feature_request_submit"),
-     url(r'^$', views.view_all, name="feature_request_home"),
-     url(r'^FeatureRequest/(?P<object_id>\d+)/(?P<direction>up|down|clear)vote/?$',
-         vote_on_object,
-         {
-            'model': FeatureRequest,
-            'post_vote_redirect' : 'feature_request_home',
-            'allow_xmlhttprequest': False,
-         },
-         name="feature_request_vote"),
-)

File feature_request/views.py

  • Ignore whitespace
-from django.contrib.auth.decorators import login_required
-from django.http import HttpResponseRedirect, HttpResponse, Http404
-from django.core.urlresolvers import reverse
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.forms.models import model_to_dict
-
-from feature_request.forms import FeatureRequestForm
-from feature_request.models import FeatureRequest
-
-from voting.views import vote_on_object as _vote_on_object
-
-# ------------------------------------------------------------------------------
-def render_response(request, template_name, template_params={}):
-    return render_to_response(template_name,
-        context_instance=RequestContext(request, template_params))
-
-# ------------------------------------------------------------------------------
-@login_required
-def delete(request, feature_id, template_name='feature_request/delete.html'):
-
-    user = request.user
-    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
-
-    if not feature_request:
-        # If the feature request doesn't exist or the user didn't create it
-        # ignore the delete request
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    if request.method == 'POST':
-        FeatureRequest.objects.delete_request(request, feature_request)
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    return render_response(request, template_name, {'feature_request':feature_request})
-
-# ------------------------------------------------------------------------------
-@login_required
-def submit(request, feature_id, template_name='feature_request/submit.html'):
-
-    user = request.user
-    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
-
-    if not feature_request:
-        # If the feature request doesn't exist or the user didn't create it
-        # ignore the delete request
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    if request.method == 'POST':
-        FeatureRequest.objects.submit_request(request, feature_request)
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    return render_response(request, template_name, {'feature_request':feature_request})
-
-# ------------------------------------------------------------------------------
-@login_required
-def edit(request, feature_id, template_name='feature_request/edit.html'):
-
-    user = request.user
-    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
-
-    if not feature_request:
-        # If the feature request doesn't exist or the user didn't create it
-        # ignore the delete request
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    if request.method == 'POST':
-        form = FeatureRequestForm(request.POST, instance=feature_request)
-        if form.is_valid():
-            form.save(request, user)
-        return HttpResponseRedirect(reverse('feature_request_home'))
-
-    form = FeatureRequestForm(model_to_dict(feature_request))
-    return render_response(request, template_name, {'form':form})
-
-# ------------------------------------------------------------------------------
-@login_required
-def add(request, template_name='feature_request/add.html'):
-    
-    user = request.user
-        
-    if request.method == 'POST':
-        form = FeatureRequestForm(request.POST)
-        if form.is_valid():
-
-            form.save(request, user)
-            return HttpResponseRedirect(reverse('feature_request_home'))
-    else :
-        form = FeatureRequestForm()
-
-    return render_response(request, template_name, {'form':form,})
-
-# ------------------------------------------------------------------------------
-@login_required
-def view_all(request, template_name='feature_request/view_all.html'):
-    user=request.user
-    #print "***** getting feature_requests *****"
-    feature_requests = FeatureRequest.objects.get_features()
-    #print "***** getting my feature requests *****"
-    my_requests = FeatureRequest.objects.get_my_features(user)
-    #print my_requests
-    #print "***** rendering *****"
-    return render_response(
-            request,
-            template_name,
-            {
-                'feature_requests':feature_requests,
-                'my_requests':my_requests,
-            })
-
-# ------------------------------------------------------------------------------
-@login_required
-def vote_on_object(request, object_id, direction, post_vote_redirect=None):
-    return _vote_on_object(
-            request,
-            FeatureRequest,
-            direction,
-            post_vote_redirect=post_vote_redirect,
-            object_id=object_id,
-            template_name=None)

File forms.py

View file
  • Ignore whitespace
+from django import forms
+
+from feature_request.models import FeatureRequest
+from django.contrib import messages
+
+class FeatureRequestForm(forms.ModelForm):
+
+    class Meta:
+        model = FeatureRequest
+        exclude = ('member','create_date','last_update',
+                   'is_complete', 'complete_date', 'complete_comments',
+                   'status', 'decline_type', 'decline_comments',
+                    'active')
+        
+    def save(self, request, member, submit=False, fr_id=None):
+        feature_request=super(FeatureRequestForm, self).save(commit=False)
+        if fr_id:
+            feature_request.id=fr_id
+        feature_request.member = member
+        feature_request.save()
+        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been saved.' % feature_request.request_title)
+        return feature_request

File models.py

View file
  • Ignore whitespace
+from django.db import models
+from django.contrib.auth.models import User
+
+from feature_request.choices import STATUS_CHOICES, DECLINE_CHOICES
+from feature_request.constants import SUBMITTED, EDITING, REVIEWING, APPROVED, DENIED
+from django.contrib import messages
+
+#===============================================================================
+class FeatureRequestManager(models.Manager):
+
+    #---------------------------------------------------------------------------
+    def get_my_completed_features(self, user):
+        return self.get_my_features(user).filter(is_complete=True)
+
+    #---------------------------------------------------------------------------
+    def get_my_submitted_features(self, user):
+        return self.get_my_features(user).filter(status__in=[SUBMITTED,REVIEWING,APPROVED,DENIED], is_complete=False)
+
+    #---------------------------------------------------------------------------
+    def get_my_unsubmitted_features(self, user):
+        return self.get_my_features(user).filter(status=EDITING, is_complete=False)
+
+    #---------------------------------------------------------------------------
+    def get_my_features(self, user):
+        return self.filter(active=True, member=user).order_by("is_complete")
+
+    #---------------------------------------------------------------------------
+    def get_features(self):
+        return self.filter(active=True).order_by("is_complete")
+
+    #---------------------------------------------------------------------------
+    def get_users_feature_request(self, feature_id, user, value=None):
+
+        try:
+            value=FeatureRequest.objects.get(id=feature_id, member=user, active=True)
+        except:
+            pass
+
+        return value
+
+    #---------------------------------------------------------------------------
+    def delete_request(self, request, feature_request):
+
+        if not feature_request:
+            log.error("Empty feature request passed to delete_request!")
+            return
+
+        feature_request.active=False
+        feature_request.save()
+        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been removed.' % feature_request.request_title)
+
+    #---------------------------------------------------------------------------
+    def submit_request(self, request, feature_request):
+
+        if not feature_request:
+            log.error("Empty feature request passed to submit_request!")
+            return
+
+        feature_request.status=SUBMITTED
+        feature_request.save()
+        messages.add_message(request, messages.ERROR, 'Feature request "%s" has been submitted.' % feature_request.request_title)
+
+#===============================================================================
+class FeatureRequest(models.Model):
+    
+    member = models.ForeignKey(User)
+    create_date = models.DateTimeField(auto_now_add=True)
+    last_update = models.DateTimeField(auto_now=True)
+    request_title = models.CharField(max_length=50, blank=False)
+    request = models.TextField(max_length=5000,blank=True)
+
+    active = models.BooleanField(default=True, db_index=True)
+
+    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=EDITING)
+    decline_type = models.CharField(max_length=10, choices=DECLINE_CHOICES, blank=True, null=True)
+    decline_comments = models.TextField(max_length=100,blank=True, null=True)
+
+    is_complete = models.BooleanField(default=False)
+    complete_date = models.DateField(blank=True, null=True)
+    complete_comments = models.TextField(max_length=100,blank=True, null=True)
+
+    objects = FeatureRequestManager()
+
+    # --------------------------------------------------------------------------
+    def __unicode__(self):
+        return u'%s' % self.id
+
+    #---------------------------------------------------------------------------
+    @property
+    def is_editable(self, value=False):
+        if self.status == EDITING:
+            value=True
+        print "Status -->%s<--" % self.status
+        return value
+    
+    #---------------------------------------------------------------------------
+    @property
+    def score(self):
+        from voting.models import Vote
+        return Vote.objects.get_score(self).get('score', 0)

File templates/feature_request/add.html

View file
  • Ignore whitespace
+{% extends "base.html" %}
+
+{% block body %}
+
+<h1>Request a Feature</h1>
+<form method="post" action="">
+<table>
+    {{form}}
+<tr><td colspan='2'><input type="submit" value="Save" /></td></tr>
+</table>
+</form>
+
+{% endblock body %}

File templates/feature_request/delete.html

View file
  • Ignore whitespace
+{% extends "base.html" %}
+
+{% block body %}
+
+<h1>Are you sure you want to remove your feature request?</h1>
+
+<form method="post" action="">
+{% csrf_token %}
+<table>
+    {{form}}
+<tr><td colspan='2'><input type="submit" value="Delete" /></td></tr>
+</table>
+</form>
+
+{% endblock body %}

File templates/feature_request/edit.html

View file
  • Ignore whitespace
+{% extends "base.html" %}
+
+{% block body %}
+
+<h1>Edit a Feature</h1>
+<form method="post" action="">
+<table>
+    {{form}}
+<tr><td colspan='2'><input type="submit" value="Save" /></td></tr>
+</table>
+</form>
+
+{% endblock body %}

File templates/feature_request/submit.html

View file
  • Ignore whitespace
+{% extends "base.html" %}
+
+{% block body %}
+
+<h1>Are you sure you want to submit your feature request?</h1>
+
+<form method="post" action="">
+{% csrf_token %}
+<table>
+    {{form}}
+<tr><td colspan='2'><input type="submit" value="Submit" /></td></tr>
+</table>
+</form>
+
+{% endblock body %}

File templates/feature_request/tags/list_completed_user_requests.html

View file
  • Ignore whitespace
+<table border='1'>
+    <caption>My Completed Requests</caption>
+    <thead>
+        <tr>
+            <th>Date Requested</th>
+            <th>Member</th>
+            <th>Requested Feature</th>
+            <th>Completed Date</th>
+            <th>Completed Comments</th>
+            <th>Score</th>
+        </tr>
+    </thead>
+    <tbody>
+    {% for feature in user_requests %}
+        <tr>
+            <td>{{feature.create_date|date:"M dS Y"}}</td>
+            <td>{{feature.member}}</td>
+            <td>{{feature.request_title|linebreaksbr}}</td>
+            <td>{{feature.complete_date|date:"M dS Y"}}</td>
+            <td>{{feature.complete_comments}}
+            </td>
+            <td>{{ feature.score }}</td>            
+        </tr>
+    {% endfor %}
+    </tbody>
+</table>

File templates/feature_request/tags/list_requests.html

View file
  • Ignore whitespace
+<table border='1'>
+    <caption>All Requests</caption>
+    <thead>
+        <tr>
+            <th>Date Requested</th>
+            <th>Member</th>
+            <th>Requested Feature</th>
+            <th>Status</th>
+            <th>Score</th>
+            <th>Vote</th>
+        </tr>
+    </thead>
+    <tbody>
+    {% for feature in feature_requests %}
+        <tr>
+            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
+            <td>{% if feature.is_complete %}Complete
+                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
+                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
+                {% else %}
+                    {{  feature.status }}
+                {% endif %}
+            </td>
+            <td>{{ feature.score }}</td>
+            <td>
+                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
+                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
+                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
+            </td>            
+        </tr>
+    {% endfor %}
+    </tbody>
+</table>

File templates/feature_request/tags/list_submitted_user_requests.html

View file
  • Ignore whitespace
+<table border='1'>
+    <caption>My Submitted Requests</caption>
+    <thead>
+        <tr>
+            <th>Date Requested</th>
+            <th>Member</th>
+            <th>Requested Feature</th>
+            <th>Status</th>
+            <th>Score</th>
+            <th>Vote</th>
+            <th>Action</th>
+        </tr>
+    </thead>
+    <tbody>
+    {% for feature in user_requests %}
+        <tr>
+            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
+            <td>{% if feature.is_complete %}Complete
+                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
+                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
+                {% else %}
+                    {{  feature.status }}
+                {% endif %}
+            </td>
+            <td>{{ feature.score }}</td>
+            <td>
+                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
+                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
+                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
+            </td>
+            <td>
+                {% if feature.is_editable %}
+                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
+                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
+                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
+                {% endif %}
+            </td>
+        </tr>
+    {% endfor %}
+    </tbody>
+</table>

File templates/feature_request/tags/list_unsubmitted_user_requests.html

View file
  • Ignore whitespace
+<table border='1'>
+    <caption>My Unsubmitted Requests</caption>
+    <thead>
+        <tr>
+            <th>Date Requested</th>
+            <th>Member</th>
+            <th>Requested Feature</th>
+            <th>Status</th>
+            <th>Score</th>
+            <th>Vote</th>
+            <th>Action</th>
+        </tr>
+    </thead>
+    <tbody>
+    {% for feature in user_requests %}
+        <tr>
+            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
+            <td>{% if feature.is_complete %}Complete
+                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
+                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
+                {% else %}
+                    {{  feature.status }}
+                {% endif %}
+            </td>
+            <td>{{ feature.score }}</td>
+            <td>
+                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
+                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
+                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
+            </td>
+            <td>
+                {% if feature.is_editable %}
+                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
+                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
+                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
+                {% endif %}
+            </td>
+        </tr>
+    {% endfor %}
+    </tbody>
+</table>

File templates/feature_request/tags/list_user_requests.html

View file
  • Ignore whitespace
+<table border='1'>
+    <caption>My Requests</caption>
+    <thead>
+        <tr>
+            <th>Date Requested</th>
+            <th>Member</th>
+            <th>Requested Feature</th>
+            <th>Status</th>
+            <th>Score</th>
+            <th>Vote</th>
+            <th>Action</th>
+        </tr>
+    </thead>
+    <tbody>
+    {% for feature in user_requests %}
+        <tr>
+            <td>{{feature.create_date|date:"M dS Y"}}</td><td>{{feature.member}}</td><td>{{feature.request_title|linebreaksbr}}</td>
+            <td>{% if feature.is_complete %}Complete
+                    {% if feature.complete_date %}({{feature.complete_date}}){% endif %}
+                    {% if feature.complete_comments %}<br />{{feature.complete_comments|linebreaksbr}}{% endif %}
+                {% else %}
+                    {{  feature.status }}
+                {% endif %}
+            </td>
+            <td>{{ feature.score }}</td>
+            <td>
+                <form action="{% url feature_request_vote feature.id "up" %}" method="post">{% csrf_token %}<input type="submit" value="+" /></form>
+                <form action="{% url feature_request_vote feature.id "down" %}" method="post">{% csrf_token %}<input type="submit" value="-" /></form>
+                <form action="{% url feature_request_vote feature.id "clear" %}" method="post">{% csrf_token %}<input type="submit" value="clear" /></form>
+            </td>
+            <td>
+                {% if feature.is_editable %}
+                    <a href="{% url feature_request_delete feature.id %}">Delete</a>&nbsp;
+                    <a href="{% url feature_request_edit feature.id %}" >Edit</a>&nbsp;
+                    <a href="{% url feature_request_submit feature.id %}" >Submit</a>
+                {% endif %}
+            </td>
+        </tr>
+    {% endfor %}
+    </tbody>
+</table>

File templates/feature_request/view_all.html

View file
  • Ignore whitespace
+{% extends "base.html" %}
+{% load feature_request_tags %}
+{% block body %}
+
+{% list_feature_requests %}
+{% list_user_requests request.user %}
+    
+{% endblock body %}

File templatetags/__init__.py

  • Ignore whitespace
Empty file added.

File templatetags/feature_request_tags.py

View file
  • Ignore whitespace
+from django.template import Library
+
+from feature_request.models import FeatureRequest
+
+register = Library()
+
+# Make this accessible to the feature request tags
+
+@register.inclusion_tag('feature_request/tags/list_requests.html')
+def list_feature_requests():
+    feature_requests = FeatureRequest.objects.get_features()      
+    return { 'feature_requests' : feature_requests, }
+
+@register.inclusion_tag('feature_request/tags/list_user_requests.html')
+def list_user_requests(user):
+    user_requests = FeatureRequest.objects.get_my_features(user)
+    return { 'user_requests' : user_requests, }
+
+@register.inclusion_tag(
+    'feature_request/tags/list_unsubmitted_user_requests.html')
+def list_unsubmitted_user_requests(user):
+    user_requests = FeatureRequest.objects.get_my_unsubmitted_features(user)
+    return { 'user_requests' : user_requests, }
+
+@register.inclusion_tag(
+    'feature_request/tags/list_submitted_user_requests.html')
+def list_submitted_user_requests(user):
+    user_requests = FeatureRequest.objects.get_my_submitted_features(user)
+    return { 'user_requests' : user_requests, }
+
+@register.inclusion_tag(
+    'feature_request/tags/list_completed_user_requests.html')
+def list_completed_user_requests(user):
+    user_requests = FeatureRequest.objects.get_my_completed_features(user)
+    return { 'user_requests' : user_requests, }

File urls.py

View file
  • Ignore whitespace
+from django.conf.urls.defaults import *
+
+from feature_request import views
+from models import FeatureRequest
+from voting.views import vote_on_object
+
+urlpatterns = patterns('',
+     url(r'^add/$', views.add, name="feature_request_add"),
+     url(r'^edit/(?P<feature_id>\d+)/$',views.edit, name="feature_request_edit"),
+     url(r'^delete/(?P<feature_id>\d+)/$',views.delete, name="feature_request_delete"),
+     url(r'^submit/(?P<feature_id>\d+)/$',views.submit, name="feature_request_submit"),
+     url(r'^$', views.view_all, name="feature_request_home"),
+     url(r'^FeatureRequest/(?P<object_id>\d+)/(?P<direction>up|down|clear)vote/?$',
+         vote_on_object,
+         {
+            'model': FeatureRequest,
+            'post_vote_redirect' : 'feature_request_home',
+            'allow_xmlhttprequest': False,
+         },
+         name="feature_request_vote"),
+)

File views.py

View file
  • Ignore whitespace
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponseRedirect, HttpResponse, Http404
+from django.core.urlresolvers import reverse
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.forms.models import model_to_dict
+
+from feature_request.forms import FeatureRequestForm
+from feature_request.models import FeatureRequest
+
+from voting.views import vote_on_object as _vote_on_object
+
+# ------------------------------------------------------------------------------
+def render_response(request, template_name, template_params={}):
+    return render_to_response(template_name,
+        context_instance=RequestContext(request, template_params))
+
+# ------------------------------------------------------------------------------
+@login_required
+def delete(request, feature_id, template_name='feature_request/delete.html'):
+
+    user = request.user
+    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
+
+    if not feature_request:
+        # If the feature request doesn't exist or the user didn't create it
+        # ignore the delete request
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    if request.method == 'POST':
+        FeatureRequest.objects.delete_request(request, feature_request)
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    return render_response(request, template_name, {'feature_request':feature_request})
+
+# ------------------------------------------------------------------------------
+@login_required
+def submit(request, feature_id, template_name='feature_request/submit.html'):
+
+    user = request.user
+    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
+
+    if not feature_request:
+        # If the feature request doesn't exist or the user didn't create it
+        # ignore the delete request
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    if request.method == 'POST':
+        FeatureRequest.objects.submit_request(request, feature_request)
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    return render_response(request, template_name, {'feature_request':feature_request})
+
+# ------------------------------------------------------------------------------
+@login_required
+def edit(request, feature_id, template_name='feature_request/edit.html'):
+
+    user = request.user
+    feature_request=FeatureRequest.objects.get_users_feature_request(feature_id, user)
+
+    if not feature_request:
+        # If the feature request doesn't exist or the user didn't create it
+        # ignore the delete request
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    if request.method == 'POST':
+        form = FeatureRequestForm(request.POST, instance=feature_request)
+        if form.is_valid():
+            form.save(request, user)
+        return HttpResponseRedirect(reverse('feature_request_home'))
+
+    form = FeatureRequestForm(model_to_dict(feature_request))
+    return render_response(request, template_name, {'form':form})
+
+# ------------------------------------------------------------------------------
+@login_required
+def add(request, template_name='feature_request/add.html'):
+    
+    user = request.user
+        
+    if request.method == 'POST':
+        form = FeatureRequestForm(request.POST)
+        if form.is_valid():
+
+            form.save(request, user)
+            return HttpResponseRedirect(reverse('feature_request_home'))
+    else :
+        form = FeatureRequestForm()
+
+    return render_response(request, template_name, {'form':form,})
+
+# ------------------------------------------------------------------------------
+@login_required
+def view_all(request, template_name='feature_request/view_all.html'):
+    user=request.user
+    #print "***** getting feature_requests *****"
+    feature_requests = FeatureRequest.objects.get_features()
+    #print "***** getting my feature requests *****"
+    my_requests = FeatureRequest.objects.get_my_features(user)
+    #print my_requests
+    #print "***** rendering *****"
+    return render_response(
+            request,
+            template_name,
+            {
+                'feature_requests':feature_requests,
+                'my_requests':my_requests,
+            })
+
+# ------------------------------------------------------------------------------
+@login_required
+def vote_on_object(request, object_id, direction, post_vote_redirect=None):
+    return _vote_on_object(
+            request,
+            FeatureRequest,
+            direction,
+            post_vote_redirect=post_vote_redirect,
+            object_id=object_id,
+            template_name=None)

File voting/__init__.py

  • Ignore whitespace
-VERSION = (0, 1, None)

File voting/admin.py

  • Ignore whitespace
-from django.contrib import admin
-from voting.models import Vote
-
-admin.site.register(Vote)

File voting/managers.py

  • Ignore whitespace
-from django.conf import settings
-from django.db import connection, models
-
-try:
-    from django.db.models.sql.aggregates import Aggregate
-except ImportError:
-    supports_aggregates = False
-else:
-    supports_aggregates = True
-
-from django.contrib.contenttypes.models import ContentType
-
-if supports_aggregates:
-    class CoalesceWrapper(Aggregate):
-        sql_template = 'COALESCE(%(function)s(%(field)s), %(default)s)'
-    
-        def __init__(self, lookup, **extra): 
-            self.lookup = lookup
-            self.extra = extra
-    
-        def _default_alias(self):
-            return '%s__%s' % (self.lookup, self.__class__.__name__.lower())
-        default_alias = property(_default_alias)
-    
-        def add_to_query(self, query, alias, col, source, is_summary):
-            super(CoalesceWrapper, self).__init__(col, source, is_summary, **self.extra)
-            query.aggregate_select[alias] = self
-
-
-    class CoalesceSum(CoalesceWrapper):
-        sql_function = 'SUM'
-
-
-    class CoalesceCount(CoalesceWrapper):
-        sql_function = 'COUNT'
-
-
-class VoteManager(models.Manager):
-    def get_score(self, obj):
-        """
-        Get a dictionary containing the total score for ``obj`` and
-        the number of votes it's received.
-        """
-        ctype = ContentType.objects.get_for_model(obj)
-        result = self.filter(object_id=obj._get_pk_val(),
-                             content_type=ctype).extra(
-            select={
-                'score': 'COALESCE(SUM(vote), 0)',
-                'num_votes': 'COALESCE(COUNT(vote), 0)',
-        }).values_list('score', 'num_votes')[0]
-
-        return {
-            'score': int(result[0]),
-            'num_votes': int(result[1]),
-        }
-
-    def get_scores_in_bulk(self, objects):
-        """
-        Get a dictionary mapping object ids to total score and number
-        of votes for each object.
-        """
-        object_ids = [o._get_pk_val() for o in objects]
-        if not object_ids:
-            return {}
-        
-        ctype = ContentType.objects.get_for_model(objects[0])
-        
-        if supports_aggregates:
-            queryset = self.filter(
-                object_id__in = object_ids,
-                content_type = ctype,
-            ).values(
-                'object_id',
-            ).annotate(
-                score = CoalesceSum('vote', default='0'),
-                num_votes = CoalesceCount('vote', default='0'),
-            )
-        else:
-            queryset = self.filter(
-                object_id__in = object_ids,
-                content_type = ctype,
-                ).extra(
-                    select = {
-                        'score': 'COALESCE(SUM(vote), 0)',
-                        'num_votes': 'COALESCE(COUNT(vote), 0)',
-                    }
-                ).values('object_id', 'score', 'num_votes')
-            queryset.query.group_by.append('object_id')
-        
-        vote_dict = {}
-        for row in queryset:
-            vote_dict[row['object_id']] = {
-                'score': int(row['score']),
-                'num_votes': int(row['num_votes']),
-            }
-        
-        return vote_dict
-
-    def record_vote(self, obj, user, vote):
-        """
-        Record a user's vote on a given object. Only allows a given user
-        to vote once, though that vote may be changed.
-
-        A zero vote indicates that any existing vote should be removed.
-        """
-        if vote not in (+1, 0, -1):
-            raise ValueError('Invalid vote (must be +1/0/-1)')
-        ctype = ContentType.objects.get_for_model(obj)
-        try:
-            v = self.get(user=user, content_type=ctype,
-                         object_id=obj._get_pk_val())
-            if vote == 0:
-                v.delete()
-            else:
-                v.vote = vote
-                v.save()
-        except models.ObjectDoesNotExist:
-            if vote != 0:
-                self.create(user=user, content_type=ctype,
-                            object_id=obj._get_pk_val(), vote=vote)
-
-    def get_top(self, Model, limit=10, reversed=False):
-        """
-        Get the top N scored objects for a given model.
-
-        Yields (object, score) tuples.
-        """
-        ctype = ContentType.objects.get_for_model(Model)
-        query = """
-        SELECT object_id, SUM(vote) as %s
-        FROM %s
-        WHERE content_type_id = %%s
-        GROUP BY object_id""" % (
-            connection.ops.quote_name('score'),
-            connection.ops.quote_name(self.model._meta.db_table),
-        )
-
-        # MySQL has issues with re-using the aggregate function in the
-        # HAVING clause, so we alias the score and use this alias for
-        # its benefit.
-        if settings.DATABASE_ENGINE == 'mysql':
-            having_score = connection.ops.quote_name('score')
-        else:
-            having_score = 'SUM(vote)'
-        if reversed:
-            having_sql = ' HAVING %(having_score)s < 0 ORDER BY %(having_score)s ASC LIMIT %%s'
-        else:
-            having_sql = ' HAVING %(having_score)s > 0 ORDER BY %(having_score)s DESC LIMIT %%s'
-        query += having_sql % {
-            'having_score': having_score,
-        }
-
-        cursor = connection.cursor()
-        cursor.execute(query, [ctype.id, limit])
-        results = cursor.fetchall()
-
-        # Use in_bulk() to avoid O(limit) db hits.
-        objects = Model.objects.in_bulk([id for id, score in results])
-
-        # Yield each object, score pair. Because of the lazy nature of generic
-        # relations, missing objects are silently ignored.
-        for id, score in results:
-            if id in objects:
-                yield objects[id], int(score)
-
-    def get_bottom(self, Model, limit=10):
-        """
-        Get the bottom (i.e. most negative) N scored objects for a given
-        model.
-
-        Yields (object, score) tuples.
-        """
-        return self.get_top(Model, limit, True)
-
-    def get_for_user(self, obj, user):
-        """
-        Get the vote made on the given object by the given user, or
-        ``None`` if no matching vote exists.
-        """
-        if not user.is_authenticated():
-            return None
-        ctype = ContentType.objects.get_for_model(obj)
-        try:
-            vote = self.get(content_type=ctype, object_id=obj._get_pk_val(),
-                            user=user)
-        except models.ObjectDoesNotExist:
-            vote = None
-        return vote
-
-    def get_for_user_in_bulk(self, objects, user):
-        """
-        Get a dictionary mapping object ids to votes made by the given
-        user on the corresponding objects.
-        """
-        vote_dict = {}
-        if len(objects) > 0:
-            ctype = ContentType.objects.get_for_model(objects[0])
-            votes = list(self.filter(content_type__pk=ctype.id,
-                                     object_id__in=[obj._get_pk_val() \
-                                                    for obj in objects],
-                                     user__pk=user.id))
-            vote_dict = dict([(vote.object_id, vote) for vote in votes])
-        return vote_dict

File voting/models.py

  • Ignore whitespace
-from django.contrib.contenttypes import generic
-from django.contrib.contenttypes.models import ContentType
-from django.contrib.auth.models import User
-from django.db import models
-
-from voting.managers import VoteManager
-
-SCORES = (
-    (u'+1', +1),
-    (u'-1', -1),
-)
-
-class Vote(models.Model):
-    """
-    A vote on an object by a User.
-    """
-    user         = models.ForeignKey(User)
-    content_type = models.ForeignKey(ContentType)
-    object_id    = models.PositiveIntegerField()
-    object       = generic.GenericForeignKey('content_type', 'object_id')
-    vote         = models.SmallIntegerField(choices=SCORES)
-
-    objects = VoteManager()
-
-    class Meta:
-        db_table = 'votes'
-        # One vote per user per object
-        unique_together = (('user', 'content_type', 'object_id'),)
-
-    def __unicode__(self):
-        return u'%s: %s on %s' % (self.user, self.vote, self.object)
-
-    def is_upvote(self):
-        return self.vote == 1
-
-    def is_downvote(self):
-        return self.vote == -1

File voting/templatetags/__init__.py

  • Ignore whitespace
Empty file removed.

File voting/templatetags/voting_tags.py

  • Ignore whitespace
-from django import template
-from django.utils.html import escape
-
-from voting.models import Vote
-
-register = template.Library()
-
-# Tags
-
-class ScoreForObjectNode(template.Node):
-    def __init__(self, object, context_var):
-        self.object = object
-        self.context_var = context_var
-
-    def render(self, context):
-        try:
-            object = template.resolve_variable(self.object, context)
-        except template.VariableDoesNotExist:
-            return ''
-        context[self.context_var] = v
-        return ''
-
-class ScoresForObjectsNode(template.Node):
-    def __init__(self, objects, context_var):
-        self.objects = objects
-        self.context_var = context_var
-
-    def render(self, context):
-        try:
-            objects = template.resolve_variable(self.objects, context)
-        except template.VariableDoesNotExist:
-            return ''
-        context[self.context_var] = Vote.objects.get_scores_in_bulk(objects)
-        return ''
-
-class VoteByUserNode(template.Node):
-    def __init__(self, user, object, context_var):
-        self.user = user
-        self.object = object
-        self.context_var = context_var
-
-    def render(self, context):
-        try:
-            user = template.resolve_variable(self.user, context)
-            object = template.resolve_variable(self.object, context)
-        except template.VariableDoesNotExist:
-            return ''
-        context[self.context_var] = Vote.objects.get_for_user(object, user)
-        return ''
-
-class VotesByUserNode(template.Node):
-    def __init__(self, user, objects, context_var):
-        self.user = user
-        self.objects = objects
-        self.context_var = context_var
-
-    def render(self, context):
-        try:
-            user = template.resolve_variable(self.user, context)
-            objects = template.resolve_variable(self.objects, context)
-        except template.VariableDoesNotExist:
-            return ''
-        context[self.context_var] = Vote.objects.get_for_user_in_bulk(objects, user)
-        return ''
-
-class DictEntryForItemNode(template.Node):
-    def __init__(self, item, dictionary, context_var):
-        self.item = item
-        self.dictionary = dictionary
-        self.context_var = context_var
-
-    def render(self, context):
-        try:
-            dictionary = template.resolve_variable(self.dictionary, context)
-            item = template.resolve_variable(self.item, context)
-        except template.VariableDoesNotExist:
-            return ''
-        context[self.context_var] = dictionary.get(item.id, None)
-        return ''
-
-def do_score_for_object(parser, token):
-    """
-    Retrieves the total score for an object and the number of votes
-    it's received and stores them in a context variable which has
-    ``score`` and ``num_votes`` properties.
-
-    Example usage::
-
-        {% score_for_object widget as score %}
-
-        {{ score.score }}point{{ score.score|pluralize }}
-        after {{ score.num_votes }} vote{{ score.num_votes|pluralize }}
-    """
-    bits = token.contents.split()
-    if len(bits) != 4:
-        raise template.TemplateSyntaxError("'%s' tag takes exactly three arguments" % bits[0])
-    if bits[2] != 'as':
-        raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
-    return ScoreForObjectNode(bits[1], bits[3])
-
-def do_scores_for_objects(parser, token):
-    """
-    Retrieves the total scores for a list of objects and the number of
-    votes they have received and stores them in a context variable.
-
-    Example usage::
-
-        {% scores_for_objects widget_list as score_dict %}
-    """
-    bits = token.contents.split()
-    if len(bits) != 4:
-        raise template.TemplateSyntaxError("'%s' tag takes exactly three arguments" % bits[0])
-    if bits[2] != 'as':
-        raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
-    return ScoresForObjectsNode(bits[1], bits[3])
-
-def do_vote_by_user(parser, token):
-    """
-    Retrieves the ``Vote`` cast by a user on a particular object and
-    stores it in a context variable. If the user has not voted, the
-    context variable will be ``None``.
-
-    Example usage::
-
-        {% vote_by_user user on widget as vote %}
-    """
-    bits = token.contents.split()
-    if len(bits) != 6:
-        raise template.TemplateSyntaxError("'%s' tag takes exactly five arguments" % bits[0])
-    if bits[2] != 'on':
-        raise template.TemplateSyntaxError("second argument to '%s' tag must be 'on'" % bits[0])
-    if bits[4] != 'as':
-        raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
-    return VoteByUserNode(bits[1], bits[3], bits[5])
-
-def do_votes_by_user(parser, token):
-    """
-    Retrieves the votes cast by a user on a list of objects as a
-    dictionary keyed with object ids and stores it in a context
-    variable.
-
-    Example usage::
-
-        {% votes_by_user user on widget_list as vote_dict %}
-    """
-    bits = token.contents.split()
-    if len(bits) != 6:
-        raise template.TemplateSyntaxError("'%s' tag takes exactly four arguments" % bits[0])
-    if bits[2] != 'on':
-        raise template.TemplateSyntaxError("second argument to '%s' tag must be 'on'" % bits[0])
-    if bits[4] != 'as':
-        raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
-    return VotesByUserNode(bits[1], bits[3], bits[5])
-
-def do_dict_entry_for_item(parser, token):
-    """
-    Given an object and a dictionary keyed with object ids - as
-    returned by the ``votes_by_user`` and ``scores_for_objects``
-    template tags - retrieves the value for the given object and
-    stores it in a context variable, storing ``None`` if no value
-    exists for the given object.
-
-    Example usage::
-
-        {% dict_entry_for_item widget from vote_dict as vote %}
-    """
-    bits = token.contents.split()
-    if len(bits) != 6:
-        raise template.TemplateSyntaxError("'%s' tag takes exactly five arguments" % bits[0])
-    if bits[2] != 'from':
-        raise template.TemplateSyntaxError("second argument to '%s' tag must be 'from'" % bits[0])
-    if bits[4] != 'as':
-        raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
-    return DictEntryForItemNode(bits[1], bits[3], bits[5])
-
-register.tag('score_for_object', do_score_for_object)
-register.tag('scores_for_objects', do_scores_for_objects)
-register.tag('vote_by_user', do_vote_by_user)
-register.tag('votes_by_user', do_votes_by_user)
-register.tag('dict_entry_for_item', do_dict_entry_for_item)
-
-# Simple Tags
-
-def confirm_vote_message(object_description, vote_direction):
-    """
-    Creates an appropriate message asking the user to confirm the given vote
-    for the given object description.
-
-    Example usage::
-
-        {% confirm_vote_message widget.title direction %}
-    """
-    if vote_direction == 'clear':
-        message = 'Confirm clearing your vote for <strong>%s</strong>.'
-    else:
-        message = 'Confirm <strong>%s</strong> vote for <strong>%%s</strong>.' % vote_direction
-    return message % (escape(object_description),)
-
-register.simple_tag(confirm_vote_message)
-
-# Filters
-
-def vote_display(vote, arg=None):
-    """
-    Given a string mapping values for up and down votes, returns one
-    of the strings according to the given ``Vote``:
-
-    =========  =====================  =============
-    Vote type   Argument               Outputs
-    =========  =====================  =============
-    ``+1``     ``"Bodacious,Bogus"``  ``Bodacious``
-    ``-1``     ``"Bodacious,Bogus"``  ``Bogus``
-    =========  =====================  =============
-
-    If no string mapping is given, "Up" and "Down" will be used.
-
-    Example usage::
-
-        {{ vote|vote_display:"Bodacious,Bogus" }}
-    """
-    if arg is None:
-        arg = 'Up,Down'
-    bits = arg.split(',')
-    if len(bits) != 2:
-        return vote.vote # Invalid arg
-    up, down = bits
-    if vote.vote == 1:
-        return up
-    return down
-
-register.filter(vote_display)

File voting/tests/__init__.py

  • Ignore whitespace
Empty file removed.

File voting/tests/models.py

  • Ignore whitespace
-from django.db import models
-
-class Item(models.Model):
-    name = models.CharField(max_length=50)
-
-    def __str__(self):
-        return self.name
-
-    class Meta:
-        ordering = ['name']

File voting/tests/runtests.py

  • Ignore whitespace
-import os, sys
-os.environ['DJANGO_SETTINGS_MODULE'] = 'voting.tests.settings'
-
-from django.test.simple import run_tests
-
-failures = run_tests(None, verbosity=9)
-if failures:
-    sys.exit(failures)

File voting/tests/settings.py

  • Ignore whitespace
-import os
-
-DIRNAME = os.path.dirname(__file__)
-
-DATABASE_ENGINE = 'sqlite3'
-DATABASE_NAME = os.path.join(DIRNAME, 'database.db')
-
-#DATABASE_ENGINE = 'mysql'
-#DATABASE_NAME = 'tagging_test'
-#DATABASE_USER = 'root'
-#DATABASE_PASSWORD = ''
-#DATABASE_HOST = 'localhost'
-#DATABASE_PORT = '3306'
<