1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- # -*- coding: utf-8 -*-
- from django.db import models
- from polymorphic import PolymorphicModel
- from coin.offers.models import OfferSubscription
- from django.db.models.signals import post_save, post_delete
- from django.dispatch import receiver
- from coin.resources.models import IPSubnet
- """
- Implementation note : Configuration is a PolymorphicModel.
- The childs of Configuration are the differents models to store
- technical informations of a subscibtion.
- To add a new configuration backend, you have to create a new app with a model
- which inherit from Configuration.
- Your model can implement Meta verbose_name to have human readable name and a
- url_namespace variable to specify the url namespace used by this model.
- """
- class Configuration(PolymorphicModel):
- offersubscription = models.OneToOneField(OfferSubscription,
- related_name='configuration',
- verbose_name='abonnement')
- @staticmethod
- def get_configurations_choices_list():
- """
- Génère automatiquement la liste de choix possibles de configurations
- en fonction des classes enfants de Configuration
- """
- return tuple((x().__class__.__name__,x()._meta.verbose_name)
- for x in Configuration.__subclasses__())
-
- def model_name(self):
- return self.__class__.__name__
- model_name.short_description = 'Nom du modèle'
- def configuration_type_name(self):
- return self._meta.verbose_name
- configuration_type_name.short_description = 'Type'
- def get_absolute_url(self):
- """
- Renvoi l'URL d'accès à la page "details" de l'objet
- Une url doit être nommée "details"
- """
- from django.core.urlresolvers import reverse
- return reverse('%s:details' % self.get_url_namespace(),
- args=[str(self.id)])
- def get_url_namespace(self):
- """
- Renvoi le namespace utilisé par la configuration. Utilise en priorité
- celui définit dans la classe enfant dans url_namespace sinon
- par défaut utilise le nom de la classe en minuscule
- """
- if self.url_namespace:
- return self.url_namespace
- else:
- return self.model_name().lower()
- @receiver(post_save, sender=IPSubnet)
- def subnet_save_event(sender, **kwargs):
- """Fires when a subnet is saved (created/modified). We tell the
- configuration backend to do whatever it needs to do with it.
- We should use a pre_save signal, so that if anything goes wrong in the
- backend (exception raised), nothing is actually saved in the database.
- But it has a big problem: the configuration backend will not see the
- change, since it has not been saved into the database yet.
- That's why we use a post_save signal instead. But surprisingly, all
- is well: if we raise an exception here, the IPSubnet object will not
- be saved in the database. But the backend *does* see the new state of
- the database. It looks like the database rollbacks if an exception is
- raised. Whatever the reason, this is not a documented feature of
- Django signals.
- """
- subnet = kwargs['instance']
- config = subnet.configuration
- if config:
- config.save_subnet(subnet, kwargs['created'])
- @receiver(post_delete, sender=IPSubnet)
- def subnet_delete_event(sender, **kwargs):
- """Fires when a subnet is deleted. We tell the configuration backend to
- do whatever it needs to do with it.
- """
- subnet = kwargs['instance']
- config = subnet.configuration
- if config:
- config.delete_subnet(subnet)
|