Package: django-secretballot
django-secretballotDjango voting application that allows voting without a logged in user.Provides abstract base model for types that the user wishes to allow voting on as well as related utilities including generic views to ease the addition of ‘anonymous’ voting to a Django project.Maintained byBasil Shubin, and some greatcontributors.InstallationFirst install the module, preferably in a virtual environment. It can be installed from PyPI:pipinstalldjango-secretballotSetupFirst of all, you must add this project to your list ofINSTALLED_APPSinsettings.py:INSTALLED_APPS+=["secretballot",]There is only one mandatory configuration option you need to set in yoursettings.py:# In order to attach the voting helpers to a particular model it is enough# to list them here...SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{},}Run./manage.py migrate. This creates the tables in your database
that are necessary for operation.Please seeexampleapplication. This application is used to manually
test the functionalities of this package. This also serves as a good
example.You need Django 1.8 or above to run that. It might run on older
versions but that is not tested.Using voting-enabled modelsOnce a model is voting-enabled a number of special fields are available on all instances:FieldsVotable objects have the following fields:votesManager to of allVoteobjects related to the current model (typically doesn’t need to be accessed directly). Can be renamed by passingvotes_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"votes_name":"vs",},}total_upvotesTotal number of +1 votes. Can be renamed by passingupvotes_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"upvotes_name":"total_upvs",},}total_downvotesTotal number of -1 votes. Can be renamed by passingdownvotes_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"downvotes_name":"total_downvs",},}vote_totalShortcut accessor for (total_upvotesminustotal_downvotes). Can be renamed by passingtotal_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"total_name":"v_total",},}_secretballot_enabledBoolean indicating thatsecretballotis enabled (can be tested for with hasattr). Cannot be renamed, exists for a reliable check that secretballot is available even if all other fields were renamed.MethodsVotable objects have the following custom methods:add_voteFunction that takes atokenand a vote (+1 or -1) and adds or updates the vote for said token. Can be renamed by passingadd_vote_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"add_vote_name":"add_v",},}remove_voteFunction that takes atokenand removes the vote (if present) for said token. Can be renamed by passingremove_vote_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"remove_vote_name":"remove_v",},}Manager functionsA special manager is added that enables the inclusion oftotal_upvotesandtotal_downvotesas well as some extra functionality.This manager by default replaces theobjectsmanager, but this can be altered by passing themanager_nameparameter toSECRETBALLOT_FOR_MODELS, for example:SECRETBALLOT_FOR_MODELS={"<app_label.model_name>":{"manager_name":"ballot_custom_manager",},}There is also an additional method on the Votable manager:from_request(self, request)When called on a votable object’s queryset will add auser_voteattribute that is the vote cast by the current ‘user’ (actually the token assigned to the request), for example:defstory_view(request,slug):story=Story.objects.from_request(request).get(pk=slug)# story has the following extra attributes# user_vote: -1, 0, or +1# total_upvotes: total number of +1 votes# total_downvotes: total number of -1 votes# vote_total: total_upvotes-total_downvotes# votes: related object manager to get specific votes (rarely needed)Tokens and SecretBallotMiddlewareWithout user logins it is impossible to be certain that a user does not vote more than once, but there are several methods to limit abuses.secretballottakes a fairly hands-off approach to this problem, the Vote object has atokenfield that is used to store a uniquely identifying token generated from a request.  To limit how many votes come from a particular ip address it is sufficient to set the token to the IP address, but it is also possible to develop more sophisticated heuristics to limit voters.secretballotuses a simple piece of middleware to do this task, and makes it trival for users to define their own middleware that will use whatever heuristic they desire.SecretBallotMiddlewareis an abstract class that defines agenerate_token(request)method that should return a string to be used for the token.For convenience several middleware have already been defined:SecretBallotIpMiddlewareSimply sets thetokentorequest.META['REMOTE_ADDR']– the user’s IP addressSecretBallotIpUseragentMiddlewareSets thetokento a hash of the user’s ip address and user agent – hopefully slightly more unique than IP aloneIf you wish to define your own middleware simply derive a class fromSecretBallotMiddlewareand implement thegenerate_tokenmethod. If you come up with something that may be useful for others contributions are always welcome.Generic Viewssecretballot.viewsincludes the following generic views:secretballot.views.voteDescription:This view creates or alters a vote on the object ofcontent_typewith a primary key ofobject_id.
If a vote already exists it will be replaced (unless vote is 0 in which case it will be deleted).Thetokenattribute of the vote that is used to prevent unlimited voting is set within this view based on the activeSecretBallotMiddleware.Depending on the parameters given the return value of this view varies:ifredirect_urlis specified it will be used no matter whatiftemplate_nameis specified it will be used (along withtemplate_loader,context_processorsand etc.)withoutredirect_urlortemplate_namea text/json response will be returnedRequired arguments:content_type: class that voting is taking place on (a VotableModel-derived model).May be an instance ofdjango.contrib.contenttypes.models.ContentType, the Model class itself, or an<app_label.model_name>string.object_id: primary key of object to vote onvote: value of this vote (+1, 0, or -1) (0 deletes the vote)Optional arguments:can_vote_test: function that allows limiting if user can vote or not. It’s an optional argument to the view that can be specified in the urlconf that is called before a vote is recorded for a user.Example implementation ofcan_vote_test:fromsecretballot.utilsimportget_vote_modeldefonly_three_votes(request,content_type,object_id,vote):returnget_vote_model().objects.filter(content_type=content_type,token=request.secretballot_token).count()<3Allcan_vote_testmethods must take the non-optional parameters tosecretballot.views.voteand should returnTrueif the vote should be allowed. If the vote is not allowed by default the view will return a 403, but it is also acceptable to raise a different exception.redirect_url: url to redirect to, if present will redirect instead of returning a normal HttpResponsetemplate_name: template to render to, recieves a context containingcontent_objwhich is the object voted upontemplate_loader: template loader to use, defaults todjango.template.loaderextra_context: dictionary containing any extra context, callables will be called at render timecontext_processors: list of context processors for this viewmimetype:  mimetype overrideCreditsdjango-secretballotwas originally started byJames Turkwho has now unfortunately abandoned the project.Licensedjango-secretballotis released under the BSD license.Changes2.0.0 (2021-10-26)drop compatibility code for Django 1.10 and belowmake it possible to customize Vote model per project1.0.0 (2017-12-05)final release that supports Django 1.8 and up0.7.1 (2017-10-03)improved support for Django 2.00.7.0 (2017-05-05)improved support for Django 1.110.6.0 (2016-10-07)support for Django 1.10 new manager rulesadd migrationsfix case where object is not fetched through correct manager0.5.0 (2015-11-02)drop South supportdrop support for Django < 1.8, add support for Django 1.90.4.0 (2015-05-27)drop South supportdrop support for Django < 1.7, add support for Django >= 1.7add Python 3 supportadd a ton of testsfix bug if vote_name was set in enable_voting_on0.3.0 (2015-04-17)related_fields and get_object_or_404 fix from François Chapuisadd property to check if secretballot is present on a classadd indexed timestamps to votes via Simon de Hanmake response valid JSON for mimetype compatibility via Dan Drinkard0.2.3 (2010-03-30)bugfixes, thanks to Gennadiy Potapov0.2.2 (2009-11-27)fixed embarassing SyntaxError in vote0.2.1 (2009-11-24)fix some documentation issues left from 0.1make content_type more flexible (can now take a model, content_type, or ‘app.model’ string)0.2.0 (2009-02-11)replace inheritance from VotableObject with enable_voting_onwhen injecting manager methods inherit from existing manager0.1.0 (2009-01-24)initial working release