Igor
Igor

Reputation: 35

Override save method in Django not working

My goal with the following code is to create an athlete object and override the save method to automatically set the category for a given athlete based on the born_date.

The Category class will be inherited in other models too. The list within the class serves as validation purposes for the save method and the tuples for choice fields (used in other models).

Although everything seems right, I ran some test in the shell and the code is saving whatever born_date is inputed. Why is that the case? Can someone shed some light on the problem? Thanks

  from django.db import models
  from datetime import datetime

  class Category:
       
       list_categories = [
           'u12',
           'u13',
           'u14',
           'u15',
           'u16',
           'u17',
           'u18',
           'u19',
           'u20',
           'u21',
           ]
   
       CATEGORIES = [
           ('U12', 'u12'),
           ('U13', 'u13'),
           ('U14', 'u14'),
           ('U15', 'u15'),
           ('U17', 'u17'),
           ('U19', 'u19'),
           ('U21', 'u21'),
       ]
   

   class Athlete(models.Model, Category):
   
       name = models.CharField(max_length=120)
       born_date = models.DateField()
       category = models.CharField(max_length=3)
   
       def save(self, *args, **kwargs):
           year_now = datetime.date.today().year
           year_born_obj = datetime.datetime.strptime(self.born_date, "%Y-%m-%d")
           self.category = 'u{}'.format(year_now - year_born_obj.year)
           if self.category in Category.list_categories:
               try: 
                   super(Athlete, self).save(*args, **kwargs)
               except ValueError:
                   print('Category does not exist. Check born date')
                   
                   
       def __str__(self):
           return self.name

Here is the shell output:

>>> a1 = Athlete.objects.create(name='Foo', born_date='1990-02-05')
>>> a1.save()
>>> a1.category
'u30'
>>> a1.category in Category.list_categories
False

Upvotes: 0

Views: 1833

Answers (2)

sayem
sayem

Reputation: 171

You can upgrade your source code based on the following way. I made some modifications to your code. Hope that will help you a lot.

from django.db import models
from datetime import datetime

class Athlete(models.Model):
    categories = [
        ("U12", "u12"),
        ("U13", "u13"),
        ("U14", "u14"),
        ("U15", "u15"),
        ("U16", "u16"),
        ("U17", "u17"),
        ("U18", "u18"),
        ("U19", "u19"),
        ("U20", "u20"),
        ("U21", "u21"),
    ]

    name = models.CharField(max_length=120)
    born_date = models.DateField(default=None, null=True)
    category = models.CharField(max_length=3, default=None, null=True)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        try:
            age = "u{age}".format(age=datetime.today().year - datetime.strptime(self.born_date, "%Y-%m-%d").year)
            category = "".join(ct[0] for ct in self.categories if age == ct[1])
            self.category = category if category != "" else None
        except Exception as exp:
            print("Exception: {exp}".format(exp=exp))
        return super(Athlete, self).save(*args, **kwargs)

Upvotes: 1

Baivaras
Baivaras

Reputation: 438

Do not assign category value to the object if you do not want to save it, I made some changes to your code.

Try to do like this:

category = 'u{}'.format(year_now - year_born_obj.year)
if category in Category.list_categories:
    self.category = category
else:
    print('Category does not exist. Check born date')
super().save(*args, **kwargs)

Please ask if you do not understand anything or it's not working:)

Upvotes: 0

Related Questions