Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do you have to set both id and pk to None to copy a Django model with inheritance?

The Django docs recommend copying a model instance thus:

original.pk = None
original.save()

But if you "use inheritance" -- apparently meaning if the model's class is a subclass of a subclass of models.Model -- you need to do it slightly differently.

Specifically, the doc says:

Due to how inheritance works, you have to set both pk and id to None:

and gives an example analogous to this:

original.pk = None
original.id = None
original.save()

This seems kludgey. In any case, I'd like to understand what's going on. Why does using inheritance require you to set the id field to None also? Don't all Django models inherit from models.Model in any case?

(NOTE: I'm omitting the bit from the doc about copying m2m fields, which incidentally seems even more kludgey.)

like image 399
Ghopper21 Avatar asked Aug 10 '12 14:08

Ghopper21


People also ask

Is PK and ID same in Django?

It doesn't matter. pk is more independent from the actual primary key field i.e. you don't need to care whether the primary key field is called id or object_id or whatever. It also provides more consistency if you have models with different primary key fields.

What is the use of PK in Django?

pk is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk".

What is primary key in Django model?

If you'd like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you've explicitly set Field.primary_key , it won't add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

Does Django create ID field?

By default, Django adds an id field to each model, which is used as the primary key for that model. You can create your own primary key field by adding the keyword arg primary_key=True to a field. If you add your own primary key field, the automatic one will not be added.


1 Answers

It's because MTI (Multiple Table Inheritance), the type you're talking about here, stores the object across multiple tables. Take this example:

class Animal(models.Model):
    ...

class Dog(Animal):
    ...

When you create a Dog, all the fields on Animal are saved into the table for Animal, and just the fields directly on Dog are saved to the table for Dog. When you lookup the Dog later, Django queries both tables and stitches them together.

Both tables, however need primary keys, and Django uses AutoFields for that, which are simply positive integer fields. So Dog has an id and Animal has an id. The pk is filled with the id for the Animal part because this is the main piece, and Dog's id doesn't matter. However, if you're going to make a copy, you need to copy both pieces. Otherwise, the Animal part will of the copy will not get it's own Dog part of the copy.

like image 65
Chris Pratt Avatar answered Oct 09 '22 10:10

Chris Pratt