In Django, I cannot downcast (attributes are missing). Any trivial solution breaks the Open-Closed Principle. This Solution not:
from django.db import modelsclass ParentModel(models.Model):type = models.CharField(max_length=255, default='item')class Meta:abstract = Truedef save(self, *args, **kwargs):self.type = self.type_strsuper().save(*args, **kwargs)@staticmethoddef register_subtype(clazz):the_type = clazz.type_strif not hasattr(ParentModel, 'subclasses'):ParentModel.subclasses = {}ParentModel.subclasses[the_type] = clazzdef downcast(self):if self.type not in ParentModel.subclasses:return selfreturn 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 settingsfrom django.apps import AppConfigclass RecipesConfig(AppConfig):name = 'recipes'def ready(self):from .models import Recipefrom core.models import ItemItem.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
Post a Comment