1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# 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 "<ColumnTab:%d:%s>" % (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 "<Columnist:%d:%s>" % (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 "<Article:%d:%s>" % (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'