Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Scott Robinson
authored and
Scott Robinson
committed
Oct 10, 2014
0 parents
commit 1a266b5
Showing
13 changed files
with
768 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
*.pyc | ||
*~ | ||
.DS_Store | ||
.AppleDouble | ||
*.swp | ||
*.egg-info | ||
*.egg | ||
*.EGG | ||
*.EGG-INFO | ||
bin | ||
build | ||
develop-eggs | ||
.hg | ||
.svn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
The primary author of django-voting is Scott Robinson. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Copyright (c) 2014 Scott Robinson | ||
|
||
Permission is hereby granted, free of charge, to any person | ||
obtaining a copy of this software and associated documentation | ||
files (the "Software"), to deal in the Software without | ||
restriction, including without limitation the rights to use, | ||
copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following | ||
conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
Django-Voting | ||
============= | ||
|
||
Django-Voting is a basic app for tracking the number of votes placed for | ||
any object in the database. It provides the ability to upvote and downvote. | ||
|
||
This project is based on the [django-hitcount][1] by Damon Timm. | ||
|
||
TODO | ||
---- | ||
|
||
Most of the basic functionality you'd need for a simple voting system has | ||
been implemented. Possible additions are: | ||
|
||
- Better JavaScript support for ajax calls | ||
- Better UI/utilities for the admin site | ||
- Rate-limiting to avoid vote-spamming | ||
- Options for allowing users to vote multiple times on an object | ||
|
||
Installation: | ||
------------- | ||
|
||
Simplest way to formally install is to run: | ||
|
||
./setup.py install | ||
|
||
Or, you could do a PIP installation: | ||
|
||
pip install -e git://github.com/scottwrobinson/django-voting.git#egg=django-voting | ||
|
||
Or, you can link the source to your `site-packages` directory. This is useful | ||
if you plan on pulling future changes and don't want to keep running | ||
`./setup.py install`. | ||
|
||
cd ~/src | ||
git clone https://github.com/scottwrobinson/django-voting.git | ||
sudo ln -s `pwd`/django-voting/voting `python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"`/voting | ||
|
||
|
||
Then modify your settings.py, adding the package voting in INSTALLED_APPS | ||
|
||
INSTALLED_APPS = ( | ||
'...', | ||
'voting', | ||
) | ||
|
||
|
||
You need to add one line to your urls.py file. | ||
---------------------------------------------- | ||
urlpatterns = patterns('', | ||
url(r'^site/ajax/vote$', # you can change this url if you would like | ||
update_vote_count_ajax, | ||
name='votecount_update_ajax'), # keep this name the same | ||
|
||
|
||
Ajax Call | ||
--------- | ||
The ajax call to the `update_vote_count_ajax` view requires two variables: | ||
|
||
- direction | ||
The vote direction. +1 for upvote and -1 for downvote. | ||
- votecount_pk | ||
The pk of the object to be voted on. Can be retrieved using the {% get_vote_object_pk for [object] %} tag (see below). | ||
- csrfmiddlewaretoken (optional) | ||
The CSRF token. Only required if CSRF validation is enabled. | ||
|
||
The ajax view returns two variables back: | ||
|
||
- status | ||
"success" for successful votes and "failed" for votes that did not get recorded. | ||
- net_change | ||
The net change of the object's vote total. | ||
|
||
Custom Template Tags | ||
-------------------- | ||
Don't forget to load the custom tags with: `{% load voting_tags %}` | ||
|
||
- Return total votes for an object: | ||
{% get_vote_count for [object] %} | ||
|
||
- Get total votes for an object as a specified variable: | ||
{% get_vote_count for [object] as [var] %} | ||
|
||
- Get total votes for an object over a certain time period: | ||
{% get_vote_count for [object] within ["days=1,minutes=30"] %} | ||
|
||
- Get total votes for an object over a certain time period as a variable: | ||
{% get_vote_count for [object] within ["days=1,minutes=30"] as [var] %} | ||
|
||
- Get or create the pk for the given object: | ||
{% get_vote_object_pk for [object] %} | ||
|
||
- Get or create the pk for the given object as a specified variable: | ||
{% get_vote_object_pk for [object] as [var] %} | ||
|
||
[1]:https://github.com/thornomad/django-hitcount |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import os | ||
from setuptools import setup, find_packages | ||
|
||
def read(fname): | ||
return open(os.path.join(os.path.dirname(__file__), fname)).read() | ||
|
||
setup( | ||
name = "django-voting", | ||
version = "0.1", | ||
url = 'http://github.com/scottwrobinson/django-voting', | ||
license = 'BSD', | ||
description = "Django voting application that tracks the number of votes for any DB objects.", | ||
long_description = read('README.md'), | ||
|
||
author = 'Scott Robinson', | ||
|
||
packages = find_packages(), | ||
|
||
classifiers=[ | ||
'Development Status :: 4 - Beta', | ||
'Environment :: Plugins', | ||
'Framework :: Django', | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: BSD License', | ||
'Programming Language :: Python', | ||
'Topic :: Software Development :: Libraries :: Python Modules', | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
VERSION = (0, 1, 0, 'beta', 1) | ||
|
||
def get_version(): | ||
version = '%s.%s' % (VERSION[0], VERSION[1]) | ||
if VERSION[2]: | ||
version = '%s.%s' % (version, VERSION[2]) | ||
else: | ||
if VERSION[3] != 'final': | ||
version = '%s %s' % (version, VERSION[3]) | ||
return version | ||
|
||
__version__ = get_version() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from django.core.exceptions import PermissionDenied | ||
|
||
def delete_queryset(modeladmin, request, queryset): | ||
# TODO | ||
# | ||
# Right now, when you delete a vote there is no warning or "turing back". | ||
# Consider adding a "are you sure you want to do this?" as is | ||
# implemented in django's contrib.admin.actions file. | ||
|
||
if not modeladmin.has_delete_permission(request): | ||
raise PermissionDenied | ||
else: | ||
if queryset.count() == 1: | ||
msg = "1 vote was" | ||
else: | ||
msg = "%s votes were" % queryset.count() | ||
|
||
for obj in queryset.iterator(): | ||
obj.delete() # calling it this way to get custom delete() method | ||
|
||
modeladmin.message_user(request, "%s successfully deleted." % msg) | ||
delete_queryset.short_description = "DELETE selected votes" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from django.contrib import admin | ||
|
||
from voting.models import Vote, VoteCount | ||
from voting import actions | ||
|
||
def created_format(obj): | ||
''' | ||
Format the created time for the admin. PS: I am not happy with this. | ||
''' | ||
return "%s" % obj.date_created.strftime("%m/%d/%y<br />%H:%M:%S") | ||
created_format.short_description = "Date (UTC)" | ||
created_format.allow_tags = True | ||
created_format.admin_order_field = 'date_created' | ||
|
||
|
||
class VoteAdmin(admin.ModelAdmin): | ||
list_display = (created_format,'user','ip','votecount') | ||
search_fields = ('ip',) | ||
date_hierarchy = 'date_created' | ||
actions = [ actions.delete_queryset, | ||
] | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(VoteAdmin, self).__init__(*args, **kwargs) | ||
self.list_display_links = (None,) | ||
|
||
def get_actions(self, request): | ||
# Override the default `get_actions` to ensure that our model's | ||
# `delete()` method is called. | ||
actions = super(VoteAdmin, self).get_actions(request) | ||
if 'delete_selected' in actions: | ||
del actions['delete_selected'] | ||
return actions | ||
|
||
# TODO: Add inlines to the VoteCount object so we can see a list of the recent | ||
# votes for the object. For this inline to work, we need to: | ||
# a) be able to see the vote data but *not* edit it | ||
# b) have the `delete` command actually alter the VoteCount | ||
# c) remove the ability to 'add new vote' | ||
# | ||
#class VoteInline(admin.TabularInline): | ||
# model = Vote | ||
# fk_name = 'votecount' | ||
# extra = 0 | ||
|
||
class VoteCountAdmin(admin.ModelAdmin): | ||
list_display = ('content_object','vote_sum','modified') | ||
fields = ('upvotes', 'downvotes') | ||
|
||
# TODO: Another option | ||
#The fields option, unlike list_display, may only contain names of fields on the model or the form specified by form. It may contain callables only if they are listed in readonly_fields. | ||
|
||
# TODO - when above is ready | ||
#inlines = [ VoteInline, ] | ||
|
||
admin.site.register(Vote, VoteAdmin) | ||
admin.site.register(VoteCount, VoteCountAdmin) |
Oops, something went wrong.