[Django]Composite Primary Key

0. Do Django models support composite primary key?

https://docs.djangoproject.com/en/3.1/faq/models/#do-django-models-support-multiple-column-primary-keys

https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys

Django doesn’t officially support composite primary key.

If there is no field for which “primary_key = True” is specified, “id” will be automatically added as the primary key. So if you are using the DB of the legacy system, “update” and “delete” method do not work. You have to add “id” field to your tables or to make your own SQL query.

1. Solutions

Proposal 1:Add a surrogate key

If I add a surrogate key (‘id’) to the DB and put a unique constraint (unique_together) on the composite key, I can use the Django model as it is.

(Problems) DB rebuild takes time and requires planned outage.

Proposal 2:Implement with your own query

Make my own query-write implementation without relying on ORM. I can control the performance of queries by myself.

(Problems) More code and test.

Proposal 3:Extend Django Model

It seems that it was also considered in the Django project, but I’m not sure recent status.

https://code.djangoproject.com/ticket/373

https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys#CurrentStatus

It seems that some people have tried various ways, but in the end, are they all unfinished?

For the time being, by extending the model myself, create a subclass of Model so that I can use it for my own work. It’s not necessary to cover all the features of Django, so it seems possible to cover the INSERT, UPDATE, and DELETE of the standalone mode I need.

(Problems) Understand the code of the current model.

Proposal 4:Make another ORM

When I read the code around the model, I felt a bit spaghetti smell. Looking at the implementation, I felt that the roles in Model, Manager, and QuerySet weren’t clearly separated. I think it’s another option to make my own simple ORM, including support for composite primary key.

(Problems) I don’t have enough time!

Proposal 5:Use another existing ORM

Is the below not supporting the primary key, only for the composite foreign key?

https://github.com/Arisophy/django-composite-foreignkey

(Problems) I haven’t found the right one yet!

2. Conclusion

My current project is gradually migrating a legacy system built with Ruby On Rails to Django. So I don’t want to touch the DB.

In conclusion, I decided to proceed with Proposal 2 and 3.

INSERT,UPDATE,DELETE will be supported by the extension class of Model in Proposal 3. When I actually made it, it worked nicely with a small amount of code. I will proceed with the project while using the extended model.

For SELECT, I can’t rely entirely on the ORM, so I’ll also use my own query.

I will post how I created the extension class at a later.

(2021/01/29)
The extension classes are published below.

https://github.com/Arisophy/django-compositepk-model

(2021/03/16)

My opinion about ticket#373 is below.