views:

39

answers:

1

Hello,
I have the following multi-table inheritance situation:

from django.db import Models

class Partner(models.Model):
    # this model contains common data for companies and persons
    code = models.CharField()
    name = models.CharField()

class Person(Partner):
    # some person-specific data
    ssn = models.CharField()

class Company(Partner):
    # some company-specific data
    tax_no = models.CharField()

How can I convert a Company instance to a Person one, and vice-versa?
Let's say someone mistakenly created a Company instance with person's details:

company = Company(name="John Smith", tax_no="<some-ssn-#>")

I want to convert all wrong Company objects (that were meant to be Persons) to Person objects, keeping all related records (I have models with FKs to the Partner model, so it's important to keep the same partner_ptr value). I can do something like this:

person = Person(name=company.name, ssn=company.tax_no, partner_ptr=company.partner_ptr)

So far so good, but is it possible to delete the Company objects that are not needed anymore? Deleting the Company object will also delete it's parent Partner object (and any related to the partner, including the newly created Person object).

Any recommendations? Thanks!

P.S.: This is an already deployed system, with lots of data in it and it is not possible to redesign the whole Partner-Person-Company inheritance concept.

+4  A: 

One way to go about this would be to first add a dummy Partner per each company awaiting deletion. After that you can update the partner_ptr of all unwanted Company instances to the appropriate dummy partner instance. Finally you can delete all the companies.

Of course you can use South to help do this.

Update

Did some rudimentary testing and this works. I am using Django 1.2.1.

I have tried this, it's not possible: In 1: Company.objects.get(pk=7924) Out1: In [2]: c.partner_ptr = Partner() In [3]: c.pk In [4]: c.delete() AssertionError: Company object can't be deleted because its partner_ptr_id attribute is set to None. Setting the partner_ptr instance to a dummy one changes the company's PK and it's not the Company.

You have to attach a new Partner and then save the company. Then you can safely delete it.

So:

company = Company.objects.get(pk=7924)
dummy_partner = Partner(code = "dummy", name = "dummy")
company.partner_ptr = dummy_partner
company.save()
company.delete()
Manoj Govindan
I have tried this, it's not possible:In [1]: Company.objects.get(pk=7924)Out[1]: <Company: John Smith>In [2]: c.partner_ptr = Partner()In [3]: c.pkIn [4]: c.delete()AssertionError: Company object can't be deleted because its partner_ptr_id attribute is set to None.Setting the partner_ptr instance to a dummy one changes the company's PK and it's not the Company.
Alexander
@Alexander: see my updated answer. You have to _save_ the company before deleting it.
Manoj Govindan
Thank you, Manoj, indeed after saving the company it worked. According to the SQL log, it deletes only the from the Company table: 2010-09-14 20:43:49 EEST LOG: statement: DELETE FROM "partners_company" WHERE "partner_ptr_id" IN (7924)2010-09-14 20:43:49 EEST LOG: statement: DELETE FROM "partners_partner" WHERE "id" IN (NULL)
Alexander