bashu / django-secretballot Goto Github PK
View Code? Open in Web Editor NEW🗳 Django voting application that allows semi-anonymous voting
Home Page: https://django-secretballot.readthedocs.io
License: BSD 2-Clause "Simplified" License
🗳 Django voting application that allows semi-anonymous voting
Home Page: https://django-secretballot.readthedocs.io
License: BSD 2-Clause "Simplified" License
Django==2.1.2
djangorestframework==3.8.2
django-secretballot==1.0.0
pytest-django==3.4.3
Python 3.7.0
When I use the following apps.py code
from django.apps import AppConfig
import secretballot
class MyConfig(AppConfig):
name = 'app'
verbose_name = 'My project'
def ready(self):
host_model = self.get_model("Host")
# secretballot.enable_voting_on(host_model)
My full test suite (111 tests) passes
If I uncomment the enable_voting_on line, pytest breaks during collection collected 83 items / 4 errors
with errors like this:
================================================== ERRORS ==================================================$
_________________________________ ERROR collecting app/tests/admin_tests.py ________________________________$
/usr/local/lib/python3.7/site-packages/py/_path/local.py:668: in pyimport
__import__(modname)
app/tests/__init__.py:6: in <module>
from .viewsets_tests import * # noqa: F401, F403
app/tests/viewsets_tests/__init__.py:7: in <module>
from .user_tests import *
<frozen importlib._bootstrap>:983: in _find_and_load
???
<frozen importlib._bootstrap>:967: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:668: in _load_unlocked
???
<frozen importlib._bootstrap>:638: in _load_backward_compatible
???
/usr/local/lib/python3.7/site-packages/_pytest/assertion/rewrite.py:290: in load_module
six.exec_(co, mod.__dict__)
app/tests/viewsets_tests/user_tests.py:12: in <module>
from app.viewsets import UserViewSet
app/viewsets/__init__.py:6: in <module>
from .hosts import HostViewSet # noqa F401
app/viewsets/hosts.py:8: in <module>
class HostViewSet(viewsets.ModelViewSet):
app/viewsets/hosts.py:9: in HostViewSet
queryset = Host.objects.filter(display=True)
/usr/local/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python3.7/site-packages/secretballot/__init__.py:59: in get_queryset
content_type = ContentType.objects.get_for_model(self.model).id
/usr/local/lib/python3.7/site-packages/django/contrib/contenttypes/models.py:51: in get_for_model
ct = self.get(app_label=opts.app_label, model=opts.model_name)
/usr/local/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:393: in get
num = len(clone)
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:250: in __len__
self._fetch_all()
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:1186: in _fetch_all
self._result_cache = list(self._iterable_class(self))
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:54: in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/usr/local/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1063: in execute_sql
cursor = self.connection.cursor()
/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py:255: in cursor
return self._cursor()
/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py:232: in _cursor
self.ensure_connection()
E Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixture$
to enable it.
All errors seem to occur in my host viewset, which looks like this
class HostViewSet(viewsets.ModelViewSet):
queryset = Host.objects.filter(display=True)
serializer_class = HostSerializer
lookup_field = 'slug'
…
Commenting the queryset line of this viewset fixes the collection and 109 tests pass (only those related to the viewset break due to missing queryset).
It's interesting to see that the viewset related to the model with voting enabled would fail this way.
@jamesturk do you have a suggestion to fix the queryset line ? Or should this be supported by django-secretballot and require some modification on secretballot's side ?
I suppose django-secretballot
is not adapted to string IDs
I need a way to query a class to see if voting is enabled for it. I cannot safely do eg. hasattr(cls, 'votes') because the enable_voting_on function allows the caller to specify names for the attributes.
My proposal is to add this line to the bottom of function enable_voting_on:
setattr(class, '_voting_enabled', 1)
This unique attribute (aka marker) will allow me to check if voting is enabled without having to worry about custom attribute names specified to enable_voting_on.
Getting issue when migrating everything in empty database. After command manage.py migrate
getting error:
File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/django/db/models/manager.py", line 228, in all
return self.get_queryset()
File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/secretballot/init.py", line 58, in get_queryset
content_type = ContentType.objects.get_for_model(self.model).id
File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/django/contrib/contenttypes/models.py", line 80, in get_for_model
"Error creating new content types. Please make sure contenttypes "
RuntimeError: Error creating new content types. Please make sure contenttypes is migrated before trying to migrate apps individually.
I'm sure this is caused by __init__.py
file trying to query ContentType
which has been not migrated to database at the time.
Workaround was editing init.py file where it queries database
try:
content_type = ContentType.objects.get_for_model(self.model).id
except:
content_type = None
while migrating.
The default JSON response uses single quotes in the variable name, but JSON requires double strings. Simple fix on line 71 of views.py:
body = "{'num_votes':%d}" % votes
to
body = '{"num_votes":%d}' % votes
Following the latest changes, can you please release a new version to PyPi @jamesturk?
import secretballot
from django.contrib.auth.models import User
secretballot.enable_voting_on(User)
All works fine.
By if I trying migrate db, i've got.
ValueError: Could not find manager VotableManager in secretballot.
Please note that you need to inherit from managers you dynamically generated with 'from_queryset()'.
Hi,
This repository seems to lack maintenance, I propose myself as a new maintainer.
Could you give me the right to push in your repository or just transfer it on my account in github?
Thank you
/home/zanklord/programas/python/hearthstone/webapp/secretballot/init.py:48: RemovedInDjango18Warning: VotableManager.get_query_set
method should be renamed get_queryset
.
class VotableManager(base_manager):
solved renaming "def get_query_set(self):" to "def get_queryset(self):"
Hi, I'm using django-secretballot with django-likes .. I just want any example of how to make unlike/unvote .. i open issue on django-likes https://github.com/praekelt/django-likes/issues/36 , but no response :(
drop Python <2.7 support and add 3.3 support
Used the latest version of django-secretballot, django v.1.9.5, used python3 and it raises an error after launching server
Internal Server Error: /
Traceback (most recent call last):
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 123, in get_response
response = middleware_method(request)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/middleware.py", line 6, in process_request
request.secretballot_token = self.generate_token(request)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/likes/middleware.py", line 19, in generate_token
return md5(s).hexdigest()
TypeError: Unicode-objects must be encoded before hashing
I am pretty green with python and django so I am not confident that your code is the problem. But when I comment out the middleware (SecretBallotIpUseragentMiddleware) the tests all pass.
Dependabot couldn't authenticate with https://pypi.python.org/simple/.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
Objects with voting enabled that are retrieved using django.shortcuts.get_object_or_404 don't have the total_upvotes and total_downvotes attributes for some reason. This causes the total_votes property to fail as well. Not sure what to suggest as far as a fix goes, but it's worth investigating.
Setup.py do not install content in the secretballot.migrations package. This code fixes this:
setup(
...
package_dir={'secretballot': 'secretballot'},
packages=['secretballot', 'secretballot.migrations'],
package_data={
'secretballot': [
'migrations/*.*',
],
},
zip_safe=False,
...
)
zip_safe is necessary because migrations do not work properly on eggs.
subj
Line 18 is missing a ":".
Thanks.
How can I contribute?
I got this error
[Sun Sep 08 18:53:01 2013] [error] [client 127.0.0.1] raise exceptions.ImproperlyConfigured('%s isn't a middleware module' % middleware_path)
[Sun Sep 08 18:53:01 2013] [error] [client 127.0.0.1] ImproperlyConfigured: SecretBallotIpUseragentMiddleware isn't a middleware module
Do I define it right?
MIDDLEWARE_CLASSES = (
'SecretBallotIpUseragentMiddleware',
)
I dont know how to solve this problem but i am not getting it right and i want to resolve it asap Please help me out
My model:
class Question(models.Model):
title = models.CharField(max_length=100)
body = models.CharField(max_length=200)
secretballot.enable_voting_on(Question)
So, I'm trying to get op rated objects:
Question.objects.all().order_by('vote_total')
and get this error:
FieldError: Cannot resolve keyword 'vote_total' into field. Choices are: body, id, titel, votes
What i'm doing wrong?
I have a Django Rest Framework api, and integrated secretballot with one of my models.
I see that django-secretballot auto-generated some views
$ docker exec -ti $(docker ps |grep 'backend'|awk '{print $1}') ./manage.py show_urls | grep vote
/secretballot/vote/ django.contrib.admin.options.changelist_view admin:secretballot_vote_changelist
/secretballot/vote/<path:object_id>/ django.views.generic.base.RedirectView
/secretballot/vote/<path:object_id>/change/ django.contrib.admin.options.change_view admin:secretballot_vote_change
/secretballot/vote/<path:object_id>/delete/ django.contrib.admin.options.delete_view admin:secretballot_vote_delete
/secretballot/vote/<path:object_id>/history/ django.contrib.admin.options.history_view admin:secretballot_vote_history
/secretballot/vote/add/ django.contrib.admin.options.add_view admin:secretballot_vote_add
/secretballot/vote/autocomplete/ django.contrib.admin.options.autocomplete_view admin:secretballot_vote_autocomplete
But we only make public our api (all urls starting with /api/
), and I'd like a format that is more aligned to DRF standards.
@jamesturk have you already used DRF before ? if yes, do you have any suggestion for a solution more tightly coupled with DRF ? Other projects have a viewset or serializer available to make it DRF-compatible.
Some 3-rd party applications may not use RequestContext instances to show their pages. This is very annoying, but sometimes I can't do anything with it.
I suggest you to use
request.META.get('REMOTE_ADDR', 'Not defined')
instead
request.META['REMOTE_ADDR']
This will help to override 500 errors sometimes.
I am receiving the following error on one of my models.
One or more models did not validate:
modelname: Accessor for m2m field 'votes' clashes with related m2m field 'Vote.modelname_set'
Assistance highly appreciated
Refer to https://github.com/jamesturk/django-secretballot/blob/master/secretballot/views.py#L54. If the template being rendered uses get_total
from https://github.com/jamesturk/django-secretballot/blob/master/secretballot/__init__.py#L42 then the VotableManager is not used, resulting in attributes upvotes_name
and downvotes_name
not being glued to the object.
I'll try and recreate the problem in a test.
I don't see any immediate solution yet except for a nasty hack in the get_total
method.
Hi. django-likes
has dependency on secretballot but it needs a new release for 1.9+ compatibility. The secretballot repo's latest code is ready for 1.9+.
Without Ajax it worked well, but with ajax:
Internal Server Error: /likes/like/interview_questions-problem/23/1
Traceback (most recent call last):
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 883, in _resolve_lookup
current = current[bit]
TypeError: 'Problem' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/likes/views.py", line 49, in like
"content_type": url_friendly_content_type,
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/views.py", line 66, in vote
body = t.render(c)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/backends/django.py", line 95, in render
return self.template.render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 206, in render
return self._render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 197, in _render
return self.nodelist.render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 992, in render
bit = node.render_annotated(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 959, in render_annotated
return self.render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/defaulttags.py", line 326, in render
return nodelist.render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 992, in render
bit = node.render_annotated(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 959, in render_annotated
return self.render(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 1043, in render
output = self.filter_expression.resolve(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 709, in resolve
obj = self.var.resolve(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 850, in resolve
value = self._resolve_lookup(context)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 891, in _resolve_lookup
current = getattr(current, bit)
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/__init__.py", line 43, in get_total
return getattr(self, upvotes_name) - getattr(self, downvotes_name)
AttributeError: 'Problem' object has no attribute 'total_upvotes'
secretballot v.0.5.0
Django 1.9.5
Python 3
next release should be 1.11+ only, so can switch to new middleware format
I've been using secretballot very happily for several years to run a 'windsurfer of the year' vote, this year I'm getting a few reports that some people are being told they have voted, when they haven't - since last year.
I have no means of knowing if someone else on the same IP address had already voted, it is possible but they claim that no one else voted from their location.
Is it possible that they are still blocked by having done last years vote? If so, is there a means of removing all the previous votes? (Or at least the old IP addresses from previous years).
I was checking the documentation for a management command or similar, but I couldn't see anything.
Thanks,
-Alastair
a few deprecation warnings from 1.9 and a breaking change in how default managers work
It has been years since I've had any need for this project, and I'd love to hand it over to someone that cares about it and wants to maintain it. If you're seeing this get in touch and I'd be glad to transfer. I have no plans to release any versions after 1.0.0 right now.
I think I must have implemented incorrectly but I cannot work out how to get vote_total, total_upvotes and total_downvotes. I'm adding an upvote or downvote through a JS ajax call.
javascript.
function projectVote(pk, value) {
info = [];
info[0] = value; //1 is passed for upvote and -1 for downvote
$.ajax({
url : '/vote/project/' + pk + '/',
type : 'POST',
data : { info : info },
success : function(json) {
console.log(json);
$("#upvotes_" + pk.toString()).text(json.upvotes);
$("#downvotes_" + pk.toString()).text(json.downvotes);
},
error : function(xhr,errmsg,err) {
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
})
}
It calls this view in views.py
def project_vote(request, pk):
obj = Project.objects.get(pk=pk)
info = request.POST.getlist('info[]')
vote(request, Project, obj.id, int(info[0]))
response_data = {
'votes' : obj.vote_total,
'upvotes' : obj.total_upvotes,
'downvotes' : obj.total_downvotes,
}
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
I have enabled voting in apps.py
from django.apps import AppConfig
from django.apps import apps
class ProjectsConfig(AppConfig):
name = 'projects'
def ready (self):
project_model = apps.get_model("projects", 'Project')
secretballot.enable_voting_on(project_model)
With the ajax return I get 'Project' object has no attribute 'vote_total'
so it is clearly failing when I define the response data. How do I access the votes. Please note, if I look at the database on the secretballot_vote table, I can see the vote.
When I installed this I couldn't get it to work, as it was failing on an SQL error. After investigating I fixed the issue with a manage.py migrate
which set up the necessary database tables.
This step isn't in the installation instructions, so should be added.
Title was copied from the README.
Where is django-secretballot 2.0 ? I can only see 1.0.0 or below.
Is that just a typo and 1.0.0 is compatible with latest django and python ?
User-agent is not required, but middleware.py expects it. If the UA doesn't supply an agent it causes a runtime error. As this code is in middleware the whole app is affected.
On line 20:
s = ''.join((request.META['REMOTE_ADDR'], request.META['HTTP_USER_AGENT']))
would be better put as
s = ''.join((request.META['REMOTE_ADDR'], request.META.get('HTTP_USER_AGENT', '')))
This issue is related to the closed issue: #34
Secretballot currently throws the following error when trying django is trying initialize the applications before we are running initial migrations for a new dev project.
web_1 | django.db.utils.ProgrammingError: relation "django_content_type" does not exist
web_1 | LINE 1: ..."."app_label", "django_content_type"."model" FROM "django_co...
As mentioned in the previously closed issue this has to do with the ContentType
call in __init__.py
when enabling voting in a model in the ready()
method of the AppConfig
class.
Looking at the various solutions mentioned, we are currently importing and enable the voting all in the ready
method, in accordance with django application loading: https://docs.djangoproject.com/en/2.1/ref/applications/#how-applications-are-loaded
class ProductConfig(AppConfig):
name = 'products'
def ready(self):
import secretballot
from .models import Product
secretballot.enable_voting_on(Product, manager_name='objects')
This configuration still throws the same error as above.
Going in a adding the code below to the secretballot __init__.py
will resolve this for initializing the django applications and running migrations, but it is not really a long term solution.
try:
content_type = ContentType.objects.get_for_model(self.model).id
except:
content_type = None
The current solution we are running is to change the order of the INSTALLED_APPS
in django settings. Instead of following the django guidelines of having the order of local apps first, i.e. your local app should take precedence for overriding templates, static files, etc... Now to be able to run initial migrations django apps needs to be in the top of the INSTALLED_APPS
which introduces a requirement of order.
INSTALLED_APPS = [
# Django
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.postgres',
# Local
'product.apps.ProductsConfig',
# Dist
'secretballot',
]
Any thoughts on this and how it can be avoided?
Python: 3.5.6
Django version: 2.0.3
Thanks
There is a problem with unicode encoding of User-Agent.
class SecretBallotIpUseragentMiddleware(SecretBallotMiddleware):
def generate_token(self, request):
s = ''.join((request.META['REMOTE_ADDR'], request.META.get('HTTP_USER_AGENT', '')))
return md5(s.encode('utf8')).hexdigest()
UnicodeDecodeError: 'ascii' codec can't decode byte ...
We should remove encode('utf-8')
Hello!
In class Vote(models.Model) you have:
def __str__(self): return '{} from {} on {}'.format(self.get_vote_display(), self.token, self.content_object)
Use, please u'{} from {} on {}'
to correct utf-8 encoding, because you return self.content_object which can be in unicode.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.