Luca Luca - 2 days ago 5
Python Question

Adding metadata for models and objects in django

I am writing a Django based app where I have a model that encapsulates various image types. I load them as fixtures as follows:

[
{
"model": "app.ImageTypeModel",
"pk": 1,
"fields": {
"type": "PNG",
"dims": 1
}
},

{
"model": "app.ImageTypeModel",
"pk": 2,
"fields": {
"type": "Custom",
"dims": 100
}
},

{
"model": "app.ImageTypeModel",
"pk": 3,
"fields": {
"type": "JPEG",
"dims": 1
}
},

{
"model": "app.ImageTypeModel",
"pk": 4,
"fields": {
"type": "BMP",
"dims": 1
}
}
]


The corresponding model declaration is as follows:

class ImageTypeModel(models.Model):
type = models.CharField(max_length=100)
dims = models.IntegerField()

class Meta:
db_table = "image_type"


Additionally, I have various instances of images as follows (I have removed some fields for simplification):

class ImageModel(models.Model):
type = models.ForeignKey(ImageTypeModel)

class Meta:
db_table = "images"


Now for each of these image types, I have different properties which I would like to specify. For example, for an image of type
Custom
, I could have various properties each of which could be a specific data type (like integers, string, floats, vectors of floats etc.). One way to define this would be to have a table for these data types and additional tables for each of the image types (let us call these tables configuration tables) where each row would be the property name and the associated data type. I can then try and generate an automatic form based on this.

However, I am not sure how to associate the image types and the associated configuration tables. So, in my original fixture example, is it advisable to just add the database table name as another field? Or should I create models for each of these configuration tables but I am not sure how to refer these models in my fixture code.

So, looking for advice on how to approach this kind of problem where one also has to specify this king of
metadata
for objects in the backend as well and how it can fit with django models and fixtures.

Answer

You can define common behaviour in an abstract base class, and in child classes put only the specifics that are different: Django supports abstract base classes for models.

class Image(models.Model):
    """ A graphic image. """

    name = models.CharacterField(max_length=1024)
    suffix = NotImplemented

    class Meta:
        abstract = True


class SVGImage(Image):
    """ A graphic image in Scalable Vector Graphics (SVG) format. """

    suffix = ".svg"
    version = models.CharacterField(max_length=20)


class JPEGImage(Image):
    """ A graphic image in Joint Picture Experts Group (JPEG) format. """

    suffix = ".jpeg"
    resolution = models.IntegerField()

Now the Image model won't be represented in the database, but all its defined functionality will be available to child classes. So an instance of SVGImage will have name, suffix, and version attributes; an instance of JPEGImage will have name, suffix, and resolution attributes.


As an aside: Your Django models will be in a module named models, so you should not add the superfluous …Model suffix to the class name.

Instead, fooapp.models.JPEGImage is plenty clear enough; it also means your database tables will be named correctly without you needing to specify.

Comments