class Project(Model): """ Projects are permission based namespaces which generally are the top level entry point for all data. A project may be owned by only a single team, and may or may not have an owner (which is thought of as a project creator). """ PLATFORM_CHOICES = tuple((p, PLATFORM_TITLES.get(p, p.title())) for p in PLATFORM_LIST) + (('other', 'Other'), ) slug = models.SlugField(null=True) name = models.CharField(max_length=200) owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="sentry_owned_project_set", null=True) team = models.ForeignKey(Team, null=True) public = models.BooleanField(default=False) date_added = models.DateTimeField(default=timezone.now) status = BoundedPositiveIntegerField(default=0, choices=( (STATUS_VISIBLE, _('Visible')), (STATUS_HIDDEN, _('Hidden')), ), db_index=True) platform = models.CharField(max_length=32, choices=PLATFORM_CHOICES, null=True) objects = ProjectManager(cache_fields=[ 'pk', 'slug', ]) class Meta: unique_together = (('team', 'slug'), ) __repr__ = sane_repr('team_id', 'slug', 'owner_id') def __unicode__(self): return u'%s (%s)' % (self.name, self.slug) def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, team=self.team) super(Project, self).save(*args, **kwargs) def delete(self): # This handles cascades properly # TODO: this doesn't clean up the index for model in (TagKey, TagValue, GroupTagKey, GroupTag, GroupCountByMinute, ProjectCountByMinute, Activity, EventMapping, Event, Group): logging.info('Removing %r objects where project=%s', model, self.id) has_results = True while has_results: has_results = False for obj in model.objects.filter(project=self)[:1000]: obj.delete() has_results = True super(Project, self).delete() def get_absolute_url(self): return absolute_uri( reverse('sentry-stream', args=[self.team.slug, self.slug])) def merge_to(self, project): if not isinstance(project, Project): project = Project.objects.get_from_cache(pk=project) for group in Group.objects.filter(project=self): try: other = Group.objects.get( project=project, logger=group.logger, culprit=group.culprit, checksum=group.checksum, ) except Group.DoesNotExist: group.update(project=project) for model in (Event, GroupTag, GroupCountByMinute): model.objects.filter(project=self, group=group).update(project=project) else: Event.objects.filter(group=group).update(group=other) for obj in GroupTag.objects.filter(group=group): obj2, created = GroupTag.objects.get_or_create( project=project, group=group, key=obj.key, value=obj.value, defaults={'times_seen': obj.times_seen}) if not created: obj2.update(times_seen=F('times_seen') + obj.times_seen) for obj in GroupCountByMinute.objects.filter(group=group): obj2, created = GroupCountByMinute.objects.get_or_create( project=project, group=group, date=obj.date, defaults={ 'times_seen': obj.times_seen, 'time_spent_total': obj.time_spent_total, 'time_spent_count': obj.time_spent_count, }) if not created: obj2.update( times_seen=F('times_seen') + obj.times_seen, time_spent_total=F('time_spent_total') + obj.time_spent_total, time_spent_count=F('time_spent_count') + obj.time_spent_count, ) for fv in TagValue.objects.filter(project=self): TagValue.objects.get_or_create(project=project, key=fv.key, value=fv.value) fv.delete() self.delete() def is_default_project(self): return str(self.id) == str(settings.SENTRY_PROJECT) or str( self.slug) == str(settings.SENTRY_PROJECT) def get_tags(self): if not hasattr(self, '_tag_cache'): tags = ProjectOption.objects.get_value(self, 'tags', None) if tags is None: tags = TagKey.objects.all_keys(self) self._tag_cache = [t for t in tags if not t.startswith('sentry:')] return self._tag_cache # TODO: Make these a mixin def update_option(self, *args, **kwargs): return ProjectOption.objects.set_value(self, *args, **kwargs) def get_option(self, *args, **kwargs): return ProjectOption.objects.get_value(self, *args, **kwargs)
class Project(Model): """ Projects are permission based namespaces which generally are the top level entry point for all data. A project may be owned by only a single team, and may or may not have an owner (which is thought of as a project creator). """ PLATFORM_CHOICES = tuple((p, PLATFORM_TITLES.get(p, p.title())) for p in PLATFORM_LIST) + (('other', 'Other'), ) slug = models.SlugField(unique=True, null=True) name = models.CharField(max_length=200) owner = models.ForeignKey(User, related_name="sentry_owned_project_set", null=True) team = models.ForeignKey(Team, null=True) public = models.BooleanField( default=settings.ALLOW_PUBLIC_PROJECTS and settings.PUBLIC) date_added = models.DateTimeField(default=timezone.now) status = models.PositiveIntegerField(default=0, choices=( (STATUS_VISIBLE, 'Visible'), (STATUS_HIDDEN, 'Hidden'), ), db_index=True) platform = models.CharField(max_length=32, choices=PLATFORM_CHOICES, null=True) objects = ProjectManager(cache_fields=[ 'pk', 'slug', ]) __repr__ = sane_repr('slug', 'owner_id') def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name) super(Project, self).save(*args, **kwargs) def delete(self): # This hadles cascades properly # TODO: this doesnt clean up the index for model in (Event, Group, FilterValue, MessageFilterValue, MessageCountByMinute): model.objects.filter(project=self).delete() super(Project, self).delete() def merge_to(self, project): if not isinstance(project, Project): project = Project.objects.get_from_cache(pk=project) for group in Group.objects.filter(project=self): try: other = Group.objects.get( project=project, logger=group.logger, culprit=group.culprit, checksum=group.checksum, ) except Group.DoesNotExist: group.update(project=project) for model in (Event, MessageFilterValue, MessageCountByMinute): model.objects.filter(project=self, group=group).update(project=project) else: Event.objects.filter(group=group).update(group=other) for obj in MessageFilterValue.objects.filter(group=group): obj2, created = MessageFilterValue.objects.get_or_create( project=project, group=group, key=obj.key, value=obj.value, defaults={'times_seen': obj.times_seen}) if not created: obj2.update(times_seen=F('times_seen') + obj.times_seen) for obj in MessageCountByMinute.objects.filter(group=group): obj2, created = MessageCountByMinute.objects.get_or_create( project=project, group=group, date=obj.date, defaults={ 'times_seen': obj.times_seen, 'time_spent_total': obj.time_spent_total, 'time_spent_count': obj.time_spent_count, }) if not created: obj2.update( times_seen=F('times_seen') + obj.times_seen, time_spent_total=F('time_spent_total') + obj.time_spent_total, time_spent_count=F('time_spent_count') + obj.time_spent_count, ) for fv in FilterValue.objects.filter(project=self): FilterValue.objects.get_or_create(project=project, key=fv.key, value=fv.value) fv.delete() self.delete() def is_default_project(self): return str(self.id) == str(settings.PROJECT) or str(self.slug) == str( settings.PROJECT) def get_tags(self): if not hasattr(self, '_tag_cache'): tags = ProjectOption.objects.get_value(self, 'tags', None) if tags is None: tags = FilterKey.objects.all_keys(self) self._tag_cache = tags return self._tag_cache
class Project(Model): """ Projects are permission based namespaces which generally are the top level entry point for all data. A project may be owned by only a single team, and may or may not have an owner (which is thought of as a project creator). """ slug = models.SlugField(unique=True, null=True) name = models.CharField(max_length=200) owner = models.ForeignKey(User, related_name="sentry_owned_project_set", null=True) team = models.ForeignKey(Team, null=True) public = models.BooleanField(default=settings.ALLOW_PUBLIC_PROJECTS) date_added = models.DateTimeField(default=timezone.now) status = models.PositiveIntegerField(default=0, choices=( (0, 'Visible'), (1, 'Hidden'), ), db_index=True) objects = ProjectManager(cache_fields=[ 'pk', 'slug', ]) def __unicode__(self): return u'%s (%s)' % (self.name, self.slug) def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) super(Project, self).save(*args, **kwargs) def delete(self): # This hadles cascades properly # TODO: this doesnt clean up the index for model in (Event, Group, FilterValue, MessageFilterValue, MessageCountByMinute): model.objects.filter(project=self).delete() super(Project, self).delete() def merge_to(self, project): if not isinstance(project, Project): project = Project.objects.get_from_cache(pk=project) for group in Group.objects.filter(project=self): try: other = Group.objects.get( project=project, logger=group.logger, culprit=group.culprit, checksum=group.checksum, ) except Group.DoesNotExist: group.update(project=project) for model in (Event, MessageFilterValue, MessageCountByMinute): model.objects.filter(project=self, group=group).update(project=project) else: Event.objects.filter(group=group).update(group=other) for obj in MessageFilterValue.objects.filter(group=group): obj2, created = MessageFilterValue.objects.get_or_create( project=project, group=group, key=obj.key, value=obj.value, defaults={'times_seen': obj.times_seen}) if not created: obj2.update(times_seen=F('times_seen') + obj.times_seen) for obj in MessageCountByMinute.objects.filter(group=group): obj2, created = MessageCountByMinute.objects.get_or_create( project=project, group=group, date=obj.date, defaults={ 'times_seen': obj.times_seen, 'time_spent_total': obj.time_spent_total, 'time_spent_count': obj.time_spent_count, }) if not created: obj2.update( times_seen=F('times_seen') + obj.times_seen, time_spent_total=F('time_spent_total') + obj.time_spent_total, time_spent_count=F('time_spent_count') + obj.time_spent_count, ) for fv in FilterValue.objects.filter(project=self): FilterValue.objects.get_or_create(project=project, key=fv.key, value=fv.value) fv.delete() self.delete() def is_default_project(self): return str(self.id) == str(settings.PROJECT) or str(self.slug) == str( settings.PROJECT)
class Project(Model): """ Projects are permission based namespaces which generally are the top level entry point for all data. A project may be owned by only a single team, and may or may not have an owner (which is thought of as a project creator). """ PLATFORM_CHOICES = tuple((p, PLATFORM_TITLES.get(p, p.title())) for p in PLATFORM_LIST) + (('other', 'Other'), ) slug = models.SlugField(null=True) name = models.CharField(max_length=200) owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="sentry_owned_project_set", null=True) team = models.ForeignKey('sentry.Team', null=True) public = models.BooleanField(default=False) date_added = models.DateTimeField(default=timezone.now) status = BoundedPositiveIntegerField(default=0, choices=( (STATUS_VISIBLE, _('Visible')), (STATUS_HIDDEN, _('Hidden')), ), db_index=True) platform = models.CharField(max_length=32, choices=PLATFORM_CHOICES, null=True) objects = ProjectManager(cache_fields=[ 'pk', 'slug', ]) class Meta: app_label = 'sentry' db_table = 'sentry_project' unique_together = (('team', 'slug'), ) __repr__ = sane_repr('team_id', 'slug', 'owner_id') def __unicode__(self): return u'%s (%s)' % (self.name, self.slug) def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, team=self.team) super(Project, self).save(*args, **kwargs) def get_absolute_url(self): return absolute_uri( reverse('sentry-stream', args=[self.team.slug, self.slug])) def merge_to(self, project): from sentry.models import (Group, GroupTagValue, Event, TagValue) if not isinstance(project, Project): project = Project.objects.get_from_cache(pk=project) for group in Group.objects.filter(project=self): try: other = Group.objects.get( project=project, checksum=group.checksum, ) except Group.DoesNotExist: group.update(project=project) for model in (Event, GroupTagValue): model.objects.filter(project=self, group=group).update(project=project) else: Event.objects.filter(group=group).update(group=other) for obj in GroupTagValue.objects.filter(group=group): obj2, created = GroupTagValue.objects.get_or_create( project=project, group=group, key=obj.key, value=obj.value, defaults={'times_seen': obj.times_seen}) if not created: obj2.update(times_seen=F('times_seen') + obj.times_seen) for fv in TagValue.objects.filter(project=self): TagValue.objects.get_or_create(project=project, key=fv.key, value=fv.value) fv.delete() self.delete() def is_internal_project(self): for value in (settings.SENTRY_FRONTEND_PROJECT, settings.SENTRY_PROJECT): if str(self.id) == str(value) or str(self.slug) == str(value): return True return False def get_tags(self): from sentry.models import TagKey if not hasattr(self, '_tag_cache'): tags = self.get_option('tags', None) if tags is None: tags = [ t for t in TagKey.objects.all_keys(self) if not t.startswith('sentry:') ] self._tag_cache = tags return self._tag_cache # TODO: Make these a mixin def update_option(self, *args, **kwargs): from sentry.models import ProjectOption return ProjectOption.objects.set_value(self, *args, **kwargs) def get_option(self, *args, **kwargs): from sentry.models import ProjectOption return ProjectOption.objects.get_value(self, *args, **kwargs)