You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:03:40