Skip to content

Commit 4fc11a5

Browse files
authored
Merge pull request #370 from py-thok/develop
feat(article): add article ranking
2 parents 88735f7 + c1d5789 commit 4fc11a5

File tree

7 files changed

+3597
-5
lines changed

7 files changed

+3597
-5
lines changed

hinghwa-dict-backend/HinghwaDict/settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@
318318
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
319319
"LOCATION": "pronunciation_ranking_cache_table",
320320
},
321+
"article_ranking": {
322+
"TIMEOUT": 900,
323+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
324+
"LOCATION": "article_ranking_cache_table",
325+
},
321326
}
322327
SIMPLEUI_LOGO = "https://hinghwa.cn/img/blue.7169aa26.svg"
323328
SIMPLEUI_HOME_INFO = False

hinghwa-dict-backend/article/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
path("/comments/<int:id>/like", csrf_exempt(LikeComment.as_view())),
1414
path("/comments/<int:id>", csrf_exempt(CommentDetail.as_view())),
1515
path("/comments", csrf_exempt(SearchComment.as_view())),
16+
path("/ranking", csrf_exempt(ArticleRanking.as_view())), # AT0203文章榜单
1617
]

hinghwa-dict-backend/article/views.py

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import demjson3
2+
import datetime
23
from django.http import JsonResponse
34
from django.utils import timezone
45
from django.views.decorators.csrf import csrf_exempt
@@ -11,9 +12,12 @@
1112
sendNotification,
1213
)
1314
from .forms import ArticleForm, CommentForm
15+
from django.db.models import Q, Count, Max
16+
from user.dto.user_simple import user_simple
1417
from .models import Article, Comment
1518
from django.conf import settings
1619
from .dto.article_all import article_all
20+
from django.core.cache import caches
1721
from .dto.article_normal import article_normal
1822
from .dto.comment_normal import comment_normal
1923
from .dto.comment_likes import comment_likes
@@ -22,7 +26,9 @@
2226
from utils.exception.types.bad_request import (
2327
BadRequestException,
2428
ReturnUsersNumException,
29+
RankWithoutDays,
2530
)
31+
from django.core.paginator import Paginator
2632
from utils.exception.types.not_found import (
2733
ArticleNotFoundException,
2834
CommentNotFoundException,
@@ -78,7 +84,7 @@ def post(self, request) -> JsonResponse:
7884
article.update_time = timezone.now()
7985
article.author = user
8086
article.save()
81-
content = f"我创建了文章(id={article.id}),请及时去审核"
87+
content = f"我创建了文章(id={article.id}),请及时审核"
8288
sendNotification(
8389
article.author,
8490
None,
@@ -372,3 +378,106 @@ def return_users_num_pass(self, request):
372378
raise ReturnUsersNumException()
373379
return int(request.GET["return_users_num"])
374380
return None
381+
382+
383+
class ArticleRanking(View):
384+
# AT0203 文章上传榜单
385+
def get(self, request) -> JsonResponse:
386+
days = request.GET["days"] # 要多少天的榜单
387+
page = request.GET.get("page", 1) # 获取页面数,默认为第1页
388+
pagesize = request.GET.get("pageSize", 10) # 获取每页显示数量,默认为10条
389+
if not days:
390+
raise RankWithoutDays()
391+
days = int(days)
392+
try:
393+
token = token_pass(request.headers)
394+
user: User = token_user(token)
395+
my_id = user.id
396+
except:
397+
my_id = 0
398+
my_amount = 0
399+
my_rank = 0
400+
rank_count = 0
401+
result_json_list = []
402+
paginator = Pages(self.get_rank_queries(days), pagesize)
403+
current_page = paginator.get_page(page)
404+
adjacent_pages = list(
405+
paginator.get_adjacent_pages(current_page, adjancent_pages=3)
406+
)
407+
408+
for rank_q in self.get_rank_queries(days):
409+
con_id = rank_q["author_id"]
410+
amount = rank_q["article_count"]
411+
rank_count = rank_count + 1
412+
if con_id == my_id:
413+
my_amount = amount
414+
my_rank = rank_count
415+
result_json_list.append(
416+
{
417+
"author": user_simple(User.objects.filter(id=con_id)[0]),
418+
"amount": amount,
419+
}
420+
)
421+
# 发送给前端
422+
return JsonResponse(
423+
{
424+
"ranking": result_json_list,
425+
"me": {"amount": my_amount, "rank": my_rank},
426+
"pagination": {
427+
"total_pages": paginator.num_pages,
428+
"current_page": current_page.number,
429+
"page_size": pagesize,
430+
"previous_page": current_page.has_previous(),
431+
"next_page": current_page.has_next(),
432+
"adjacent_pages": adjacent_pages,
433+
},
434+
},
435+
status=200,
436+
)
437+
438+
@classmethod
439+
def get_rank_queries(cls, days):
440+
rank_cache = caches["article_ranking"]
441+
rank_queries = rank_cache.get(str(days))
442+
if rank_queries is None:
443+
# 发现缓存中没有要查询的天数的榜单,更新榜单,并把更新的表格录入到数据库缓存中article_ranking表的对应位置
444+
rank_queries = cls.update_rank(days)
445+
rank_cache.set(str(days), rank_queries)
446+
return rank_queries
447+
448+
@classmethod
449+
def update_rank(cls, search_days): # 不包括存储在数据库中
450+
if search_days != 0:
451+
start_date = timezone.now() - datetime.timedelta(days=search_days)
452+
# 查询发布时间在规定开始时间之后的
453+
result = (
454+
Article.objects.filter(
455+
Q(publish_time__gt=start_date) & Q(visibility=True)
456+
)
457+
.values("author_id")
458+
.annotate(
459+
article_count=Count("author_id"),
460+
last_date=Max("publish_time"),
461+
)
462+
.order_by("-article_count", "-last_date")
463+
)
464+
else:
465+
result = (
466+
Article.objects.filter(visibility=True)
467+
.values("author_id")
468+
.annotate(
469+
article_count=Count("author_id"),
470+
last_date=Max("publish_time"),
471+
)
472+
.order_by("-article_count", "-last_date")
473+
)
474+
return result # 返回的是Queries
475+
476+
477+
class Pages(Paginator):
478+
# 对原有的Paginator类进行扩展,获取当前页的相邻页面
479+
def get_adjacent_pages(self, current_page, adjancent_pages=3):
480+
current_page = current_page.number
481+
start_page = max(current_page - adjancent_pages, 1) # 前面的页码数
482+
end_page = min(current_page + adjancent_pages, self.num_pages) # 后面的页码数
483+
return range(start_page, end_page + 1)

hinghwa-dict-backend/utils/exception/types/bad_request.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ def __init__(self, msg="可用测试题不足"):
3030
super().__init__(msg)
3131

3232

33-
class PronunciationRankWithoutDays(BadRequestException):
33+
class RankWithoutDays(BadRequestException):
3434
"""
3535
发音排名请求没有发送天数异常
3636
"""
3737

38-
def __init__(self, msg="发音排名请求没有发送天数"):
38+
def __init__(self, msg="排名请求没有发送天数"):
3939
super().__init__(msg)
4040

4141

hinghwa-dict-backend/word/pronunciation/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from user.dto.user_simple import user_simple
2020
from utils.exception.types.bad_request import (
2121
BadRequestException,
22-
PronunciationRankWithoutDays,
22+
RankWithoutDays,
2323
InvalidPronunciation,
2424
)
2525
from utils.exception.types.not_found import (
@@ -498,7 +498,7 @@ def get(self, request) -> JsonResponse:
498498
page = request.GET.get("page", 1) # 获取页面数,默认为第1页
499499
pagesize = request.GET.get("pageSize", 10) # 获取每页显示数量,默认为10条
500500
if not days:
501-
raise PronunciationRankWithoutDays()
501+
raise RankWithoutDays()
502502
days = int(days)
503503
try:
504504
token = token_pass(request.headers)

0 commit comments

Comments
 (0)