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?

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

1 Comment

After long cogitations I decided to use @dimamobile's suggestion to create a custom templatetag. Anyway thank you all guys for help.
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

1 Comment

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?
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()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.