I have a django application where I need to check if a user has a valid subscription, otherwise it redirects the user to his/her dashboard.
I was thinking to use the django decorator user_passes_test
but I couldn't find a proper way to create the function to check the user.
My models for user and subscription are:
class CustomUser(AbstractUser):
user_type_data = (
('admin', 'admin'),
('school_admin', 'school_admin'),
('student', 'student'),
)
user_type = models.CharField(
max_length=20, choices=user_type_data, default='student')
address = models.CharField(max_length=500, null=True, blank=True)
city = models.CharField(max_length=200, null=True, blank=True)
zip_code = models.CharField(max_length=100, null=True, blank=True)
country = CountryField(null=True, blank=True)
phone = models.CharField(max_length=200, null=True, blank=True)
selected_course = models.ForeignKey(QuizTheoryCourse, on_delete=models.CASCADE, null=True, blank=True)
class Subscription(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
issue_date = models.DateTimeField(null=True, blank=True)
duration = models.IntegerField(choices=DURATION_CHOICES)
expiration_date = models.DateTimeField()
def __str__(self):
return f'{self.user} - {str(self.expiration_date)}'
def get_expiration(self):
if self.expiration_date:
if self.expiration_date > timezone.now():
expiration_date = self.expiration_date timedelta(days=int(self.duration))
else:
expiration_date = dt.now() timedelta(days=int(self.duration))
else:
expiration_date = dt.now() timedelta(days=int(self.duration))
return expiration_date
def is_subscription_valid(self):
today = timezone.now()
return today < self.expiration_date
The function I am using to pass in the decorator is:
def subscription_valid(user):
try:
superuser = user.is_superuser
user_valid = user.subscription.is_subscription_valid
return superuser or user_valid
except user.DoesNotExist:
return False
My problem is that, anytime the user doesn't have any kind of subscription (let's say it's just registered) I receive an error:
CustomUser has no subscription.
I suppose I have some kind of if/elif statement in the function, but I couldn't figure out how to get around it.
CodePudding user response:
Your idea is good, but there are some erros in your function.
When you try to access to subscription, Django can raise a ObjectDoesNotExist, not a model.DoesNotExist exception.
You can check if subscription exist by using hasattr(user, 'subscription')
or try an access and catch the exception
from django.core.exceptions import ObjectDoesNotExist
def subscription_valid(user):
try:
superuser = user.is_superuser
user_valid = user.subscription.is_subscription_valid
return superuser or user_valid
except ObjectDoesNotExist:
return False