182 lines
5.8 KiB
Python
182 lines
5.8 KiB
Python
"""
|
|
Model to store a microsite in the database.
|
|
|
|
The object is stored as a json representation of the python dict
|
|
that would have been used in the settings.
|
|
|
|
"""
|
|
import collections
|
|
|
|
from django.contrib.sites.models import Site
|
|
from django.db import models
|
|
from django.db.models.base import ObjectDoesNotExist
|
|
from django.db.models.signals import pre_delete, pre_save
|
|
from django.dispatch import receiver
|
|
from jsonfield.fields import JSONField
|
|
from model_utils.models import TimeStampedModel
|
|
|
|
|
|
class Microsite(models.Model):
|
|
"""
|
|
This is where the information about the microsite gets stored to the db.
|
|
To achieve the maximum flexibility, most of the fields are stored inside
|
|
a json field.
|
|
|
|
Notes:
|
|
- The key field was required for the dict definition at the settings, and it
|
|
is used in some of the microsite_configuration methods.
|
|
- The site field is django site.
|
|
- The values field must be validated on save to prevent the platform from crashing
|
|
badly in the case the string is not able to be loaded as json.
|
|
|
|
.. no_pii:
|
|
"""
|
|
site = models.OneToOneField(Site, related_name='microsite', on_delete=models.CASCADE)
|
|
key = models.CharField(max_length=63, db_index=True, unique=True)
|
|
values = JSONField(null=False, blank=True, load_kwargs={'object_pairs_hook': collections.OrderedDict})
|
|
|
|
def __unicode__(self):
|
|
return self.key
|
|
|
|
def get_organizations(self):
|
|
"""
|
|
Helper method to return a list of organizations associated with our particular Microsite
|
|
"""
|
|
return MicrositeOrganizationMapping.get_organizations_for_microsite_by_pk(self.id) # pylint: disable=no-member
|
|
|
|
@classmethod
|
|
def get_microsite_for_domain(cls, domain):
|
|
"""
|
|
Returns the microsite associated with this domain. Note that we always convert to lowercase, or
|
|
None if no match
|
|
"""
|
|
|
|
# remove any port number from the hostname
|
|
domain = domain.split(':')[0]
|
|
microsites = cls.objects.filter(site__domain__iexact=domain)
|
|
|
|
return microsites[0] if microsites else None
|
|
|
|
|
|
class MicrositeHistory(TimeStampedModel):
|
|
"""
|
|
This is an archive table for Microsites model, so that we can maintain a history of changes. Note that the
|
|
key field is no longer unique
|
|
|
|
.. no_pii:
|
|
"""
|
|
site = models.ForeignKey(Site, related_name='microsite_history', on_delete=models.CASCADE)
|
|
key = models.CharField(max_length=63, db_index=True)
|
|
values = JSONField(null=False, blank=True, load_kwargs={'object_pairs_hook': collections.OrderedDict})
|
|
|
|
def __unicode__(self):
|
|
return self.key
|
|
|
|
class Meta(object):
|
|
""" Meta class for this Django model """
|
|
verbose_name_plural = "Microsite histories"
|
|
|
|
|
|
def _make_archive_copy(instance):
|
|
"""
|
|
Helper method to make a copy of a Microsite into the history table
|
|
"""
|
|
archive_object = MicrositeHistory(
|
|
key=instance.key,
|
|
site=instance.site,
|
|
values=instance.values,
|
|
)
|
|
archive_object.save()
|
|
|
|
|
|
@receiver(pre_delete, sender=Microsite)
|
|
def on_microsite_deleted(sender, instance, **kwargs): # pylint: disable=unused-argument
|
|
"""
|
|
Archive the exam attempt when the item is about to be deleted
|
|
Make a clone and populate in the History table
|
|
"""
|
|
_make_archive_copy(instance)
|
|
|
|
|
|
@receiver(pre_save, sender=Microsite)
|
|
def on_microsite_updated(sender, instance, **kwargs): # pylint: disable=unused-argument
|
|
"""
|
|
Archive the microsite on an update operation
|
|
"""
|
|
|
|
if instance.id:
|
|
# on an update case, get the original and archive it
|
|
original = Microsite.objects.get(id=instance.id)
|
|
_make_archive_copy(original)
|
|
|
|
|
|
class MicrositeOrganizationMapping(models.Model):
|
|
"""
|
|
Mapping of Organization to which Microsite it belongs
|
|
|
|
.. no_pii:
|
|
"""
|
|
|
|
organization = models.CharField(max_length=63, db_index=True, unique=True)
|
|
microsite = models.ForeignKey(Microsite, db_index=True, on_delete=models.CASCADE)
|
|
|
|
def __unicode__(self):
|
|
"""String conversion"""
|
|
return u'{microsite_key}: {organization}'.format(
|
|
microsite_key=self.microsite.key,
|
|
organization=self.organization
|
|
)
|
|
|
|
@classmethod
|
|
def get_organizations_for_microsite_by_pk(cls, microsite_pk):
|
|
"""
|
|
Returns a list of organizations associated with the microsite key, returned as a set
|
|
"""
|
|
return cls.objects.filter(microsite_id=microsite_pk).values_list('organization', flat=True)
|
|
|
|
@classmethod
|
|
def get_microsite_for_organization(cls, org):
|
|
"""
|
|
Returns the microsite object for a given organization based on the table mapping, None if
|
|
no mapping exists
|
|
"""
|
|
|
|
try:
|
|
item = cls.objects.select_related('microsite').get(organization=org)
|
|
return item.microsite
|
|
except ObjectDoesNotExist:
|
|
return None
|
|
|
|
|
|
class MicrositeTemplate(models.Model):
|
|
"""
|
|
A HTML template that a microsite can use
|
|
|
|
.. no_pii:
|
|
"""
|
|
|
|
microsite = models.ForeignKey(Microsite, db_index=True, on_delete=models.CASCADE)
|
|
template_uri = models.CharField(max_length=255, db_index=True)
|
|
template = models.TextField()
|
|
|
|
def __unicode__(self):
|
|
"""String conversion"""
|
|
return u'{microsite_key}: {template_uri}'.format(
|
|
microsite_key=self.microsite.key,
|
|
template_uri=self.template_uri
|
|
)
|
|
|
|
class Meta(object):
|
|
""" Meta class for this Django model """
|
|
unique_together = (('microsite', 'template_uri'),)
|
|
|
|
@classmethod
|
|
def get_template_for_microsite(cls, domain, template_uri):
|
|
"""
|
|
Returns the template object for the microsite, None if not found
|
|
"""
|
|
try:
|
|
return cls.objects.get(microsite__site__domain=domain, template_uri=template_uri)
|
|
except ObjectDoesNotExist:
|
|
return None
|