2

I am working on a Django project whereby I want to check if a user is subscribed to a product or not. I have created in my models.py several model instances and I am stuck on how to check if the user is subscribed inside the template. Here is my template where I loop through the fetched data:

<ul>
{% for content in content %}
{% if content.model.is_premium and user.is_subscribed %}
       <li>Premium</li>
 {% else %}
  <li>Not premium</li>
  {% endif %}
 {% endfor %}
 </ul>

Here is my views.py :

@login_required(login_url='/user/login')
def homepage(request):
    content = ModelContent.objects.all()
    categorys = Category.objects.all()
    models = MyModels.objects.all()
    suggestions = MyModels.objects.all()[:3]
    # profiles = Profile.objects.filter(user__is_creator=True)
    context = {"categorys": categorys, "models": models, "content":content, "suggestions":suggestions}
    return render(request, 'users/home.html', context)

And here is the models.py:

User = get_user_model()
class MyModels(models.Model):
    owner = models.ForeignKey(Profile, on_delete=models.CASCADE, null=False, blank=False)
    name = models.CharField(max_length=500, null=False, blank=False)
    username = models.CharField(max_length=500, null=False, blank=False, unique=True)
    title = models.CharField(max_length=500, null=False, blank=False)
    description = models.TextField(max_length=500, null=False, blank=False)
    image = models.ImageField(upload_to='img',  blank=True, null=True)
    placeholder = models.ImageField(upload_to='img',  blank=True, null=True)
    sex = models.CharField(max_length=50, choices=SEX_CHOICES, default=NONE)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=False, blank=False)
    content_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)
    created = models.DateField(auto_now_add=True)
    is_popular = models.BooleanField(default=False)
    is_premium = models.BooleanField(default=False)
    # posted_content = models.ManyToManyField('ModelContent', related_name='model_content')

    def __str__(self):
        return self.username
class ModelContent(models.Model):
model = models.ForeignKey(MyModels, on_delete=models.CASCADE, null=False, blank=False )
title = models.CharField(max_length=500, null=False, blank=False)
date = models.DateTimeField(auto_now_add=True)
content_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)

class Meta:
    ordering = ['-date']

def __str__(self):
    return str(self.title)

class Subscription(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='subscriptions_to_product')
    model = models.ForeignKey(MyModels, on_delete=models.CASCADE, related_name='subscriptions_from_subscriber')
    is_subscribed = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.user.username} subscribed to {self.model.username}"

The views.py is inside an app called 'users' while the models.py is inside an app called 'posts'. I have tried doing this :

{% for content in content %}
    {% if content.model.is_premium %}
        {% with subscription=request.user.subscriptions_to_product.filter(model_id=content.model_id).first %}
            {% if subscription and subscription.is_subscribed %}
                <li>User Subscribed</li>
            {% else %}
                <li>User Not Subscribed</li>
            {% endif %}
        {% endwith %}
    {% else %}
        <li>Not premium</li>
    {% endif %}
{% endfor %}

But it did not work.

victor
  • 134
  • 1
  • 9

1 Answers1

3

This is not the task of the template. Templates should be used only for rendering. Not for business logic. You can use an Exists subquery [Django-doc]:

from django.db.models import F
from django.db.models.functions import Exists

@login_required(login_url='/user/login')
def homepage(request):
    content = ModelContent.objects.annotate(
        is_subscriped=Exists(
            Subscription.objects.filter(
                model__modelcontent=OuterRef('pk'),
                user=request.user,
                is_subscribed=True,
            )
        )
    )
    categorys = Category.objects.all()
    suggestions = MyModels.objects.all()[:3]
    context = {
        'categorys': categorys,
        'content': content,
        'suggestions': suggestions,
    }
    return render(request, 'users/home.html', context)

In the template, you then render this as:

{% for content in content %}
    {% if content.model.is_premium %}
        {% if content.is_subscribed %}
            <li>User Subscribed</li>
        {% else %}
            <li>User Not Subscribed</li>
        {% endif %}
    {% else %}
        <li>Not premium</li>
    {% endif %}
{% endfor %}
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555