0

Having two models, parent and child, I want to set the value of one of the attributes the child inherits.

For example, in the following code the color attribute would be set when creating a RedCat object.

# Parent class
class Cat(models.Model):
    name = models.CharField(max_length=10)
    color = models.CharField(max_length=10)

    class Meta:
        abstract = True

# Child class
class RedCat(Cat):
    color = 'red' # <-- Doesn't work!

I'm considering either overriding the parent attribute or having the attribute only on the children, but I wonder, is there a right/better way to set a default value in a Django model for an inherited attribute?

3 Answers 3

2

You can link using ForeignKey and then override the parent field value in child.

models.py

# Parent class
class Cat(models.Model):
    name = models.CharField(max_length=10)
    color = models.CharField(max_length=10)

# Child class
class RedCat(Cat):
    color_type = models.ForeignKey(Cat, on_delete=models.CASCADE)

    def save(self, *args, **kwargs):
       self.color_type.color = "Red"
       self.color_type.save()
       super(RedCat, self).save(*args, **kwargs)
Sign up to request clarification or add additional context in comments.

2 Comments

@Berbus, Let me know if this helped.
I was testing a few things. So, your answer and Ameya's commit made me realise what is actually happening here. First, I missed that the parent class has to be abstract, so a table won't be created for it and generating a foreign key is not possible. Then, I was playing around with the save method when I realised that the "default value" for the attribute was being set, it just doesn't show when I navigate the tables in the /admin interface but it's accessible everywhere else. I'll update the question to explain it better. Thank you for your answer! ;)
1

First, the description of being a child of a parent in django, I think it is not by subclassing the parent class.

Instead, Considering if RedCat is a child of Cat, you should create a new model that has a ForeignKey field that aims to the Cat module.

I think what you mean is to set default values for a field, which can be done by using the default attr on the field.

Models.py

class Cat(models.Model):
    ...

class RedCat(models.Model):
    cat = models.ForeignKey(Cat, on_delete=models.CASCADE)
    color = models.CharField(
        max_length=10,
        default='red',
        )

Comments

0

When I first made the question I was confused because I couldn't see the value for the attribute being set in the subclass in the /admin interface, but the code actually works.

The parent class is an abstract class that contains the definition of the attribute.

The child class inherits this attribute correctly and sets its value.

When navigating the admin panel for this model, the value of the attribute will not show, as it is established by default and will never change, but this attribute is still correctly set and accessible from everywhere else.

See Django docs on abstract model classes

1 Comment

In case anyone stumbles in here, get_change_form_initial_data would allow you to see the value on a create in the admin but only applies in the admin, not when you save elsewhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.