Skip to main content

Solve the Downcasting-Problem of Django Models

In Django, I cannot downcast (attributes are missing). Any trivial solution breaks the Open-Closed Principle. This Solution not:
from django.db import models


class ParentModel(models.Model):

type = models.CharField(max_length=255, default='item')

class Meta:
abstract = True

def save(self, *args, **kwargs):
self.type = self.type_str
super().save(*args, **kwargs)

@staticmethod
def register_subtype(clazz):
the_type = clazz.type_str
if not hasattr(ParentModel, 'subclasses'):
ParentModel.subclasses = {}
ParentModel.subclasses[the_type] = clazz

def downcast(self):
if self.type not in ParentModel.subclasses:
return self
return ParentModel.subclasses[self.type].objects.get(pk=self.pk)

With the example Item:
class Item(ParentModel):
"""Stuff you can purchase"""
type_str = 'item'

name = models.CharField(max_length=255)
...
and it's subclass:
class Recipe(Item):
type_str = 'recipe'
duration = models.IntegerField(null=True)
...
I register the subclass, which is the key point to conform with the OCP:
from django.conf import settings
from django.apps import AppConfig


class RecipesConfig(AppConfig):
name = 'recipes'

def ready(self):
from .models import Recipe
from core.models import Item
Item.register_subtype(Recipe)
Now, I can downcast an item, if it is a subclass:
def test_downcasting_with_subtype(self):
Item.register_subtype(Recipe)
Recipe.objects.create(name="recipe_name", duration=20)
item = Item.objects.all()[0].downcast()
self.assertIsInstance(item, Recipe)
self.assertEqual(20, item.duration) # subtype specific data loaded

Comments

Popular posts from this blog

Futureproof Software

From here:  https://dzone.com/articles/the-secrets-of-futureproof-software Self-healing Self-patching, or more broadly, self-updating Backward compatibility Dynamic adaptation/ability to evolve over time Intent-based Made up of reusable futureproof components

Choose Projects you do NOT do!

Inspiration from FluentC++ Choose which project NOT to work on. Be clear what you want and which projects are toxic. Keep the Hedgehog-concept in mind. Be sure that you are a) deeply passionate about the project b) the project can be the best in the world quality c) you can earn money with it If one of the three points is not met and not realistic soon don't do the project. Play around with it privately. Maybe you can pivot there so that it meets the criteria.