Many to Many relation with Model inheritance in Django

django model inheritance
django model relationships
django model fields
multi-table inheritance django
django models tutorial
django model save
django model get field value
django model create

I have an abstract object called parameter. parameter can be of several different types. For example - Numeric Parameter, Constant parameter, MultiValue parameter etc. Each parameter can be related to many parameter of different types and vise versa.

After reviewing Django's doc on Model inheritance I decided what I need is a simple abstract base class. An example of a many to many relation from the base class can be found later on in the docs.

class ParameterBase(models.Model):
    id = models.AutoField(primary_key=True)    
    description = models.CharField(max_length=200)
    sort_order = models.DecimalField(null=False, max_digits=6, decimal_places=4)

    m2m = models.ManyToManyField('self',related_name='dependent_on')

    class Meta:
        abstract = True

class ParameterConstant(ParameterBase):
    value = models.DecimalField(null=False, blank=False, max_digits=20 , decimal_places=4)

class ParameterNumeric(ParameterBase):
    minimum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)    
    maximum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)

So after syncing i could see that django created 4 tables -

CREATE TABLE "calc_parameterconstant_m2m" (
    "id" serial NOT NULL PRIMARY KEY,
    "from_parameterconstant_id" integer NOT NULL,
    "to_parameterconstant_id" integer NOT NULL,
    UNIQUE ("from_parameterconstant_id", "to_parameterconstant_id")
)
;
CREATE TABLE "calc_parameterconstant" (
    "id" serial NOT NULL PRIMARY KEY,
    "description" varchar(200) NOT NULL,
    "sort_order" numeric(6, 4) NOT NULL,
    "value" numeric(20, 4) NOT NULL
)
;
ALTER TABLE "calc_parameterconstant_m2m" ADD CONSTRAINT "from_parameterconstant_id_refs_id_f893bb67" FOREIGN KEY ("from_parameterconstant_id") REFERENCES "calc_parameterconstant" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "calc_parameterconstant_m2m" ADD CONSTRAINT "to_parameterconstant_id_refs_id_f893bb67" FOREIGN KEY ("to_parameterconstant_id") REFERENCES "calc_parameterconstant" ("id") DEFERRABLE INITIALLY DEFERRED;

CREATE TABLE "calc_parameternumeric_m2m" (
    "id" serial NOT NULL PRIMARY KEY,
    "from_parameternumeric_id" integer NOT NULL,
    "to_parameternumeric_id" integer NOT NULL,
    UNIQUE ("from_parameternumeric_id", "to_parameternumeric_id")
)
;
CREATE TABLE "calc_parameternumeric" (
    "id" serial NOT NULL PRIMARY KEY,
    "description" varchar(200) NOT NULL,
    "sort_order" numeric(6, 4) NOT NULL,
    "minimum" numeric(20, 4),
    "maximum" numeric(20, 4)
)

Now, This is obviously was not my intention - I want to be able to connect a parameter of each type to parameters of other types as well. Is there any way to achieve this goal using Django ORM and model inheritance ?

If the base parameter model was a table on it's own with Many to Many relation to it self and the sub tables were connected with an unbinding one to one relation this might be a good solution here database wise.


I think multi-table inheritance will solve your problem. To use it, just remove abstract = True from the ParameterBase.Meta subclass (or remove that subclass completely).

When using multi-table inheritance, to access attributes of a particular subclass, Django has to know that you're dealing with that subclass.

For example, this will fail:

p = ParameterBase.objects.get(...)  # get a ParameterBase that is a ParameterConstant
print p.value

Instead, you would have to do this:

p = ParameterConstant.objects.get(...)
print p.value

Or this:

p = ParameterBase.objects.get(...)  # get a ParameterBase that is a ParameterConstant
print p.paramaterconstant.value

Models | Django documentation, use inheritance, which involves an implicit one-to-one relation). As with ForeignKey , a recursive relationship can be  I'm looking to use Django's Generic models in a ManyToMany style relationship where one model inherits from a base class, and the other model doesn't inherit can have multiple references to many of


One way to solve this would be to replace

m2m = models.ManyToManyField('self',related_name='dependent_on')

with

m2m = models.ManyToManyField('ParameterBase', related_name='dependent_on')

but Django won't let you create an m2m field that points to a model that hasn't been installed yet or one that is abstract. At this point ParameterBase is both of those.

I'd do it like this

class Parameter(models.Model):
    id = models.AutoField(primary_key=True)    
    description = models.CharField(max_length=200)
    sort_order = models.DecimalField(null=False, max_digits=6, decimal_places=4)

class ParameterType(models.Model):
    parameter = models.ForeignKey(Parameter)
    related_parameters = models.ManyToManyField(Parameter,related_name='dependent_on')

    class Meta:
        abstract = True

class ParameterConstant(ParameterType):
    value = models.DecimalField(null=False, blank=False, max_digits=20 , decimal_places=4)

class ParameterNumeric(ParameterType):
    minimum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)    
    maximum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)

#12002 (Models inherited from multiple Models) – Django, In case Model is created as inherited from multiple non-abstract Models there is a Restaurant) objects related via many-to-many relationship are deleted twice  To define a many-to-many relationship, use ManyToManyField. In this example, an Article can be published in multiple Publication objects, and a Publication has multiple Article objects: from django.db import models class Publication ( models .


If you use a ManyToMany field in an abstract parent class, you should provide a unique related_name as stated in the docs... in your case, this should go fine:

m2m = models.ManyToManyField('self',related_name='%(app_label)s_%(class)s_m2m')

Modeling Polymorphism in Django With Python – Real Python, Polymorphism is the ability of an object to take on many forms. Common E300) Field defines a relation with model 'Product', which is either not installed, or is abstract. Django offers another way to implement inheritance in models. Instead  Inheritance among models can be done in two ways: a common abstract class (see the "Model mixins" example) a common model with multiple tables; The multi tables inheritance will create one table for the common fields and one per child model example:


Relationships in Django models, How to declare Django model relationships one to many, many to many and one a one to one relationship in RDBMS is similar to object-oriented inheritance  Many to many relationships in Django models. A many to many relationship implies that many records can have many other records associated amongst one another. For example, Store model records can have many Amenity records, just as Amenity records can belong to many Store records. To define a many to many relationship in Django models you use the ManyToManyField data type. Listing 7-23 illustrates a sample of a many to many Django relationship.


Django 2 Multi Table Model Inheritance In Django #31, A many-to-many relationship refers to a relationship between tables in a database when a parent row in one table contains several child rows in the second table,  It’s sort of a hybrid of the two approaches here — there’s no inheritance taking place, but Django is taking care of creating the matching OneToOneField if it’s not present. Also, thornomad does make a good point about the redundancy in your models.


3. How to model many to many relationships?, For example:: from django.db import models class Person(models. For sample code, see the `Many-to-one relationship model tests`_. typically use :ref:`​inheritance <model-inheritance>`, which involves an implicit one-to-one relation). To define a many-to-one relationship, use django.db.models.ForeignKey. You use it just like any other Field type: by including it as a class attribute of your model. ForeignKey requires a positional argument: the class to which the model is related.