Sunday, May 29, 2016

Re: Model inheritance with constraints


What I have
=========

class MyFunModel(models.Model):
    my_foo_field = <blah>

What I am attempting to add
=====================

class MyAnotherFunModel(MyFunModel):
    my_another_foo_field = <blah>

Such that the migration gives me *only* <app>_myanotherfunmodel table with fields "my_foo_field" and "my_another_foo_field", *without* touching any data in the <app>_myfunmodel table. 

None of the options in https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance seem to address this case, or maybe I am missing something?

If I understand your requirements, then yes, you are missing something. I believe you are being affected by a consequence of multi-table inheritance in Django:


The first paragraph talks about an 'automatic' OneToOne relationship between the parent and child tables being created (which is annoying IMO). This is likely what you are seeing in your migrations. I don't think that MyFunModel is being directly affected (at least in the DB), but you are likely seeing an extra table being built for this new relationship with MyAnotherFunModel.

To get around this, you would need to redefine your common fields into an abstract model, and then your two concrete models would inherit from your new abstract model:


class FunAbstractModel(models.Model):
    my_foo_field = <blah>
    
    class Meta:
        abstract = True

class MyFunModel(FunAbstractModel):
    pass

class MyAnotherFunModel(FunAbstractModel):
    my_another_foo_field = <blah>

Both of your concrete models (MyFunModel and MyAnotherFunModel) will contain a 'my_foo_field' field, but MyAnotherFunModel will also contain 'my_another_foo_field'. There will also be no automatic relationship built between the two models since they no longer inherit from each other (both inherit from FunAbstractModel, which is abstract so it doesn't directly affect your database). 

You should be able to make this change transparently and get the results you want if you replicate all of the appropriate fields in FunAbstractModel that are currently used by MyFunModel.

I personally never use MTI and always use abstract models to handle these cases. If I need a OneToOne, I enter it manually in the code so that I don't have to remember it is there down the road, since I usually only look at the model definition and not check through the inheritance tree for magic relationships. I haven't personally found a use-case where I was fine with an implicit relationship rather than an explicit one.

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciWLzbnzbGYCUBjYhNncr1kg7%3DomRztxdQ61bxkyGqQCFQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment