Akira Kotsugai
Akira Kotsugai

Reputation: 1159

How to create abstract model in Django?

I am new to Django framework and in my project I have a model called Layer.

class Layer(models.Model):
    name = models.CharField(max_length=255)

I would like layer to have a relationship with an abstract model called "Geometry", more specifically, one layer should have one or no Geometry and one Geometry should be owned by one layer.

The problem is that I have for types of Geometries and they all have different properties, so I decided to create multiple geometries:

class Circle(models.Model):
    radius = models.CharField(max_length=255)

class Rectangle(models.Model):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

I would like to have a data structure where both models are of the same type (Geometry). I would like to call layer.geometry and be able to get either a circle or a rectangle, or a cross and so on. Is that possible? And how is the database shape going to be like? Is Django going to create two different tables or one table with merged properties?

Thanks in advance

Upvotes: 2

Views: 524

Answers (2)

ZephyRr Mahesh
ZephyRr Mahesh

Reputation: 77

Although you can link Cirle and Rectangle models with ForeignKey or OneToOneField, your have an option to create an AbstractModel for Geometry model.

class Geometry(models.Model):
    id = models.IntegerField()

    class Meta:
        abstract = True

class Circle(Geometry):
    radius = models.CharField(max_length=255)

class Rectangle(Geometry):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

As such, both Circle and Rectangle models will have id field from Geometry model, but will only have 2 tables in your database. However, you wont be able to query in Geometry model.

If you need to query explicitly for Geometry model, go for ForeignKey or OneToOneField option. If not, abstract model is a cleaner approach in my opinion.

From Django Docs: Often, you will just want to use the parent class to hold information that you don’t want to have to type out for each child model. This class isn’t going to ever be used in isolation, so Abstract base classes are what you’re after.

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476729

Django supports inheritance, although it is not very common. You can thus create a model Geometry, and let Circle and Rectangle inherit from that:

class Geometry(models.Model):
    pass

class Circle(Geometry):
    radius = models.CharField(max_length=255)

class Rectangle(Geometry):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

We can furthermore make a ForeignKey (or another relation) to this Geometry class with:

class Layer(models.Model):
    name = models.CharField(max_length=255)
    geometry = models.ForeignKey(Geometry, on_delete=models.CASCADE)

Django will make migrations that, for an SQL database create tables for Geometry, Circle and Rectangle. The Circle and Rectangle models will have an implicit OneToOneRelation to the table for the Geometry named geometry_ptr_id, that thus refers to the parent.

For more information, see the section on Multi-table inheritance in the documentation.

Upvotes: 4

Related Questions