Question

I've got 2 models

class Post(models.Model):
    user = models.ForeignKey(User, verbose_name='User')
    content = models.TextField(verbose_name='Text', max_length=4000)
    date = models.DateTimeField(verbose_name='Date', default=now())

class Vote(models.Model):
    vote = models.IntegerField(choices=VOTE, verbose_name='Vote')
    post = models.ForeignKey(Post, verbose_name='Post')
    user = models.ForeignKey(User, verbose_name='User')

and view which load last 15 posts:

posts = Post.objects.all().order_by('-date')[:15]

Now I want to have information about active user vote in all of my queryset objects

I thought about custom method in Post model which will check logged user and get vote objects:

def user_vote(self):
    try:
        data = Vote.objects.filter(post=self, user=request.user)
        return data.vote
    except ObjectDoesNotExist:
        #not voted

But it seems django dont allow to use request in model. Any other ideas?

Was it helpful?

Solution

You can pass user as argument to method like this:

def user_vote(self, user):

also I guess you need to get a Vote instance, not queryset, so you should user .get method instead .filter:

def user_vote(self, user):
    try:
        data = Vote.objects.get(post=self, user=user)
        return data.vote
    except ObjectDoesNotExist:
        #not voted

then you can call this method with Post instance:

post.user_vote(request.user)

UPDATE

Django not allow to use method with arguments in template. So in your case better to refactor this method into templatetag:

def get_user_vote(post, user):
    try:
        data = Vote.objects.get(post=post, user=user)
        return data.vote
    except ObjectDoesNotExist:
        #not voted

You can find manual here https://stackoverflow.com/a/6493001/3291969

don't forget to register it :)

OTHER TIPS

That's not a django problem, it's because request isn't anywhere in the scope of your code. If you pass request to your model's method it will work. Something like:

def user_vote(self, request):
        try:
            data = Vote.objects.get(post=self, user=request.user)
            return data.vote
        except Vote.DoesNotExist:
            #not voted

and call it like this with your Post instance:

# Note the request being passed as a parameter
vote = post.user_vote(request)

UPDATE:

To get all votes from a user you could do something like this:

votes = Vote.objects.filter(post=self, user=request.user)
return reduce(lambda x, y: x.vote + y.vote, votes, 0) 

we set a 0 at the end, so in cases where there's no votes from this user, we'll get a 0 as a return. This will sum every vote and return it.

If you don't want to sum these votes, change the line:

return reduce(lambda x, y: x.vote + y.vote, votes, 0) 

to:

return map(lambda x, y: x.vote + y.vote, votes) 

and this will get you a list with all the votes from the request.user user

I think you're looking for this package: https://pypi.python.org/pypi/django-crequest/1.0

Description:

crequest will bring you current request object of your django application from anywhere in your code.

And it is used like this:

from crequest.middleware import CrequestMiddleware
current_request = CrequestMiddleware.get_request()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top