Yax
Yax

Reputation: 2189

Check a List With If Statement in a Loop Using Python/Django

I have an Article model which I fetch from when a user successfully logs in:

articles = Article.objects.all()

I also have Likes model which has user_id and article_id to record articles users have liked.

articles_liked = Likes.objects.values_list('article_id', flat = True)
users_who_liked = Likes.objects.values_list('user_id', flat = True)

The article_id gives a list of article users have liked while users_who_liked gives a list of users who liked those articles as shown below:

articles_liked = [4, 3, 5, 6, 10]
users_who_liked = [1, 13, 15, 16, 110]

What I want to achieve is to be able to tell if a particular post is already liked by the logged in user in my template.

{% for article in articles %}
    <p>{{article.content}}</p>
        {% if this_user_id in users_who_liked and article.id in articles_liked %}
            <p class = 'likes'> 2 </p>
        {% else %}
            <p class = 'likes already_liked'> 2 </p>
        {% endif %}
{% endfor %}

Let's assume this_user_id = 1 and the articles he/she likes is 4, the if statement returns True for all the articles and the else block never get to be executed.

How can I do this the right way?

Upvotes: 0

Views: 563

Answers (2)

Burhan Khalid
Burhan Khalid

Reputation: 174624

As your Likes object has a reference to both Users and Articles, why not exploit this in your view? That way you control the logic in your view and template just becomes a simple if statement:

def some_view(request):
   articles = Article.objects.all()
   user = request.user
   article_list = []
   for a in articles:
     # Create a tuple, with a flag if the user has liked this article or not.
     article_status = (Likes.objects.filter(article_id=a.pk, user_id=user.pk).exists(), a,)
     article_list.append(article_status)
   return render(request, 'template.html', {'articles': article_list})

Now, in your template you have the following:

{% for liked,article in articles %}
  {% if liked %}
      <strong>You already liked this article!</strong>
  {% endif %}
  {{ article }}
{% endfor %}

Upvotes: 0

timo.rieber
timo.rieber

Reputation: 3867

Your variables articles_liked and users_who_liked are not correlated to each other. They always contain all liked articles and all users who liked, but between them there is no relation in your template context which you can rely on.

Therefore your if statement will always return True for every user who liked any article which has been liked by at least one user.

Assuming from your question that Like has a foreign key (Django docs) to User and a foreign key to Article you could just add a filter to your articles_liked assignment to only retrieve likes from the current user:

articles_liked = Likes.objects.filter(user_id=this_user_id).values_list('article_id', flat = True)

Then in your template you can simply check if the current article is in this list:

{% for article in articles %}
    <p>{{article.content}}</p>

    {% if article.id in articles_liked %}
        <p class = 'likes'> 2 </p>
    {% else %}
        <p class = 'likes already_liked'> 2 </p>
    {% endif %}
{% endfor %}

Upvotes: 1

Related Questions