class TestFieldModel(models.Model): title = models.CharField(max_length=200) mlist = ListField() mlist_default = ListField(default=["a", "b"]) slist = ListField(ordering=lambda x: x) slist_default = ListField(default=["b", "a"], ordering=lambda x: x) mdict = DictField() mdict_default = DictField(default={"a": "a", 'b': 1}) mset = SetField() mset_default = SetField(default=set(["a", 'b'])) class MongoMeta: index_together = [{'fields': [('title', -1), 'mlist']}]
class TestFieldModel(models.Model): title = models.CharField(max_length=200) mlist = ListField() mlist_default = ListField(default=["a", "b"]) slist = ListField(ordering=lambda x:x) slist_default = ListField(default=["b", "a"], ordering=lambda x:x) mdict = DictField() mdict_default = DictField(default={"a": "a", 'b':1}) mset = SetField() mset_default = SetField(default=set(["a", 'b'])) class MongoMeta: index_together = [{ 'fields' : [ ('title', False), 'mlist'] }] def __unicode__(self): return "Test special field model: %s" % (self.title)
class BaseObjectPermission(models.Model): permission_set = SetField(models.CharField(max_length=64)) content_type = models.CharField(max_length=256) object_id = models.PositiveIntegerField() def get_permissions(self): return self.permission_set def set_permissions(self, permission_list): self.permission_set = permission_list permissions = property(get_permissions, set_permissions) class Meta: abstract = True
class PmUser(AbstractBaseUser): name = models.CharField(max_length=30, blank=False) email = models.CharField(unique=True, db_index=True, max_length=255) phoneNumber = models.CharField(max_length=20, blank=True) isActive = models.BooleanField(default=True) type = models.CharField(max_length=10, blank=True) is_staff = models.BooleanField(default=False) sources = SetField() additionalInfo = DictField() is_email_subscribed = models.BooleanField(default=False) isDeleted = models.BooleanField(default=False) createdAt = models.DateTimeField(default=datetime.datetime.now()) autoLogOutTime = models.IntegerField(default=0) USERNAME_FIELD = 'email' objects = CustomUserManager() def get_full_name(self): return self.name def get_email(self): return self.email def get_phone_number(self): return self.phoneNumber def get_short_name(self): return self.email @property def is_superuser(self): return self.is_staff def has_perm(self, perm, obj=None): return self.is_staff def has_module_perms(self, app_label): return self.is_staff class MongoMeta: db_table = 'Users' index_together = ["name"]
class ConceptVersion(ConceptValidationMixin, ResourceVersionModel): external_id = models.TextField(null=True, blank=True) concept_class = models.TextField() datatype = models.TextField(null=True, blank=True) names = ListField(EmbeddedModelField('LocalizedText')) descriptions = ListField(EmbeddedModelField('LocalizedText'), null=True) retired = models.BooleanField(default=False) root_version = models.ForeignKey('self', null=True, blank=True) is_latest_version = models.BooleanField(default=True) version_created_by = models.TextField() update_comment = models.TextField(null=True, blank=True) source_version_ids = SetField() class MongoMeta: indexes = [[('uri', 1)], [('versioned_object_id', 1), ('is_latest_version', 1), ('created_at', -1)], [('source_version_ids', 1), ('updated_at', -1)]] objects = MongoDBManager() def clone(self): concept_version = ConceptVersion( mnemonic='--TEMP--', public_access=self.public_access, external_id=self.external_id, concept_class=self.concept_class, datatype=self.datatype, names=map(lambda n: n.clone(), self.names), retired=self.retired, versioned_object_id=self.versioned_object_id, versioned_object_type=self.versioned_object_type, released=self.released, previous_version=self, parent_version=self.parent_version, root_version=self.root_version, is_latest_version=self.is_latest_version, extras=self.extras) if self.descriptions: concept_version.descriptions = map(lambda d: d.clone(), self.descriptions) else: concept_version.descriptions = [] return concept_version @property def name(self): return self.versioned_object.mnemonic @property def owner(self): return self.versioned_object.owner @property def owner_name(self): return self.versioned_object.owner_name @property def owner_type(self): return self.versioned_object.owner_type @property def owner_url(self): return self.versioned_object.owner_url @property def display_name(self): return Concept.get_display_name_for(self) @property def display_locale(self): return Concept.get_display_locale_for(self) @property def source(self): return self.versioned_object.parent @property def parent_source(self): return self.source def get_collection_versions(self): from collection.models import CollectionVersion return CollectionVersion.get_collection_versions_with_concept(self.id) @property def mappings_url(self): concept = self.versioned_object source = concept.parent owner = source.owner owner_kwarg = 'user' if isinstance(owner, User) else 'org' return reverse('concept-mapping-list', kwargs={ 'concept': concept.mnemonic, 'source': source.mnemonic, owner_kwarg: owner.mnemonic }) @property def names_for_default_locale(self): names = [] for name in self.names: if settings.DEFAULT_LOCALE == name.locale: names.append(name.name) return names @property def all_names(self): names = [] for name in self.names: names.append(name.name) return names @property def descriptions_for_default_locale(self): descriptions = [] if self.descriptions: for desc in self.descriptions: if settings.DEFAULT_LOCALE == desc.locale: descriptions.append(desc.name) return descriptions @property def is_root_version(self): return self == self.root_version @property def public_can_view(self): return self.source.public_access in [ ACCESS_TYPE_EDIT, ACCESS_TYPE_VIEW ] def get_empty_mappings(self): return self.versioned_object.get_empty_mappings() def get_unidirectional_mappings(self): return self.versioned_object.get_unidirectional_mappings() def get_bidirectional_mappings(self): return self.versioned_object.get_bidirectional_mappings() @classmethod def get_latest_version_of(cls, concept): versions = ConceptVersion.objects.filter( versioned_object_id=concept.id, is_latest_version=True).order_by('-created_at') return versions[0] if versions else None @classmethod def get_latest_version_by_id(cls, id): versions = ConceptVersion.objects.filter( versioned_object_id=id, is_latest_version=True).order_by('-created_at') return versions[0] if versions else None @classmethod def for_concept(cls, concept, label, previous_version=None, parent_version=None): return ConceptVersion( mnemonic=label, public_access=concept.public_access, external_id=concept.external_id, concept_class=concept.concept_class, datatype=concept.datatype, extras=concept.extras, names=concept.names, descriptions=concept.descriptions, retired=concept.retired, versioned_object_id=concept.id, versioned_object_type=ContentType.objects.get_for_model(Concept), released=False, previous_version=previous_version, parent_version=parent_version, version_created_by=concept.created_by, created_by=concept.created_by, updated_by=concept.updated_by, ) @classmethod def diff(cls, v1, v2): diffs = {} if v1.public_access != v2.public_access: diffs['public_access'] = { 'was': v1.public_access, 'is': v2.public_access } if v1.external_id != v2.external_id: diffs['external_id'] = { 'was': v1.external_id, 'is': v2.external_id } if v1.concept_class != v2.concept_class: diffs['concept_class'] = { 'was': v1.concept_class, 'is': v2.concept_class } if v1.datatype != v2.datatype: diffs['datatype'] = {'was': v1.datatype, 'is': v2.datatype} # Diff names names_diff = cls.diff_in_localized_text_list(v1.names, v2.names) if names_diff: diffs['names'] = names_diff # Diff descriptions desc_diff = cls.diff_in_localized_text_list(v1.descriptions, v2.descriptions) if desc_diff: diffs['descriptions'] = desc_diff # Diff extras extras1 = v1.extras if v1.extras else {} extras2 = v2.extras if v2.extras else {} diff = len(extras1) != len(extras2) if not diff: for key in extras1: if key not in extras2: diff = True break if extras2[key] != extras1[key]: diff = True break if diff: diffs['extras'] = {'was': extras1, 'is': extras2} return diffs @classmethod def diff_in_localized_text_list(cls, names1, names2): if names1 is None or names2 is None: return None if len(names1) != len(names2): return True n1 = sorted(names1, key=lambda n: n.name) n2 = sorted(names2, key=lambda n: n.name) for i, n in enumerate(n1): if n.external_id != n2[i].external_id: return True if n.name != n2[i].name: return True if n.type != n2[i].type: return True if n.locale != n2[i].locale: return True if n.locale_preferred != n2[i].locale_preferred: return True return False @classmethod def persist_clone(cls, obj, user=None, **kwargs): errors = dict() if not user: errors[ 'version_created_by'] = 'Must specify which user is attempting to create a new concept version.' return errors obj.version_created_by = user.username previous_version = obj.previous_version previous_was_latest = previous_version.is_latest_version and obj.is_latest_version source_version = SourceVersion.get_head_of(obj.versioned_object.parent) persisted = False errored_action = 'saving new concept version' try: obj.clean() obj.save(**kwargs) obj.mnemonic = obj.id obj.save() errored_action = "updating 'is_latest_version' attribute on previous version" if previous_was_latest: previous_version.is_latest_version = False previous_version.save() errored_action = 'replacing previous version in latest version of source' source_version.update_concept_version(obj) # Mark versioned object as updated concept = obj.versioned_object concept.extras = obj.extras concept.names = obj.names concept.descriptions = obj.descriptions concept.concept_class = obj.concept_class concept.datatype = obj.datatype concept.save() persisted = True except ValidationError as err: errors.update(err.message_dict) finally: if not persisted: source_version.update_concept_version(obj.previous_version) if previous_was_latest: previous_version.is_latest_version = True previous_version.save() if obj.id: obj.delete() errors['non_field_errors'] = [ 'An error occurred while %s.' % errored_action ] return errors @classmethod def resource_type(cls): return VERSION_TYPE @classmethod def versioned_resource_type(cls): return CONCEPT_TYPE @staticmethod def get_url_kwarg(): return 'concept_version'
class MappingVersion(MappingValidationMixin, ResourceVersionModel): parent = models.ForeignKey(Source, related_name='mappings_version_from') map_type = models.TextField() from_concept = models.ForeignKey(Concept, related_name='mappings_version_from') to_concept = models.ForeignKey(Concept, null=True, blank=True, related_name='mappings_version_to') to_source = models.ForeignKey(Source, null=True, blank=True, related_name='mappings_version_to') to_concept_code = models.TextField(null=True, blank=True) to_concept_name = models.TextField(null=True, blank=True) retired = models.BooleanField(default=False) external_id = models.TextField(null=True, blank=True) is_latest_version = models.BooleanField(default=True) update_comment = models.TextField(null=True, blank=True) source_version_ids = SetField() objects = MongoDBManager() class MongoMeta: indexes = [[('parent', 1), ('map_type', 1), ('from_concept', 1), ('to_concept', 1), ('to_source', 1), ('to_concept_code', 1)], [('parent', 1), ('map_type', 1), ('from_concept', 1), ('to_source', 1), ('to_concept_code', 1), ('to_concept_name', 1)], [('parent', 1), ('from_concept', 1), ('to_concept', 1), ('is_active', 1), ('retired', 1)], [('versioned_object_id', 1), ('is_latest_version', 1), ('created_at', -1)], [('source_version_ids', 1), ('updated_at', -1)]] def clone(self): return MappingVersion(mnemonic='--TEMP--', parent=self.parent, map_type=self.map_type, from_concept=self.from_concept, to_concept=self.to_concept, to_source=self.to_source, to_concept_code=self.to_concept_code, to_concept_name=self.to_concept_name, retired=self.retired, versioned_object_id=self.versioned_object_id, versioned_object_type=self.versioned_object_type, released=self.released, previous_version=self, parent_version=self.parent_version, is_latest_version=self.is_latest_version, extras=self.extras) class Meta: pass @property def source(self): return self.parent.mnemonic @property def parent_source(self): return self.parent @property def owner(self): return self.parent.owner_name @property def owner_type(self): return self.parent.owner_type @property def from_source(self): return self.from_concept.parent @property def from_source_owner(self): return self.from_source.owner_name @property def from_source_owner_mnemonic(self): return self.from_source.owner.mnemonic @property def from_source_owner_type(self): return self.from_source.owner_type @property def from_source_name(self): return self.from_source.mnemonic @property def from_source_url(self): return self.from_source.url @property def from_source_shorthand(self): return "%s:%s" % (self.from_source_owner_mnemonic, self.from_source_name) @property def from_concept_code(self): return self.from_concept.mnemonic @property def from_concept_name(self): return self.from_concept.display_name @property def from_concept_url(self): return self.from_concept.url @property def from_concept_shorthand(self): return "%s:%s" % (self.from_source_shorthand, self.from_concept_code) def get_to_source(self): return self.to_source or self.to_concept and self.to_concept.parent @property def to_source_name(self): return self.get_to_source() and self.get_to_source().mnemonic @property def to_source_url(self): to_source = self.get_to_source() return to_source.url if to_source else None @property def to_mapping_url(self): return self.versioned_object.uri @property def to_source_owner(self): return self.get_to_source() and unicode(self.get_to_source().parent) @property def to_source_owner_mnemonic(self): return self.get_to_source() and self.get_to_source().owner.mnemonic @property def to_source_owner_type(self): return self.get_to_source() and self.get_to_source().owner_type @property def to_source_shorthand(self): return self.get_to_source() and "%s:%s" % ( self.to_source_owner_mnemonic, self.to_source_name) def get_to_concept_name(self): return self.to_concept_name or (self.to_concept and self.to_concept.display_name) def get_to_concept_code(self): return self.to_concept_code or (self.to_concept and self.to_concept.mnemonic) @property def to_concept_url(self): return self.to_concept.url if self.to_concept else None @property def to_concept_shorthand(self): return "%s:%s" % (self.to_source_shorthand, self.get_to_concept_code()) @property def public_can_view(self): return self.public_access in [ACCESS_TYPE_EDIT, ACCESS_TYPE_VIEW] @staticmethod def resource_type(): return MAPPING_VERSION_RESOURCE_TYPE @property def collection_versions(self): return get_model('collection', 'CollectionVersion').objects.filter(mappings=self.id) @staticmethod def get_url_kwarg(): return 'mapping_version' @classmethod def for_mapping(cls, mapping, previous_version=None, parent_version=None): return MappingVersion( public_access=mapping.public_access, is_active=True, parent=mapping.parent, map_type=mapping.map_type, from_concept=mapping.from_concept, to_concept=mapping.to_concept, to_source=mapping.to_source, to_concept_code=mapping.to_concept_code, to_concept_name=mapping.to_concept_name, retired=mapping.retired, external_id=mapping.external_id, versioned_object_id=mapping.id, versioned_object_type=ContentType.objects.get_for_model(Mapping), released=False, previous_version=previous_version, parent_version=parent_version, created_by=mapping.created_by, updated_by=mapping.updated_by) @classmethod def get_latest_version_by_id(cls, id): versions = MappingVersion.objects.filter( versioned_object_id=id, is_latest_version=True).order_by('-created_at') return versions[0] if versions else None @classmethod def persist_clone(cls, obj, user=None, prev_latest_version=None, **kwargs): errors = dict() if not user: errors[ 'version_created_by'] = 'Must specify which user is attempting to create a new concept version.' return errors obj.version_created_by = user.username previous_version = obj.previous_version previous_was_latest = previous_version.is_latest_version and obj.is_latest_version source_version = SourceVersion.get_head_of(obj.versioned_object.parent) persisted = False errored_action = 'saving new mapping version' try: obj.save(**kwargs) obj.mnemonic = int(prev_latest_version.mnemonic) + 1 obj.save() errored_action = "updating 'is_latest_version' attribute on previous version" if previous_was_latest: previous_version.is_latest_version = False previous_version.save() errored_action = 'replacing previous version in latest version of source' source_version.update_mapping_version(obj) # Mark versioned object as updated mapping = obj.versioned_object mapping.save() persisted = True finally: if not persisted: source_version.update_mapping_version(obj.previous_version) if previous_was_latest: previous_version.is_latest_version = True previous_version.save() if obj.id: obj.delete() errors['non_field_errors'] = [ 'An error occurred while %s.' % errored_action ] return errors
class Service(models.Model): SLUG_RE = re.compile(r'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$') slug = models.SlugField(unique=True, db_index=True) label = models.CharField(max_length=255) backend = models.ForeignKey(Backend, null=True) params = models.TextField() owners = SetField(models.ForeignKey(User)) if use_ancestor: key = DbKeyField(primary_key=True) @classmethod def validate_slug(cls, slug): return cls.SLUG_RE.search(slug) @classmethod def split_request_host(cls, request): host = request.META['HTTP_HOST'] pieces = host.split('.', 1) if not cls.validate_slug(pieces[0]): raise Http404 if len(pieces) < 2: pieces.append('') else: pieces[1] = '.' + pieces[1] return tuple(pieces) @classmethod def get_from_request(cls, request): return cls.objects.get(slug=cls.split_request_host(request)[0]) @classmethod def new_from_request(cls, request): return cls(slug=cls.split_request_host(request)[0]) @classmethod def is_creation_allowed(cls, request): slug = cls.split_request_host(request)[0] if not cls.validate_slug(slug): return False pattern = getattr(settings, 'MULTITREEHOLE_SERVICE_SLUG_DISALLOWED', None) if pattern is None: return True return not re.search(pattern, slug) @classmethod def build_host(cls, slug, request): return slug + cls.split_request_host(request)[1] def get_host(self, request): return self.build_host(self.slug, request) def get_params(self): if not hasattr(self, 'params_data'): self.params_data = json.loads(self.params) return self.params_data def check_access(self, request, text=None): ''' This method returns three values. The first is access level: * If text is set, returns 'accept', 'moderate', 'throttle' or 'reject'. * If text is not set, returns 'accept', 'throttle' or 'reject'. The second is user identifier as a string. Usually this is user IP with last bits cleared. The third is a "confirm" function. Call it after a message is placed to confirm access (for throttling). ''' for access in self.get_params().get('access', []): access_level, user_identifier, confirm = self.match_access(access, request) if access_level != 'reject': if text is None or access_level == 'throttle': return access_level, user_identifier, confirm else: if 'reject' in access: reject_re = re.compile(access['reject']) if reject_re.search(text): return 'reject', user_identifier, confirm if 'moderate' in access: moderate_re = re.compile(access['moderate']) if moderate_re.search(text): return 'moderate', user_identifier, confirm # access_level should be 'accept' here. return access_level, user_identifier, confirm return 'reject', None, lambda obj: True def match_access(self, access, request): ''' Returns 'accept', 'throttle' or 'reject', plus the user identifier mentioned above. ''' from datetime import datetime, timedelta user_identifier = self.extract_user_identifier(access, request) confirm = lambda obj: True if user_identifier: throttle = access.get('throttle') if throttle: delta = timedelta(seconds=throttle) threshold = datetime.now() - delta def confirm(obj=None): try: existing = Message.filter_service(self).get( user_identifier=user_identifier, timestamp__gt=threshold, ) except ObjectDoesNotExist: if obj: # Shouldn't happen raise Exception('Expected message object is missing when confirming throttling') else: return True except MultipleObjectsReturned: return False # existing is returned if obj: if existing != obj: raise Exception('Expected message object is not returned when confirming throttling') else: return True else: return False if not confirm(): return 'throttle', user_identifier, confirm return 'accept', user_identifier, confirm return 'reject', user_identifier, confirm def extract_user_identifier(self, access, request): import ipaddr try: network = ipaddr.IPNetwork(access.get('network')) except ValueError: network = None address = ipaddr.IPAddress(request.META['REMOTE_ADDR']) if network and address in network: subnet = ipaddr.IPNetwork(address).supernet(access.get('suffixlen', 0)) return str(subnet.network) return None def is_owner(self, user): # Must be request.user.pk return user.pk in self.owners or user.is_superuser def __unicode__(self): return self.label
class ConceptContainerVersionModel(ResourceVersionModel): name = models.TextField() full_name = models.TextField(null=True, blank=True) default_locale = models.TextField(default=Common.DEFAULT_LOCALE, blank=True) supported_locales = ListField(null=True, blank=True) website = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True) version_external_id = models.TextField(null=True, blank=True) external_id = models.TextField(null=True, blank=True) _background_process_ids = SetField() # Used to skip saving _background_process_ids, # which is updated using atomic raw queries, see https://stackoverflow.com/a/33225984 default_save_fields = None def __init__(self, *args, **kwargs): super(ConceptContainerVersionModel, self).__init__(*args, **kwargs) if self.default_save_fields is None: # This block should only get called for the first object loaded default_save_fields = { f.name for f in self._meta.fields if not f.auto_created } default_save_fields.difference_update({ '_background_process_ids', }) self.__class__.default_save_fields = tuple(default_save_fields) def save(self, **kwargs): if self.id is not None and 'update_fields' not in kwargs: # If self.id is None (meaning the object has yet to be saved) # then do a normal update with all fields. # Otherwise, make sure `update_fields` is in kwargs. kwargs['update_fields'] = self.default_save_fields super(ConceptContainerVersionModel, self).save(**kwargs) class Meta(ResourceVersionModel.Meta): abstract = True @property def owner(self): return self.versioned_object.owner @property def owner_name(self): return self.versioned_object.owner_name @property def owner_type(self): return self.versioned_object.owner_type @property def owner_url(self): return self.versioned_object.owner_url @property def parent_resource(self): return self.versioned_object.parent_resource @property def parent_resource_type(self): return self.versioned_object.parent_resource_type @property def parent_url(self): return self.versioned_object.parent_url @staticmethod def get_url_kwarg(): return 'version' @classmethod def get_latest_released_version_of(cls, versioned_object): versions = versioned_object.get_version_model().objects.filter( versioned_object_id=versioned_object.id, is_active=True, released=True, retired=False).order_by('-created_at') return versions[0] if versions else None @classmethod def persist_new(cls, obj, user=None, **kwargs): obj.is_active = True if user: obj.created_by = user obj.updated_by = user kwargs['seed_concepts'] = True kwargs['seed_mappings'] = True return cls.persist_changes(obj, **kwargs) def update_version_data(self, obj=None): pass @classmethod def persist_changes(cls, obj, **kwargs): errors = dict() # Ensure versioned object specified versioned_object = kwargs.pop('versioned_object', obj.versioned_object) if versioned_object is None: errors['non_field_errors'] = ['Must specify a versioned object.'] return errors obj.versioned_object = versioned_object # Ensure mnemonic does not conflict with existing old_mnemonic = obj.mnemonic mnemonic = kwargs.pop('mnemonic', obj.mnemonic) if mnemonic != old_mnemonic: if cls.objects.filter(versioned_object_id=versioned_object.id, mnemonic=obj.mnemonic).exists(): errors['mnemonic'] = [ "Version with mnemonic %s already exists for %s %s." % (obj.mnemonic, cls.name, versioned_object.mnemonic) ] return errors obj.mnemonic = mnemonic # Ensure previous version is valid if hasattr(obj, '_previous_version_mnemonic' ) and obj._previous_version_mnemonic: previous_version_queryset = cls.objects.filter( versioned_object_id=versioned_object.id, mnemonic=obj._previous_version_mnemonic) if not previous_version_queryset.exists(): errors['previousVersion'] = [ "Previous version %s does not exist." % obj._previous_version_mnemonic ] elif obj.mnemonic == obj._previous_version_mnemonic: errors['previousVersion'] = [ "Previous version cannot be the same as current version." ] else: obj.previous_version = previous_version_queryset[0] del obj._previous_version_mnemonic # Ensure parent version is valid if hasattr( obj, '_parent_version_mnemonic') and obj._parent_version_mnemonic: parent_version_queryset = cls.objects.filter( versioned_object_id=versioned_object.id, mnemonic=obj._parent_version_mnemonic) if not parent_version_queryset.exists(): errors['parentVersion'] = [ "Parent version %s does not exist." % obj._parent_version_mnemonic ] elif obj.mnemonic == obj._parent_version_mnemonic: errors['parentVersion'] = [ "Parent version cannot be the same as current version." ] else: obj.parent_version = parent_version_queryset[0] del obj._parent_version_mnemonic # If there are errors at this point, fall out before doing any more work if errors: return errors # Seed mappings from another version, if requested seed_references = kwargs.pop('seed_references', False) if seed_references: obj.seed_references() obj.update_version_data() try: persisted = False seed_concepts = kwargs.pop('seed_concepts', False) seed_mappings = kwargs.pop('seed_mappings', False) obj.save(**kwargs) # Seed concepts from another version, if requested if seed_concepts: obj.seed_concepts() # Seed mappings from another version, if requested if seed_mappings: obj.seed_mappings() persisted = True finally: if not persisted: errors['non_field_errors'] = [ "Encountered an error while updating version." ] return errors def add_processing(self, process_id): if self.id: # Using raw query to atomically add item to the list self.__class__.objects.raw_update( {'_id': ObjectId(self.id)}, {'$push': { '_background_process_ids': process_id }}) # Update the current object self._background_process_ids.add(process_id) def remove_processing(self, process_id): if self.id: # Using raw query to atomically remove item from the list self.__class__.objects.raw_update( {'_id': ObjectId(self.id)}, {'$pull': { '_background_process_ids': process_id }}) # Update the current object self._background_process_ids.remove(process_id) @property def is_processing(self): if self._background_process_ids: for process_id in tuple(self._background_process_ids): res = AsyncResult(process_id) if (res.successful() or res.failed()): self.remove_processing(process_id) else: return True if self._background_process_ids: return True else: return False def clear_processing(self): self._background_process_ids = set() self.save(update_fields=['_background_process_ids']) @staticmethod def clear_all_processing(type): type.objects.all().update(_background_process_ids=set())
class Topic(models.Model): homepage = models.BooleanField(db_index=True) hidden = models.BooleanField() deleted = models.BooleanField() tags = SetField(db_index=True) obj = EmbeddedModelField() objects = TopicManager() views_count = models.PositiveIntegerField(default=0) replies_count = models.PositiveIntegerField(default=0) rating = models.IntegerField(default=0) timeshift = models.IntegerField(default=0) #Mostly used for bookkeeping, but might be useful later timestamp = models.PositiveIntegerField(default=0, db_index=True) def __init__(self, *args, **kwargs): super(Topic, self).__init__(*args, **kwargs) @property def title(self): return self.obj.title or self.pk @property def body(self): return self.obj.body def save(self, *args, **kwargs): if not self.timestamp: self.timestamp = int(time.mktime(datetime.datetime.now().timetuple())) # self.addToUserTopics() #The data transfer is massive so the benefit of this is slim to negative. super(Topic, self).save(*args, **kwargs) def updateRepliesCount(self): replies_count = self.replies.count() Topic.objects.raw_update({"_id": ObjectId(self.pk)}, {"$set": {"replies_count": replies_count}}) return replies_count def addToUserTopics(self): try: Profile.objects.raw_update( {"user_id": ObjectId(self.obj.user.pk)}, {"$addToSet": {"topics": self.pk}, }) except AttributeError: #If the obj has no user attribute (it's not a Post, for instance) pass return self def adjustRating(self, rating=0): Topic.objects.raw_update({"_id": ObjectId(self.pk)}, {"$inc": {"rating": rating}}) return self def tag(self, tagname): self.tags.add(tagname) return Tag.objects.create_or_update_count(tagname, self) def __unicode__(self): return self.title @permalink def get_absolute_url(self): return 'board_topic_view', (self.pk,), {} class Meta: ordering = ['-timestamp']