class ImportObject(models.Model): u''' Base class to import model *instance* specific code at runtime. By default the model instance contains a python import string (myapp.foo.MyClass) in the primary key. Example: my_workflow=WorkflowDefinition.objects.get(pk='myapp.foo.MyClass') my_workflow.object --> instance of myapp.foo.MyClass myapp.foo.MyClass can be a normal Python class or a Model subclass. If myapp.foo.MyClass is a subclass of Model. It should have a OneToOneField to (in this example) WorkflowDefinition. Why not use content types and generic relations which are provided by django? The imported class don't need to be a model. It can be plain python class. Next argument: because it does not use serial (auto increment) primary keys. Explicit primary keys don't clash if you want to deploy applications in several projects. ''' class Meta: abstract=True _import_object_attribute='pk' _cls=None @property def cls(self): if not self._cls is None: return self._cls import_string=getattr(self, self._import_object_attribute) if not import_string: cls=None else: if isinstance(import_string, models.Model): import_string=import_string.pk # myapp.foo.MyClass cls=import_from_string(import_string) self._cls=cls return cls _object=None @property def object(self): if not self._object is None: return self._object cls=self.cls if cls is None: obj=None else: if issubclass(cls, models.Model): obj=self.cls.objects.get(pk=self) else: obj=self.cls(self) self._object=obj return obj def import_from_string(to_import): u''' Import a object (variable, method, class ...) with a string. Example: 'myapp.models.FooModel' ''' if not '.' in to_import: raise ImportError('No "." in %r' % to_import) idx=to_import.rindex('.') module_name=to_import[:idx] attr=to_import[idx+1:] module=__import__(module_name, {}, {}, [attr]) something=getattr(module, attr, None) if not something: raise ImportError('module %s has no attribute %r' % (module_name, attr)) return something