Assume I have in models.py
something like:
Class ModelA(models.Model):
# many fields, including
relatives = models.ManyToManyField(Person)
)
# also, A is foreign key to other models:
Class SomeOtherModel(models.Model):
mya = models.ForeignKey(A)
# now we produce two classes with multi-table inheritance
# WITHOUT any additional fileds
Class InhertA1(ModelA):
pass
Class InhertA2(ModelA):
pass
So as as I understand, this will create Tables for ModelA
, InheritA1
and InheritA1
; each instance of ModelA
will get a row in the ModelA
-table only, each instance of InheritA1
will have a row both in the ModelA
-table (basically containing all the data) and another in the InheritA1
-table (only containing a PK and a OneToOne key pointing to the ModelA
-table row), etc. Django queries for ModelA
-objects will give all objects, queries for InheritA1
-objects only the InheritA1
ones etc.
So now I have an InheritA1
-object a1
, and want to make it into a InheritA2
-object, without changing the according ModelA
-object. So previously the parent-IbeToOne Key of a1
points to the ModelA
-row with key 3, say (and the ForeignKey
of some SomeOtherModel
-object is set to 3). In the end, I want a InheritA1
-object a2
pointing to the same, unchanged ModelA
-row (and the object a1
removed).
It seems that django doesn't offer any such move-Class-functionality?
Can I safely implement the according SQL operations myself?
Or will things go horribly wrong? I.e., can I just execute the SQL commands that
- Create a new row in the
InheritA2
-table, setting the parent-OneToOne key to the one ofa1
, - Remove the
a1
row in theInheritA2
-table?
It seems I cannot do this from non-SQL-django without automatically creating a ModelA
-row. Well, for 1., maybe I can create a temporary object x
that way, then let p
be the parent of x
, then change the parent-OneToOne key of x
to point to the one of a1
, then delete the obect p
? But for 2, I do not think that it is possible in non-SQL-django to remove an instance of a child while keeping the parent object?
Alternatively, is there a good django way to copy instances in django and change references to them?
I.e., I could create a new InheritA2
object y
, and copy all the properties of a1
into the new object, and then go through the database and find all ManyToMany and ForeignKey entries that point to the parent of a1
and change it to point to the parent of y
instead, and then delete a1
.
That could be done with non-SQL-django, the downside is that it seems wasteful performance-wise (which would be of no great concern for my project), and that it might also not be so "stable" I.e., if I change ModelA
or other models in relation to it, the code that copies everything might break? (Or is there a good way to do something like
Forall models M in my project:
Forall keys k used in M:
If k is a descendant of a ManyToMany or Foreign or ... key:
If k points to ModelA:
Forall instances x of M:
If x.k=a1:
x.k=y
The first four lines seem rather dubious.
Remarks:
- Copying without changing the instance can be done in a stable, simple, standard way, see e.g. here, but we are still stuck in the same child class (and still have to modify ForeignKeys etc)?
- Changing the class by just declaring it in the standard python way, see here, is not an option for me, as nobody seems to know whether it will horribly break django.