Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-views

Django models.py I want a function go to a variable


I want the def remain and the result of it to go to the field d_remain but whatever I use the function it doesn't show anything, it shows only negative numbers, this is my code, this is the base code give me a way to make it happen thank you.

class sub(models.Model):
    id = models.UUIDField(default=uuid.uuid4, primary_key = True, editable = False)
    provider = models.CharField(max_length=70)
    tier = models.CharField(max_length=40)
    date_started = models.DateField(auto_now=False, auto_now_add=False)
    date_end = models.DateField(auto_now=False, auto_now_add=False, )
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=7, decimal_places=2, default=0)
    d_remain = models.IntegerField()#I want the value of def remain go to this filed 
    def remain(self):
        today = date.today()
        remaining_days = (self.date_end - today).days
        return(remaining_days)

    def get_absolute_url(self):
        return reverse('sub-detail', kwargs={'pk':self.id})

Solution

  • Don't store fully functional dependencies in a database. Indeed, if something fully depends on a (set of) column(s), it makes no sense to store it as an extra column. At best it will require extra storage, but very likely it also becomes a lot harder to keep the item in sync, since now for each update of the columns, you need to update the dependent column as well.

    In this specific case, each day you would have to update the number of remaining days. This would require running a daily query, that can fail as well, and if the date_end is modified, you should always update the d_remaining columns, which will of course easily result into data inconsistencies.

    You can define a property that will calculate the number of remaining days when necessary:

    from django.conf import settings
    
    
    class Sub(models.Model):
        id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
        provider = models.CharField(max_length=70)
        tier = models.CharField(max_length=40)
        date_started = models.DateField()
        date_end = models.DateField()
        author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        price = models.DecimalField(max_digits=7, decimal_places=2, default=0)
        # no d_remain
    
        @property
        def remain(self):
            return (self.date_end - date.today()).days
    
        def get_absolute_url(self):
            return reverse('sub-detail', kwargs={'pk': self.pk})

    and for the queries, we can query with:

    Sub.objects.filter(date_end__lte=date.today() - timedelta(days=5))

    to get the Subs that end within five days.


    Note: Models in Django are written in PascalCase, not snake_case, so you might want to rename the model from sub to Sub.


    Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.