Как сделать подписку на отдельные продукты для одного и того же пользователя в django

У меня есть сайт, на котором есть некоторые услуги, на которые нужно подписываться индивидуально. Пользователь должен подписаться на те услуги, которые он хочет получить. Сейчас есть три плана подписки: ежемесячный, ежеквартальный и полугодовой. Пользователь должен выбрать один из них индивидуально для каждой услуги, которую он выбирает.

Например, у меня есть три услуги civil, tax, criminal. Теперь пользователь может выбрать подписку Civil на 1 месяц и Criminal на 6 месяцев, следовательно, они тоже будут истекать по отдельности. На основании выбранных услуг он получит меню, как только войдет в систему. Ниже приведен подход, который я использовал для создания моделей.

models.py

SUB_CHOICES = (
('monthly', 'monthly'),
('quaterly', 'quaterly'),
('hf', 'half_yearly'),
('anually', 'anually'),
)


class ServiceProduct(models.Model):
    
    title = models.CharField(max_length=50, null = True)
    code = models.IntegerField(null=True, unique= True)
    price = models.DecimalField(max_digits=10,decimal_places=2,null=True)


    def __str__(self):
        return self.title  


class UserSubscription(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    service_choosen = models.ForeignKey(ServiceProduct, on_delete=models.CASCADE, null=True)
    is_active = models.BooleanField(default= False)
    subscribed_on = models.DateTimeField(null=True)
    expiring_on = models.DateTimeField(null=True)
 

Здесь я подключил модель usermembership к customuser с внешним ключом, чтобы сделать несколько подписок для одного и того же пользователя с классом is_active, который должен переключаться на основе дат подписки и дат истечения срока действия. Модель ServiceProduct хранит название, цены и т.д. услуги, которые будут необходимы во время оформления заказа

This is how the things are getting stored

Но теперь, как я сказал, пользователь получит меню после входа в систему на основе того, какие услуги активны в подписке. Я не могу сделать это в шаблоне. Я передал значение из моих представлений как

views.py

 subuser = request.user

 sub = UserSubscription.objects.filter(user = subuser)
 return render(request, 'testpage.html', {'subuser': subuser, 'sub': sub})

Но в html я не могу написать что-то вроде

{% for cust in sub %} 
   {% if cust.service_choosen.civil.is_active %} 
          do something... 
   {% endif %}
{% endfor %}

Я уверен, что не могу создать правильные модели .Поэтому, пожалуйста, предложите мне, каким будет правильный подход к созданию моделей, которые сделают возможным этот тип метода подписки.

Желаемый результат:

Если пользователь выбирает гражданское дело на месяц и уголовное дело на 6 месяцев, то Гражданское дело должно быть активно для него в течение месяца и Уголовное дело должно быть активно для него в течение 6 месяцев

Я считаю, что is_active будет лучше в качестве метода моделирования. Например, так:

def is_active(self):
    return timezone.now() <= self.expiring_on

потому что он будет "обновляться" автоматически, если пройдет время подписки.

Поделитесь еще views.py и я расскажу вам, как передать контекст в html.

в views.py я бы сначала отфильтровал UserSubscription для выбора только активных подписок

subuser = request.user
sub = UserSubscription.objects.filter(user = subuser, is_active = True)
return render(request, 'testpage.html', {'subuser': subuser, 'sub': sub})

Таким образом, вы можете упростить свой шаблон:

{% for cust in sub %} 
   {% if cust.service_choosen.title == 'civil' %} 
          do something with Civil... 

   {% elif cust.service_choosen.title == 'tax' %}
          do something with Tax... 

   {% elif cust.service_choosen.title == 'criminal' %}
          do something with Criminal... 

   {% endif %}
{% endfor %}

или используя код вместо названия (предположим, коды 1=Гражданское, 2=Налоговое и так далее):

{% for cust in sub %} 
   {% if cust.service_choosen.code == 1 %} 
          do something with Civil... 

   {% elif cust.service_choosen.code == 2 %}
          do something with Tax... 

   {% elif cust.service_choosen.code == 3 %}
          do something with Criminal... 

   {% endif %}
{% endfor %}

В зависимости от того, какой результат вам нужен, вы также можете попробовать обобщить (пример)

{% for cust in sub %} 
  <a href='#'>Service {{ cust.service_choosen.title }}</a>
{% endfor %}

Также учтите, что вычисление is_active на лету, как предложено в ответе NixonSparrow, является лучшей практикой

Вернуться на верх