views:

120

answers:

1

Here's what I'm trying to do, and failing...

I have a File model which has a generic-relation to other objects:

class File(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()
    file = models.FileField(upload_to='files/%Y/%m/%d')
    # etc....

I also want to have a sub-class of File to deal with the specific case of images to be displayed in-page, rather than downloaded:

class Image(File):
    file = models.ImageField(upload_to='files/%Y/%m/%d')

All of the above works fine, including generic inlines of the File model, until I want to use a generic-inline of the Image model --- the save process fails to create the base class instance and so raises an error stating that the Image.file_ptr (the 'secret' foreign key to the base class) cannot be None.

So, basically, generic inlines do not properly support multi-table inheritance at the moment.

It's quite likely that I'm making this more complicated than it need be, so can anyone suggest either a fix for this problem, or a better way of achieving the same end?

Please let me know if you need further clarification.

A: 

Inheritance can be implemented two ways in a relational model.

A subclass can be a new table with all the same columns as the superclass repeated. This works well when you have an abstract superclass or subclass features that override the superclass.

A subclass can be just the unique columns with a join to the superclass table. This works well when you have a concrete superclass.

In your case, it looks you might have the following.

class FileFacts( models.Model ):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

class DownloadFile( models.Model ):
    facts = models.ForeignKey( FileFacts )
    file = models.FileField(upload_to='files/%Y/%m/%d')

class InlineImage( models.Model ):
    facts = models.ForeignKey( FileFacts )
    file = models.ImageField(upload_to='files/%Y/%m/%d')

This is my preference for handling a subclass-like model.

S.Lott