Skip to main content

custom fields useful to implement the Strategy Pattern with Django models.

Project description

django-strategy-field

Pypi coverage Test Django

Set of custom fields useful to implement the Strategy Pattern with Django models.

The Strategies are displayed in SelectBoxes as standard choice field

This package provides the following custom fields:

  • StrategyField
  • MultipleStrategyField
  • StrategyClassField
  • MultipleStrategyClassField

The StrategyField can be accessed as instance of the model with an attribute context that points to model that 'owns' the field (inverse relation). So:

Example

    from strategy_field.fields import StrategyField
    from django.core.mail.backends.filebased.EmailBackend


    class Event(models.Model):
        backend = StrategyField()

    Event(sender='django.core.mail.backends.filebased.EmailBackend')

Use case

As example we can imagine an application that manages Events that need to be notified to users. Each Occurrence of Event can be notified using different transport, (email, sms,...). We want to be able to add/change the way we send notification, per event basis, simply using the Django admin panel.

    from strategy_field.fields import StrategyField
    from strategy_field.registry import Registry

    class TransportRegistry(Registry)
        pass

    class AbstractStrategy(object):
        def __init__(self, context):
            self.context = context

        def send(self):
            raise NotImplementedError

    class EmailStrategy(AbstractTransport):
        def send(self):
            ...

    class SMSStrategy(AbstractTransport):
        def send(self):
            ...
    registry = TransportRegistry(AbstractStrategy)
    registry.register(EmailStrategy)
    registry.register(SMSStrategy)

    class Event(models.Model):
        sender = StrategyField(registry=registry)

    Event.objects.get_or_create(sender=EmailStrategy)
    ...
    ...
    e = Event.objects.get(sender=EmailStrategy)
    e.sender.send() # e.sender.context == e

More examples

Use callable

    from strategy_field.fields import StrategyField
    from strategy_field.registry import Registry

    registry1 = Registry()
    registry2 = Registry()

    class A(model):
        sender = StrategyField(registry=lambda model: model._registry)
        class Meta:
            abstract = True

    class C1(A):
        _registry = registry1
        class Meta:
            abstract = True

    class C2(A):
        _registry = registry2
        class Meta:
            abstract = True

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page