zep
zep

Reputation: 13

calculate remaining days in python/Django

I'm creating a Django e-commerce site; This site "sells" digital items. On one of the templates, related to a "user profile", I'm trying to calculate the remaining days in a web app but so far have not been successful at doing it and displaying it on my template. I've tried to create a remaining_days function but unable so far to use it

Hereunder the code:

models.py

class UserSubscription(models.Model):
    user = models.ForeignKey(User, related_name= 'tosubscriptions', on_delete=models.CASCADE, null=True, blank=True)
    subscription = models.ForeignKey("Subscription", related_name = 'tosubscriptions',on_delete=models.CASCADE, null=True, blank=True) 
    # startdate of a subscription, auto_now_add needs to be "False" for acummulation of days in subscriptions
    start_date = models.DateTimeField(auto_now_add=False, null=True, blank=True,verbose_name="Start Date") 
    expiry_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True,verbose_name="Expiry Date") # expiry date of a subscription
    # "is_canceled" is used to calculate if a usersubscription is active
    is_canceled = models.BooleanField(default=False, verbose_name="Is Canceled")
    cancel_date = models.DateTimeField(auto_now=False, auto_now_add=False, blank=True, null=True)


    class Meta:
        verbose_name = "User Subscription"
        verbose_name_plural = "User Subscriptions"

    def __str__(self):
        """Unicode representation of UserSubscription"""

        return "PK: [{}] Subscription of: {}, {}, Expiring the: {}, is canceled: {}".format(
                str(self.pk),
                str(self.user),
                str(self.subscription),
                str(self.expiry_date),
                str(self.is_canceled )
            )
    
    def save(self, *args, **kwargs):  # calculated when object is saved and saved in the db
        """
        Function to calculate the expiry date of a user subscription. 
        The expiry_date is saved in the db
        """
        self.expiry_date = self.start_date + timedelta(self.subscription.duration)  # "timedelta" added to be able to calculate automaticaly end dates of subscriptions
        super().save()

    @property
    def is_active(self):
        """
        Function to calculate if a subscription is active 
        This calculation is not stocked in the db
        """
        if not self.is_canceled and datetime.datetime.today() < self.expiry_date:
            return True
        else:
            return False

    @property
    def remaining_days(self):
        remaining = self.expiry_date - self.datetime.datetime.today()
        return remaining

class Subscription(models.Model):
    plan_name = models.CharField(max_length=50, null=True, blank=True, verbose_name="Subscription Plan Name")    
    description = models.TextField(verbose_name="Subscription Plan Description")   
    price = models.FloatField(verbose_name="Subscription Plan Price")   
    start_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True, verbose_name="Subscription Plan Start Date")
    end_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True, verbose_name="Subscription Plan End Date")   
    is_active = models.BooleanField(default=True)
    duration = models.IntegerField(blank=True, null=True)    

    class Meta:
        verbose_name = "Subscription"
        verbose_name_plural = "Subscriptions"       

    def __str__(self):
        """Unicode representation of Subscription"""

        return " Subscription type: {}, Description: {}, Price: {}, Is active: {}".format(
                self.plan_name,
                self.description,
                self.price,
                self.is_active
            )

views.py

@login_required
def user_profile(request):
    """"""

    all_user_subscription = UserSubscription.objects.filter(user=request.user)
    last_user_subscription = all_user_subscription.last()

    context = {
        "all_user_subscription": all_user_subscription,
        "last_user_subscription": last_user_subscription,
    }

    return render(request, "myprofile.html",context)

template

<p>My Current Plan: {{last_user_subscription.subscription.plan_name}}</p>
<p>End Date: {{last_user_subscription.expiry_date}}</p>
<p>remaining days {{last_user_subscription.remaining}}</p>
<a href="{% url 'home' %}">Renew my Subscription</a>
<hr>
<p>My Bills:</p>
{%for i in all_user_subscription%}
<p>Bill : {{ i.subscription.price }} €</p>
<p>Bought on the : {{ i.start_date }} </p>
{% endfor %}
<hr>

result:

My Current Plan: 1 Month

End Date: April 12, 2021, 11:22 p.m.

remaining days

Renew my Subscription

My Bills:

Bill : 5.0 €

Bought on : March 13, 2021, 10:22 p.m. 

Upvotes: 0

Views: 1958

Answers (2)

koko
koko

Reputation: 397

I do not understand exactly what question is. But your 'def remaining_days':

  1. self.datetime.datetime.today() change to datetime.datetime.today()
  2. When you subtract datetimes objects you get timedelta object

I suppose it can help you:

@property
def remaining_days(self):
        remaining = (self.expiry_date - datetime.datetime.today()).days
        return remaining

UPDATED: I tried to write data with your models except save() method (I do not like it, I just removed it), and this (I placed it before Meta)

    @property
    def remaining_days(self):
        remaining = (datetime.datetime.now().date() - self.expiry_date.date()).days
        return remaining

and got this(I crated random dates, expary_date = 2020-10-14)

>>> u=UserSubscription.objects.all().first()
>>> u.remaining_days
151

I think It's that you want

Upvotes: 4

Neeraj
Neeraj

Reputation: 997

Try running the code with debugger in ide and add breakpoints before return statements. I agree with koko here, either change the DateTimeFields in models to DateField( I recommend this since I don't see time being used anywhere ) or convert the datetime to date and then do the calculations.

Upvotes: 0

Related Questions