How to restrict users voting on their own model

Go To StackoverFlow.com

2

I am using django-voting as a voting application for two of my models. Those both models have fields "author".

How can I restrict a user from voting on a model that has this particular user set as it's author without modifying django-voting app?

Django middleware is the first thing that comes to my mind, but I don't understand it's "proces_view" function. If you think middleware is the right way could you please give an example of how to do it.

2009-06-16 14:28
by aleksandar


4

Add this code anywhere in your settings.py:

from voting.managers import VoteManager

def check_user(func):
    def wrapper(self, obj, user, vote):
        if obj.user != user:
            return func(self, obj, user, vote)
        else:
            return None
            # or raise some exception
    return wrapper

VoteManager.record_vote = check_user(VoteManager.record_vote)

I didn't run this code, maybe it's incorrect, but I hope idea is clear

2009-06-16 17:08
by Glader
Yes, the idea is clear. And it is working. Just for future reference this code can't be put into settings.py. Put it in a file which is going to execute for certain, except settings.py. For example in models.py in your application - aleksandar 2009-06-18 10:51
I think this is the better way of doing it. This way the logic is also written for AJAX calls and it is in one place - aleksandar 2009-06-18 11:14
Be careful with this code if there are objects in your project which can be voted on that do not have a 'user' attribute. In that case you will need to either add a hasattr(obj, 'user') check or wrap everything in a try... except AttributeError - Carl Meyer 2009-06-18 23:38
this is far more elegant than what I had... maybe I ought to refactor : - Jiaaro 2009-06-19 14:36


2

Rather than a middleware hack, why not reroute requests to that particular URI through another view? Then you can performs whatever logic you like, and subsequently call the original view if appropriate.

2009-06-16 14:53
by ozan
that's what I did ; - Jiaaro 2009-06-16 15:29
This is so obvious I don't know why I didn't do it in a first place. Both answers are correct. Which to accept :) - aleksandar 2009-06-18 10:58
The disadvantage of this approach is that you'll be having to make extra database queries to fetch the object being voted on, which will then be repeated within django-voting's own view. So the other solution is more efficient and DRY, although this one doesn't require monkeypatching - Carl Meyer 2009-06-18 23:35


0

Another idea is to use the post_save signal

like so:

from django.db.models.signals import post_save
from voting.models import Vote

def check_user(sender, instance, **kwargs):
    if instance.user == instance.object.user:
        instance.delete()
        # do some other stuff to tell the user it didn't work

post_save.connect(check_user, sender=Vote)

The benefit of doing this vs overriding VoteManager.record_vote is that it's less tightly coupled to the voting module, and if they make changes it's less likely to break your code

edit: as in Glader's answer, you need to make sure that all the objects you're voting on have a 'user' attribute.

2009-06-19 14:46
by Jiaaro
Yes this is good example to - aleksandar 2009-06-23 14:48
Ads