基于django-disqus实现按评论数排序食谱查询集的技术求助
按Disqus评论量排序食谱的解决方案
嘿,我明白你现在的困扰——想用django-disqus给Recipe模型做评论量最高的排序,但ORM里没法直接关联Disqus的评论数据对吧?我给你几个实用的方案,一步步来:
方案一:本地缓存评论数(推荐,性能最优)
这个方法是把Disqus的评论数同步到你的Recipe模型字段里,之后排序就和普通Django查询一样简单了,还能避免频繁调用API的性能问题。
1. 给Recipe模型加评论数字段
先在你的models.py里给Recipe加一个存储评论数的字段:
from django.db import models class Recipe(models.Model): # 你的现有字段... title = models.CharField(max_length=200) # 新增评论数字段 disqus_comment_count = models.IntegerField(default=0, editable=False) def get_absolute_url(self): # 确保这个方法返回食谱的完整URL(Disqus就是靠这个关联线程的) return reverse('recipe_detail', args=[str(self.id)])
之后记得执行python manage.py makemigrations和python manage.py migrate来更新数据库。
2. 写一个定时同步评论数的管理命令
创建一个自定义Django管理命令,用来定期从Disqus API拉取评论数并更新到本地字段。
首先在你的app下创建management/commands目录,然后新建sync_disqus_comments.py文件:
import requests from django.core.management.base import BaseCommand from django.conf import settings from yourapp.models import Recipe class Command(BaseCommand): help = '同步Disqus评论数到Recipe模型' def handle(self, *args, **options): # 替换成你的Disqus信息 DISQUS_API_KEY = settings.DISQUS_API_KEY DISQUS_FORUM_SHORTNAME = settings.DISQUS_FORUM_SHORTNAME # 调用Disqus的listThreads接口,获取所有线程数据 url = f"https://disqus.com/api/3.0/threads/list.json" params = { 'api_key': DISQUS_API_KEY, 'forum': DISQUS_FORUM_SHORTNAME, 'limit': 100, # 一次最多拉100条,多的话需要分页处理 'order': 'commentCount', 'sort': 'desc' } response = requests.get(url, params=params) threads = response.json().get('response', []) # 遍历线程,匹配对应的Recipe并更新评论数 for thread in threads: thread_url = thread.get('link') # 从URL中提取Recipe的ID(这里需要根据你的URL规则调整) # 比如你的URL是https://example.com/recipes/123/,那可以拆分获取123 try: recipe_id = int(thread_url.split('/')[-2]) recipe = Recipe.objects.get(id=recipe_id) recipe.disqus_comment_count = thread.get('commentCount', 0) recipe.save() self.stdout.write(f"更新食谱 {recipe.title} 评论数为 {thread.get('commentCount')}") except Recipe.DoesNotExist: self.stdout.write(f"未找到对应URL的食谱: {thread_url}")
然后在settings.py里配置你的Disqus密钥和论坛短名:
DISQUS_API_KEY = "你的Disqus API密钥" DISQUS_FORUM_SHORTNAME = "你的论坛短名"
之后你可以手动执行python manage.py sync_disqus_comments来同步,也可以用系统定时任务(比如Linux的cron)定期执行,比如每天同步一次。
3. 在视图中按评论数排序
现在排序就非常简单了,直接用Django的ORM查询:
from django.views.generic import ListView from yourapp.models import Recipe class MostCommentedRecipesView(ListView): model = Recipe template_name = 'recipes/most_commented.html' context_object_name = 'recipes' # 按评论数倒序排列,取前N条的话可以加[:10] queryset = Recipe.objects.order_by('-disqus_comment_count')
方案二:实时拉取API排序(适合小流量站点)
如果不想存本地,也可以在视图里实时拉取Disqus的线程数据,和本地Recipe查询集结合后排序,但注意要加缓存避免重复调用API:
import requests from django.conf import settings from django.views.generic import ListView from django.core.cache import cache from yourapp.models import Recipe class MostCommentedRecipesView(ListView): template_name = 'recipes/most_commented.html' context_object_name = 'recipes' def get_queryset(self): # 先尝试从缓存取评论数据 disqus_threads = cache.get('disqus_most_commented_threads') if not disqus_threads: # 缓存不存在,调用API url = f"https://disqus.com/api/3.0/threads/list.json" params = { 'api_key': settings.DISQUS_API_KEY, 'forum': settings.DISQUS_FORUM_SHORTNAME, 'limit': 20, 'order': 'commentCount', 'sort': 'desc' } response = requests.get(url, params=params) disqus_threads = response.json().get('response', []) # 缓存1小时 cache.set('disqus_most_commented_threads', disqus_threads, 3600) # 从线程数据中提取Recipe ID,获取对应的食谱对象 recipe_ids = [] thread_comment_counts = {} for thread in disqus_threads: thread_url = thread.get('link') try: recipe_id = int(thread_url.split('/')[-2]) recipe_ids.append(recipe_id) thread_comment_counts[recipe_id] = thread.get('commentCount', 0) except ValueError: continue # 获取食谱并按评论数排序 recipes = list(Recipe.objects.filter(id__in=recipe_ids)) recipes.sort(key=lambda x: thread_comment_counts.get(x.id, 0), reverse=True) return recipes
注意事项
- 记得去Disqus开发者平台申请API密钥,确保权限足够访问listThreads接口
- 注意Disqus API的请求限制,避免频繁调用导致被限流
- 方案一中的URL解析逻辑要根据你自己的站点URL规则调整,确保能正确从Disqus线程的link字段匹配到对应的Recipe
内容的提问来源于stack exchange,提问作者SalahAdDin
相关产品推荐
相关产品推荐

