class AllFields(models.Model): bigintegerfield = models.BigIntegerField() binaryfield = models.BinaryField() booleanfield = models.BooleanField() charfield = models.CharField() commaseparatedintegerfield = models.CommaSeparatedIntegerField() datefield = models.DateField() datetimefield = models.DateTimeField() decimalfield = models.DecimalField() durationfield = models.DurationField() emailfield = models.EmailField() filefield = models.FileField() filepathfield = models.FilePathField() floatfield = models.FloatField() genericipaddressfield = models.GenericIPAddressField() ipaddressfield = models.IPAddressField() imagefield = models.ImageField() integerfield = models.IntegerField() nullbooleanfield = models.NullBooleanField() positiveintegerfield = models.PositiveIntegerField() positivesmallintegerfield = models.PositiveSmallIntegerField() slugfield = models.SlugField() smallintegerfield = models.SmallIntegerField() textfield = models.TextField() timefield = models.TimeField() urlfield = models.URLField() uuidfield = models.UUIDField() arrayfield = ps_fields.ArrayField(models.CharField()) cicharfield = ps_fields.CICharField() ciemailfield = ps_fields.CIEmailField() citextfield = ps_fields.CITextField() hstorefield = ps_fields.HStoreField() class Meta: app_label = "tests"
class DataStore(TimeStampedModel): name = pg_fields.CICharField(max_length=200) version = models.IntegerField(default=1) uuid = models.UUIDField(unique=True, db_index=True, default=uuid.uuid4, editable=False) data = pg_fields.JSONField(default=dict) cleaned_data = pg_fields.JSONField(default=dict) fields = pg_fields.ArrayField(models.CharField(max_length=200), default=list) field_tracker = FieldTracker(fields=['data', 'cleaned_data', 'fields']) author_type = models.ForeignKey( ContentType, db_constraint=False, on_delete=models.PROTECT, related_name="%(app_label)s_%(class)s_authored", ) author_id = models.CharField(max_length=128) author = GenericForeignKey('author_type', 'author_id') objects = DataStoreManager() all_objects = models.Manager() class Meta: abstract = True def save(self, *args, **kwargs): request = get_request() if not self.pk: if request: if not request.session.session_key: request.session.save() session_object = request.session._get_session_from_db() self.author_type_id = ContentType.objects.get_for_model(session_object._meta.model).id self.author_id = session_object.pk return super().save(*args, **kwargs)
class Contact(BasicModel, BIDModel): """ 联系人 """ class Meta: verbose_name = 'Contact' verbose_name_plural = verbose_name unique_together = ('usrid', 'touchid') db_table = 'k_cv_contact' ordering = ('-updated_at',) show_limit = 20 # 联系人展示记录条数 convid = models.UUIDField('会话', db_index=True) usrid = models.BigIntegerField('用户', db_index=True) touchid = models.BigIntegerField('对方', db_index=True) unread = models.PositiveSmallIntegerField('未读消息量', default=0) read_at = models.DateTimeField('最后阅读', null=True, default=None) # 标记已读 last_msg = models.JSONField('最新消息内容', help_text='', default=dict) last_at = models.DateTimeField('最新消息时间', db_index=True, null=True, default=None) keywords = fields.CICharField('检索关键字', max_length=255, db_index=True, default='') is_block = models.BooleanField('屏蔽对方', default=False) remark = models.CharField('备注', max_length=50, default='') objects = ContactManager() @property def other_info(self): """ 对方联系人信息 """ inst = self.__class__.objects.get( usrid=self.touchid, touchid=self.usrid ) return inst @property def is_blocked(self): """ 是否被屏蔽 """ is_block = self.other_info.is_block return is_block @property def user(self): inst = self.get_user(self.usrid) return inst @property def touch_info(self): inst = self.get_user(self.touchid) return inst @property def conv_info(self): inst = Conversation.objects.get(convid=self.convid) return inst @property def unread_msg_qs(self): """ 未读消息列表 """ qs = self.conv_info.msg_qs.filter( read_at__isnull=True, ).exclude(sender=self.usrid) return qs @property def last_timer(self): """ 最新消息显示时间值 """ if not self.last_at: return '' desc = deal_time.show_humanize_simple(self.last_at) return desc @property def last_memo(self): """ 最新消息,含称谓转换 """ memo = self.last_msg.get('memo', '') return memo def set_block(self, is_block): self.is_block = is_block self.save(update_fields=['is_block', 'updated_at']) self.extra_log('block', block=self.is_block) def up_unread(self): """ 更新未读消息量 """ self.unread = self.unread_msg_qs.count() self.save(update_fields=['unread', 'updated_at']) def open_conv(self): """ 打开会话 """ self.mark_read() def mark_read(self): """ 标记已读 """ now = deal_time.get_now() if self.unread == 0: logger.info(f'contact__marked_read {self.usrid}') return for msg in self.unread_msg_qs: msg.mark_read(self.usrid, now) self.unread, self.read_at = 0, now self.save(update_fields=['unread', 'read_at', 'updated_at']) self.rtm_event_open_conv() # 更新不同设备未读消息量 def rtm_event_open_conv(self): """ 打开会话,同步客户端,发送至RTM """ # 1. 更新接接收者不同设备会话列表未读消息量 # 2. 更新发送者对话框消息是否已读状态 rtm_e = mc.LCEvent.OpenConv user_tid = pk_hashid_encode(self.usrid) touch_tid = pk_hashid_encode(self.touchid) content = dict(evt=rtm_e, cid=self.convid, usrtid=user_tid) agora_rtm_send_peer(content, [user_tid, touch_tid]) def add_keyword(self, word): """ 添加索引关键词 """ word = str(word).replace('|', '') word = word.replace(' ', '').strip() if (not word) or (word in self.keywords): return self.keywords += f'|{word}' self.save(update_fields=['keywords', 'updated_at']) def up_remark(self, remark): """ 修改备注 """ self.remark = remark self.save(update_fields=['remark', 'updated_at']) self.add_keyword(remark) def check_last_msg(self): """ 冗余最新消息,用于最近联系人列表显示 """ last_msg = self.conv_info.last_msg assert isinstance(last_msg, Message) msg_memo = last_msg.trigger_content(self.usrid) is_self = self.usrid == last_msg.sender memo = filter_newlines(msg_memo, ' ') self.last_msg = dict( memo=memo, self=is_self, id=last_msg.pk, by=last_msg.sender, ) self.last_at = last_msg.created_at self.save(update_fields=['last_at', 'last_msg', 'updated_at'])
class Service(models.Model): class Meta: unique_together = ("owner", "name") owner = pg_fields.CICharField(max_length=100) name = pg_fields.CICharField(max_length=100) status = models.CharField( choices=((item.value, item.value) for item in Status), null=True, blank=True, max_length=100, ) impact = models.CharField( choices=((item.value, item.value) for item in Impact), null=True, blank=True, max_length=100, ) datacenter = models.ForeignKey( "DataCenter", on_delete=models.PROTECT, null=True, blank=True ) slack_channel = models.CharField(max_length=22, null=True, blank=True) sentry_project = models.CharField(max_length=100, null=True, blank=True) sonarqube_project = models.CharField(max_length=250, null=True, blank=True) rating_grade = models.CharField(max_length=1, null=True, blank=True) rating_reason = models.CharField(max_length=250, null=True, blank=True) repository = models.ForeignKey( "repos.Repository", on_delete=models.PROTECT, null=True, blank=True ) pagerduty_url = models.URLField(max_length=500, null=True, blank=True) dashboard_url = models.URLField(max_length=500, null=True, blank=True) docs_url = models.URLField(max_length=500, null=True, blank=True) service_url = models.URLField(max_length=500, null=True, blank=True) health_check_url = models.URLField(max_length=500, null=True, blank=True) owner_slug = models.SlugField(max_length=140) name_slug = models.SlugField(max_length=140) tags = pg_fields.ArrayField( base_field=models.CharField(max_length=50), blank=True, default=list ) def get_absolute_url(self): return reverse("service_detail", args=[self.owner_slug, self.name_slug]) def rate_according_to_sentry(self): Category = SentryIssueCategory queryset = self.sentry_issues.prefetch_related("stats").all() if not queryset.exists(): return { "grade": "S", "reason": "No issues at all 🎉 You, my friends, are doing an amazing job 😎", } three_days_ago = arrow.now().shift(days=-3).day is_recent = models.Q(stats__timestamp__day__gte=three_days_ago) queryset = queryset.annotate(freq=models.Sum("stats__count", filter=is_recent)) avg_daily_events_count = queryset.aggregate(models.Sum("freq"))["freq__sum"] / 3 issues = SentryIssueCounts( total=queryset.count(), problematic=queryset.exclude(category=Category.FRESH.value).count(), spoiled=queryset.filter(category=Category.SPOILED.value).count(), decaying=queryset.filter(category=Category.DECAYING.value).count(), stale=queryset.filter(category=Category.STALE.value).count(), ) return ratings.SentryRater(avg_daily_events_count, issues).get_rating() def update_rating(self): sentry_rating = self.rate_according_to_sentry() if self.sentry_project else None if sentry_rating: self.rating_grade = sentry_rating["grade"] self.rating_reason = sentry_rating["reason"] self.full_clean() self.save() @property def key(self): return f"{self.owner}/{self.name}" @property def owner_url(self): if self.repository: return f"{settings.GITLAB_URL}/{self.repository.owner}" @property def slack_url(self): if self.slack_channel: return f"{settings.SLACK_URL}/messages/{self.slack_channel}" @property def gitlab_url(self): if self.repository: return ( f"{settings.GITLAB_URL}/{self.repository.owner}/{self.repository.name}" ) def __str__(self): return f"{self.key}"
class Library(models.Model): class Meta: unique_together = ("owner", "name") verbose_name_plural = "libraries" owner = pg_fields.CICharField(max_length=100) name = pg_fields.CICharField(max_length=100) status = models.CharField( choices=((item.value, item.value) for item in Status), null=True, blank=True, max_length=100, ) impact = models.CharField( choices=((item.value, item.value) for item in Impact), null=True, blank=True, max_length=100, ) slack_channel = models.CharField(max_length=22, null=True, blank=True) sonarqube_project = models.CharField(max_length=250, null=True, blank=True) repository = models.ForeignKey( "repos.Repository", on_delete=models.PROTECT, null=True, blank=True, related_name="libraries", ) docs_url = models.URLField(max_length=500, null=True, blank=True) library_url = models.URLField(max_length=500, null=True, blank=True) owner_slug = models.SlugField(max_length=140) name_slug = models.SlugField(max_length=140) tags = pg_fields.ArrayField(base_field=models.CharField(max_length=50), blank=True, default=list) def get_absolute_url(self): return reverse("library_detail", args=[self.owner_slug, self.name_slug]) @property def key(self): return f"{self.owner}/{self.name}" @property def owner_url(self): if self.repository: return f"{settings.GITLAB_URL}/{self.repository.owner}" @property def gitlab_url(self): if self.repository: return ( f"{settings.GITLAB_URL}/{self.repository.owner}/{self.repository.name}" ) @property def slack_url(self): if self.slack_channel: return f"{settings.SLACK_URL}/messages/{self.slack_channel}" def __str__(self): return f"{self.key}"