Как сделать подписку на отдельные продукты для одного и того же пользователя в 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 хранит название, цены и т.д. услуги, которые будут необходимы во время оформления заказа
Но теперь, как я сказал, пользователь получит меню после входа в систему на основе того, какие услуги активны в подписке. Я не могу сделать это в шаблоне. Я передал значение из моих представлений как
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, является лучшей практикой