M
M
Maxim Zubenko2019-06-16 23:13:34
Django
Maxim Zubenko, 2019-06-16 23:13:34

How in Django to keep the fields of only the child model, and not affect the fields of the parent model?

I have an application "profile" and two models: "Human" and "Client".
The "Human" model extends the built-in "User" model.
And the "Client" model extends the "Human" model.

from django.contrib.auth.models import User

class Human(User):
    city = models.CharField(max_length=100, blank=True)
    address = models.CharField(max_length=150, blank=True)
    phone = models.CharField(max_length=30, blank=True)

    def __str__(self):
        return "{0} ({1})".format(self.username, self.get_full_name())

class Client(Human):
    company = models.CharField(max_length=100, blank=True)
    discount = models.DecimalField(max_digits=4, decimal_places=2, default=15)
    
    def __str__(self):
        return "#{} : {} | {} ({})".format(self.id, self.username, self.get_full_name(), self.company)

Through the Django shell, I am adding a new entry to the database. I use the Human child class for this:
from profile.models import Human
hu = Human(username='first', email='[email protected]', first_name='Mr.First', city='First City', phone="+9876543210")
hu.set_password('12345678')
hu.save()

In the database, I see that there are entries in the auth_user and profile_human tables. Let's say they were assigned id = 3. (in auth_user it is displayed as id, and in profile_human as user_ptr_id)
Suppose my user has become my client. And now I need to add additional data to the Client model (to the profile_client table).
This is not a new user! I already have this user. Information about it is in two tables (auth_user and profile_human). But there are no records about this user in the profile_client table yet.
Through the Django shell, I create a new instance of the Client model:
from profile.models import Client
cli = Client(id=3, company='FST', discount=10.00)

Because this is an existing user, then I specify id=3
If I try to do this
cli.update()
, I get an error, because there is no such entry in the profile_client table yet and therefore I see an error that the Client object does not have an update attribute.
If I try to save only the specified fields: Then I get an error again, because there is no such entry in the profile_client table yet, and therefore a hint comes up, they say, try to save without the update_fields attribute. But if I save simply through: table, it is called human_ptr_id), but in other tables, information from all fields is set to zero (becomes empty).
cli.save(update_fields=['company', 'discount'])
cli.save()
Those. now in the auth_user and profile_human tables, all information from the user with id = 3 has been erased. Completely.
Q : When adding a new record of a child model, how can I keep the fields of only that child model without affecting the fields of the parent models?
ps There, of course, there are many more fields, but for understanding the code of the models is simplified.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Maxim Zubenko, 2019-06-17
@JawsIk

What I love about Django is that it's very convenient. It turns out the solution was very simple. It is a pity that I could not find it in the official documentation (in my opinion the documentation is poorly done).
To put it simply, the solution would be:

from profile.models import Client
cli = Client(company = 'FST', discount=10.00, human_ptr_id=3)
cli.save_base(raw = True)

those. The last line does exactly what is described in the question. And instead of id we write parent_ptr_id . So tnank you. The question is closed.

F
FulTupFul, 2019-06-17
@FulTupFul

1. Inheriting from This is VERY bad practice. Don't do it. The User model is not an abstract model. 2. You have three different models, hence three different tables. There is no connection between them. 3. The correct solution would be to override the User model. Here is a tutorial for this https://simpleisbetterthancomplex.com/tutorial/201... The fourth option will work for you. Then you can get rid of Human. And connect the Client model with the User via ForeignKeyfrom django.contrib.auth.models import User

class CustomUser(AbstractBaseUser, PermissionsMixin):
    # some fields
    # some methods

class Client(models.Model):
    user = models.ForeignKey("CustomUser", on_delete=models.CASCADE)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question