2

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?

Dmitry Loparev
  • 462
  • 2
  • 9
qraq
  • 318
  • 3
  • 11

3 Answers3

4

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 :)

Community
  • 1
  • 1
Dmitry Loparev
  • 462
  • 2
  • 9
  • After long cogitations I decided to use @dimamobile's suggestion to create a custom templatetag. Anyway thank you all guys for help. – qraq May 11 '14 at 21:39
1

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

Patrick Bassut
  • 3,310
  • 5
  • 31
  • 54
  • Thank you @PatrickBassut and @dimamobile for this useful hint, but I need to call my user_vote instance for multiple posts (For example 15 last posts). Should I try to call user_vote and pass `request` parameter in template? – qraq May 09 '14 at 19:59
1

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()
Ramez Ashraf
  • 873
  • 6
  • 14