import xml.etree.ElementTree as et from django.db import models from boards.models import KeyPair TAG_MODEL = 'model' TAG_REQUEST = 'request' TAG_ID = 'id' TYPE_GET = 'get' TYPE_LIST = 'list' ATTR_VERSION = 'version' ATTR_TYPE = 'type' ATTR_NAME = 'name' ATTR_KEY = 'key' ATTR_KEY_TYPE = 'type' ATTR_LOCAL_ID = 'local-id' class GlobalIdManager(models.Manager): def global_id_exists(self, global_id): """ Checks if the same global id already exists in the system. """ return self.filter(key=global_id.key, key_type=global_id.key_type, local_id=global_id.local_id).exists() class GlobalId(models.Model): """ Global model ID and cache. Key, key type and local ID make a single global identificator of the model. Content is an XML cache of the model that can be passed along between nodes without manual serialization each time. """ class Meta: app_label = 'boards' objects = GlobalIdManager() def __init__(self, *args, **kwargs): models.Model.__init__(self, *args, **kwargs) if 'key' in kwargs and 'key_type' in kwargs and 'local_id' in kwargs: self.key = kwargs['key'] self.key_type = kwargs['key_type'] self.local_id = kwargs['local_id'] key = models.TextField() key_type = models.TextField() local_id = models.IntegerField() content = models.TextField(blank=True, null=True) def __str__(self): return '%s::%s::%d' % (self.key_type, self.key, self.local_id) def to_xml_element(self, element: et.Element): """ Exports global id to an XML element. """ element.set(ATTR_KEY, self.key) element.set(ATTR_KEY_TYPE, self.key_type) element.set(ATTR_LOCAL_ID, str(self.local_id)) @staticmethod def from_xml_element(element: et.Element): """ Parses XML id tag and gets global id from it. Arguments: element -- the XML 'id' element Returns: global_id -- id itself exists -- True if the global id was taken from database, False if it did not exist and was created. """ try: return GlobalId.objects.get(key=element.get(ATTR_KEY), key_type=element.get(ATTR_KEY_TYPE), local_id=int(element.get( ATTR_LOCAL_ID))), True except GlobalId.DoesNotExist: return GlobalId(key=element.get(ATTR_KEY), key_type=element.get(ATTR_KEY_TYPE), local_id=int(element.get(ATTR_LOCAL_ID))), False def is_local(self): """Checks fo the ID is local model's""" return KeyPair.objects.filter( key_type=self.key_type, public_key=self.key).exists() def clear_cache(self): """ Removes content cache and signatures. """ self.content = None self.save() self.signature_set.all().delete() class Signature(models.Model): class Meta: app_label = 'boards' def __init__(self, *args, **kwargs): models.Model.__init__(self, *args, **kwargs) if 'key' in kwargs and 'key_type' in kwargs and 'signature' in kwargs: self.key_type = kwargs['key_type'] self.key = kwargs['key'] self.signature = kwargs['signature'] key_type = models.TextField() key = models.TextField() signature = models.TextField() global_id = models.ForeignKey('GlobalId', on_delete=models.CASCADE)