Django Polymorphic behaviour (Custom ForeignKey) without using GenericForeignKey

I’m working with a legacy DB (Postgresql) that has fields like edited_by_type, and edited_by_id in many tables. This is basically a polymorphic relation for RubyOnRails persons. This represents a FK relation to multiple models using combinations of these two fields.

for example, the value of edited_by_type can be either user, admin, or client. These are 3 different tables. so now you can guess that it’s basically a unique constraint of edited_by_type, and edited_by_id together, where edited_by_type is used to determine the type of person (table) and then query that table using edited_by_id.

I have a fairly good understanding of Django’s GenericFK field that uses the contentType table internally. but since this is a legacy DB and I don’t want to use the ContentType table at all it requires creating migrations and entries in the contenttype table. What I’m looking for is a customFk or (even customGenericFK) solution that somehow manages this and allows us to query the db as easily as we can.

e.g something like the below (open to any other approach that doesn’t involve creating a CustomFK). here is what I’ve tried so far.

class CustomFK(models.ForeignKey):
    def __init__(self, fk_models, on_delete, **kwargs):
        for model in fk_models:
            super().__init__(to=model, on_delete=on_delete, **kwargs)

    # override update and filter functionality here but not sure exactly what methods 
    # need to be overridden. may be __call__ or __new__ method? 

edited_by = CustomFK([User, Admin, Client], on_delete=, related_name=, ...)

# while querying
MyModel.objects.filter(edited_by=user/client/admin object, ...)
# internally this will use above two fields to get the correct record. Similarly we can do for update.
mymodel_obj.edited_by = user/client/admin object
mymodel_obj.save()  # this internally updates above two fields

I tried to go in the below direction as well but this wont work directly as the FKs are part of CustomFK class not model class. we may need custom model manager as well.

class CustomFK():
    def __init__(self, fmodels, on_delete, **kwargs):
        for model in fmodels:
            models.ForeignKey(model, on_delete, **kwargs)

I went through couple of sources to find a direction but no luck yet. Some of them are –

https://www.better-simple.com/django/2023/10/03/registerfields-in-django/

How to use django models with foreign keys in different DBs?

Again I want to emphasize that I really dont want to use GenericFK. So if you have any other pointers I would really appreciate.

Leave a Comment