Skip to content

A robust framework for dynamically extending Django models at runtime

License

Notifications You must be signed in to change notification settings

hnarayanan/django-extensible-models

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Django Extensible Models

What is it?

Django Extensible Models is a robust framework for dynamically extending Django models at runtime. It uses JSONFields for flexible data storage, with JSONSchema validation ensuring data integrity. It seamlessly integrates with Django’s ORM while enabling multi-tenant schema variations.

Why is it?

Django offers a really robust model system that functions as a great interface to store and retrieve data related to your app. Models in Django are backed by tables in a relational database. While this is really good for correctness, it is quite rigid in terms of the shape of data that is stored. Sometimes, you run into use-cases that demand a bit more dynamism during the running of your Django app.

Let’s take a concrete example. You have an existing Django SaaS app that’s launched to many happy customers. They are happy, but each customer feels that if they could store just a little bit more custom data as part of their usage of your app, their workflows would be much smoother. So they ask you to add what they want. The trouble is, each customer is interested in augmenting their data in different ways. You diligently add the first customer’s fields. And then another’s. And then even more. And before you know it, things get really messy.

Solving this problem is the point of this project. Instead of individually catering to each of their requests, Django Extensible Models offers you a general extension mechanism that allows your models to grow with your customers’ needs.

Features

It’s easy to incrementally add this to your app

With a relatively small change to your existing model code (see Installation and Usage), you now have a Django model that retains all its Django goodness, and can be extended on the fly with additional fields at runtime.

Formal schema for extended fields

We don’t just stuff the extra data for these additional fields into a JSONField and call it a day,[fn::What sort of operation do you think this is?] we allow you to define a proper schema for this data (using JSON Schema).

Different extended schema for different groups of objects

It wouldn’t make much sense to apply the same extension schema to all objects of your model,[fn::You could just update the Python model code of your app instead!] so Django Extensible Models allows you to define different extended fields for different sets of objects.

We also allow you to extended individual objects in unique ways if that is what you need.

Strong validation of data for these extended fields

With a good schema defined, it is easy to validate that incoming data for your extended fields match your expectations before storing it in the database.

Ability to query these fields using an ORM-friendly syntax

The data for your extended fields is not simply stored in a messy, impenetrable blob. It is stored in a structured JSONField that can be queried in a systematic way using standard Django syntax.

Dynamically generated forms for these extended fields in the Django Admin interface

Dynamic extensions for these fields in Django Model Forms (and Crispy Forms)

Dynamic extensions for these fields in for Django Rest Framework

Dynamic extensions for these fields in Django (Rest Framework) Filters

Migrations between versions of your extended schema!

Taken together, you should be able to use your extended fields much like how you use your native Django model fields. And this is just cool.

Installation

pip install django-extensible-models
# settings.py
INSTALLED_APPS = [
    # ...
    "extensible_models",
    # ...
]

EXTENSIBLE_MODELS_TENANT_MODEL = "your_app.YourTenantModel"
EXTENSIBLE_MODELS_TENANT_FIELD = "your_tenant_field_name"

Usage

# models.py
from django.db import models
from extensible_models.models import ExtensibleModelMixin


class ExampleModel(ExtensibleModelMixin, models.Model):

    ...
# admin.py
from django.contrib import admin

from extensible_models.admin import ExtensibleModelAdminMixin


class ExampleModelAdmin(ExtensibleModelAdminMixin, admin.ModelAdmin):

    # Leave all your existing configuration as is!

Copyright and License

Copyright (c) 2022-2024 Harish Narayanan

This code is licenced under the MIT Licence. See LICENSE for the full text of this licence.

About

A robust framework for dynamically extending Django models at runtime

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages