# coding=utf8 from __future__ import unicode_literals, absolute_import, print_function from django.db import models from django.conf import settings from django.utils.functional import cached_property from gm_types.gaia import TOPIC_TYPE from . import Problem from . import TopicImage from talos.services import UserService from talos.services.tag import TagService from utils.exceptions import Impossible class ColumnTab(models.Model): """ 更美专栏tab """ class Meta: verbose_name = '专栏tab' verbose_name_plural = '专栏tab' db_table = 'api_columntab' app_label = 'talos' name = models.CharField(default='', max_length=10, null=True, blank=True, verbose_name=u'专栏tab名') is_online = models.BooleanField(default=True, verbose_name=u"是否有效") order = models.IntegerField(default=0, blank=True, verbose_name=u"tab序号", help_text=u"小的排在前,大的排在后") created_time = models.DateTimeField(auto_now_add=True, verbose_name=u"tab创建时间") last_modified = models.DateTimeField(auto_now=True, verbose_name=u"最后修改时间", null=True) def __unicode__(self): return "" % (self.id, self.name) @cached_property def tags(self): ts = ColumnTabTag.objects.filter(column_tab=self).values_list('tag_id', flat=True) _tags = TagService.get_tags_by_tag_ids(list(ts)) return _tags or [] @classmethod def tabs(cls): ts = ColumnTab.objects.filter(is_online=True).order_by('order') return ts @classmethod def get_tab_by_id(cls, tab_id): try: return ColumnTab.objects.get(id=tab_id) except ColumnTab.DoesNotExist: return None @property def data(self): _format = '%Y-%m-%d %H:%M:%S' return { 'id': self.id, 'name': self.name, 'order': self.order, 'created_time': self.created_time.strftime(_format), 'last_modified': self.last_modified.strftime(_format), } @property def articles(self): tab_tags = ColumnTabTag.objects.filter(column_tab=self.id).values_list('tag_id', flat=True) articles = Problem.objects.filter( is_online=True, topic_type__in=[TOPIC_TYPE.COLUMN_ARTICLE, TOPIC_TYPE.USER_ARTICLE], problemtag__tag_id__in=tab_tags ).distinct().order_by('-last_modified') return articles @property def articles_exists(self): tab_tags = ColumnTabTag.objects.filter(column_tab=self.id).values_list('tag_id', flat=True) est = Problem.objects.filter( is_online=True, topic_type__in=[TOPIC_TYPE.COLUMN_ARTICLE, TOPIC_TYPE.USER_ARTICLE], problemtag__tag_id__in=tab_tags ).exists() return est class ColumnTabTag(models.Model): """ 专栏tab-关联-tag """ class Meta: app_label = 'talos' db_table = 'api_columntabtag' column_tab = models.ForeignKey(ColumnTab) tag_id = models.IntegerField(verbose_name=u"关联的tag_id") def __unicode__(self): return "%s:%d" % (self.tag_id, self.column_tab.id) @classmethod def create_bind(cls, column_tab_id, tag_id): tab_exists = ColumnTab.objects.filter(id=column_tab_id).exists() tag_exists = TagService.get_tag_by_tag_id(id=tag_id) is not None if tab_exists and tag_exists: tt = cls() tt.column_tab_id = column_tab_id tt.tag_id = tag_id tt.save() return True else: return False class Columnist(models.Model): """ 专栏作者 """ class Meta: verbose_name = '专栏作者' verbose_name_plural = '专栏作者' db_table = 'api_columnist' app_label = 'talos' user_id = models.IntegerField(default=0, null=True, db_index=True, unique=True, verbose_name=u"关联的User表id") introduction = models.CharField(default='', max_length=50, blank=True, null=True, verbose_name=u'专栏作者简介') profession = models.CharField(default='', max_length=20, blank=True, null=True, verbose_name=u'专栏作者职业') is_online = models.BooleanField(default=True, verbose_name=u"是否在线") def __unicode__(self): return "" % (self.id, self.user_id) class ArticleCard(models.Model): """ 专栏文章关联卡片(美购,医生,医院) """ class Meta: verbose_name = '专栏文章关联卡片' verbose_name_plural = '专栏文章关联卡片' db_table = 'api_columncard' app_label = 'talos' article = models.ForeignKey(Problem) service_id = models.IntegerField(default=None, null=True, db_index=True, verbose_name=u"关联的美购id") doctor_id = models.CharField(default=None, max_length=100, null=True, db_index=True, verbose_name=u"关联的医生id") hospital_id = models.CharField(default=None, max_length=100, null=True, db_index=True, verbose_name=u"关联的医院id") diary_id = models.IntegerField(default=None, null=True, verbose_name=u"关联的日记本id") answer_id = models.IntegerField(default=None, null=True, db_index=True, verbose_name=u'关联的回答') rankboard_id = models.IntegerField(default=None, null=True, db_index=True, verbose_name=u'关联榜单') class Article(models.Model): """ 文章关联(目前支持专栏文章、优质用户文章) """ class Meta: verbose_name = '文章关联' verbose_name_plural = '文章关联' db_table = 'api_article' app_label = 'talos' article_id = models.IntegerField(default=None, unique=True, null=True, verbose_name=u"一一对应的帖子中文章") article_type = models.CharField(max_length=10, null=False, verbose_name=u'文章类型', default=TOPIC_TYPE.USER_ARTICLE, choices=TOPIC_TYPE, db_index=True) is_online = models.BooleanField(default=True, help_text=u"是否可以上线", verbose_name=u"上线", db_index=True) created_time = models.DateTimeField(auto_now_add=True, verbose_name=u"创建时间") last_modified = models.DateTimeField(auto_now=True, verbose_name=u"最后修改时间", null=True) def __unicode__(self): return "" % (self.id, self.article_id) @property def data(self): image = TopicImage.objects.filter(topic=self.article_id, is_cover=True) topic = Problem.objects.filter(id=self.article_id, is_online=True) user_id = topic[0].user_id if topic else None columnist = Columnist.objects.filter(user_id=user_id, is_online=True) if user_id else None user = UserService.get_user_by_user_id(user_id=user_id) if user_id else None title = topic[0].title if topic else "" content = topic[0].ask if topic else "" return { 'reply_num': topic[0].reply_num if topic else 0, 'portrait': user.portrait if user else '', 'article_id': self.article_id, 'head_image': image[0].get_image_data() if image else None, # 封面 'area': user.city_name if user else None, # 作者坐标 'introduction': columnist[0].introduction if columnist else '', # 作者简介 'user_id': user.id if user else -1, 'title': title, 'is_voted': topic[0].is_voted(user_id) if topic else False, 'vote_num': topic[0].vote_amount if topic else 0, 'view_num': topic[0].view_amount if topic else 0, 'content': content, 'user_level': { 'membership_icon': user.membership_icon if user else '', 'level_icon': user.level_icon if user else '', 'constellation_icon': user.constellation_icon if user else '' }, 'nickname': user.nickname if user else '', # 作者昵称 'user_name': user.nickname if user else '', # 作者昵称 'images': [item.get_image_data() for item in image] } @classmethod def last_articles(cls, article_type_list, num): _max_num = 50 if num > _max_num: num = _max_num last_articles = Article.objects.filter(article_type__in=article_type_list, is_online=True)[:num] return last_articles def _content_score(self, topic): if topic.is_push: return 100 else: return 20 def _reply_score(self, topic): reply_num = topic.reply_num if reply_num == 0: return 0 elif 1 <= reply_num <= 30: return 50 elif 31 <= reply_num: return 100 else: raise Exception("impossible") def _like_score(self, topic): like_num = topic._get_vote_amount_of_id(topic.id) if like_num == 0: return 0 elif 1 <= like_num <= 10: return 50 elif 11 <= like_num: return 100 else: raise Impossible def _time_score(self): created_date = self.created_time.date() delta = created_date - settings.FOUNDING_DAY return delta.days def topic(self): topics = Problem.objects.filter(id=self.article_id, is_online=True) return topics[0] if topics else None def smart_rank(self): topic = self.topic() if topic is None: return 0 content_score = self._content_score(topic) social_score = settings.SOCIAL_REPLY_WEIGHT * self._reply_score(topic) + \ settings.SOCIAL_LIKE_WEIGHT * self._like_score(topic) rank = settings.CONTENT_WEIGHT * content_score + \ settings.SOCIAL_WEIGHT * social_score + \ settings.TIME_WEIGHT * self._time_score() return rank class ArticleAsk(models.Model): """ 文章关联(目前支持专栏文章、优质用户文章) """ class Meta: verbose_name = '文章关联' verbose_name_plural = '文章关联' db_table = 'api_problem' app_label = 'talos'