Django DETAIL: Failing row contains (11, SG 553, BATTLE-SCARRED, CLASSIFIED, NORMAL, RIFLE, null, 6235.05)

Viewed 18

task to create Weapon objects:

def populate_weapon_objects(amount: int = 1) -> None:
    for _ in range(amount):
        Weapon.objects.create(
            name=_get_random_name(),
            exterior=_get_random_exterior(),
            quality=_get_random_quality(),
            category=_get_random_category(),
            price=_get_random_price(),
        )

Weapon model:

class Weapon(models.Model):
     ...
    
     name = models.CharField(max_length=64, choices=WEAPONS, db_index=True)
     exterior = models.CharField(max_length=64, choices=EXTERIOR, default=EXTERIOR_FACTORY_NEW, db_index=True)
     quality = models.CharField(max_length=64, choices=QUALITY, default=QUALITY_CONSUMER_GRADE, db_index=True)
     category = models.CharField(max_length=64, choices=CATEGORY, default=CATEGORY_NORMAL, db_index=True)
     type = models.CharField(max_length=64, editable=False, db_index=True)
     slug = models.SlugField(max_length=64, editable=False, unique=True, db_index=True)
     price = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(10**4)], db_index=True)
     updated_at = models.DateTimeField(auto_now=True)
     created_at = models.DateTimeField(auto_now_add=True)

     def save(self, *args, **kwargs):
        if not self.type:
            self.type = self._get_type_by_name()
        if not self.slug:
            self.slug = self._get_slug()
        return super().save(*args, **kwargs)

     def _get_type_by_name(self) -> str:
        return next(k for k, v in self.NAME_TO_TYPE_DICT.items() if self.name in v)
    
     def _get_slug(self) -> None:
        self.slug = generate_slug(self)

generate_slug function:

def generate_slug(weapon) -> str:
    name = weapon.name
    exterior = weapon.exterior
    quality = weapon.quality
    category = weapon.category
    sequence = [name, exterior, quality, category]
    slug = slugify(' '.join(sequence))
    return slug

This leads to:

django.db.utils.IntegrityError: null value in column "slug" of 
relation "weapons_weapon" violates not-null constraint
celery-worker  | DETAIL:  Failing row contains (14, PP-BIZON, 
MINIMAL WEAR, RESTRICTED, NORMAL, SMG, null, 7354.3, 
2022-09-15 13:15:43.75499+00, 2022-09-15 13:15:43.754978+00).

Why this happens? Why the type field is being filled when creating an Weapon objects and slug field keeps crashing (not being filled)? Please Help.

Doesn't the create() method call save() method of an object? I am clearly sure it does. But why then self.type gets a value and self.slug does not?

1 Answers

I found the solution. It was in _get_slug method

def _get_slug(self) -> None:
    self.slug = generate_slug(self)

It was returning NoneType + it was already trying to assign value to slug field. Why I say 'was trying' is because then in save method it was again assigning the return value of _get_slug method which is None:

if not self.slug:
    self.slug = self._get_slug() # returns None

I changed my code to:

def _get_slug(self) -> str:
    return generate_slug(self)

Now it works perfectly.

Related