Last active
November 6, 2018 11:19
-
-
Save rluts/242196b2289b7bb1fac6ca2a63d09841 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.db import models | |
from django.conf import settings | |
import pkgutil | |
import os | |
from importlib import import_module | |
from functools import partialmethod | |
class PluginField(models.CharField): | |
""" | |
1) Create 'plugins' path in your application directory | |
2) Declare Plugin class with 'name' property | |
3) in models.py: | |
class YourModel(models.Model): | |
plugin = PluginField() | |
4) Get Plugin instance: | |
obj = YourModel.objects.get(id=1) | |
instance = obj.get_plugin_instance() | |
https://gist.github.com/rluts/242196b2289b7bb1fac6ca2a63d09841 | |
""" | |
description = 'Plugin field' | |
def __init__(self, plugins_path='plugins', *args, **kwargs): | |
self.plugins_path = plugins_path | |
kwargs['max_length'] = 255 | |
super(PluginField, self).__init__(*args, **kwargs) | |
def deconstruct(self): | |
name, path, args, kwargs = super().deconstruct() | |
del kwargs["max_length"] | |
return name, path, args, kwargs | |
def _plugin_choices(self): | |
module_path = os.path.join(settings.BASE_DIR, self.app_label, self.plugins_path) | |
for pack in pkgutil.walk_packages([module_path]): | |
loader = import_module('.'.join([self.app_label, self.plugins_path, pack.name])) | |
yield (pack.name, loader.Plugin.name) | |
def _check_choices(self): | |
if hasattr(self, 'model'): | |
self.app_label = self.model._meta.app_label | |
self.choices = list(self._plugin_choices()) | |
self.help_text = 'You can add new plugin to %s path' % os.path.join(self.app_label, self.plugins_path) | |
return super(PluginField, self)._check_choices() | |
def _get_loader(self, instance, *args): | |
loader = import_module('.'.join( | |
[self.model._meta.app_label, self.plugins_path, getattr(instance, self.attname)]) | |
) | |
return loader.Plugin() | |
def contribute_to_class(self, cls, name, **kwargs): | |
super().contribute_to_class(cls, name, **kwargs) | |
instance = getattr(cls, self.attname) | |
setattr(cls, 'get_%s_instance' % self.name, partialmethod(self._get_loader, instance)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment