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

如何实现Django中评论对象与关联TV数据的同时展示?

问题

我需要展示用户评论,同时通过评论对象中的tv_id查询并展示对应的TV数据。每条评论都关联tv_id,但目前不知道如何在HTML中同时展示评论和对应的TV数据,求实现方法。

当前代码

模型定义

class TV(models.Model):
    id = models.CharField(primary_key=True, editable=False,
                          validators=[alphanumeric],max_length = 9999)
    stars = models.FloatField(
                    blank=False,
                    null=False,
                    default=0, 
                    validators=[MinValueValidator(0.0),
                     MaxValueValidator(10.0)]
                     )
    def get_comments(self):
        return Comment_tv.objects.filter(tv_id=self.id)
    
    def average_stars(self):
        comments = self.get_comments()
        n_comments = comments.count()

        if n_comments:
            self.stars = sum([comment.stars for comment in comments]) / n_comments
        else:
            self.stars = 0
        return self.stars

class Comment_tv(models.Model):
    comment     = models.TextField(max_length=1000)
    stars       = models.FloatField(
                     blank=False,
                     null=False,
                     default=0, 
                     validators=[MinValueValidator(0.0),
                     MaxValueValidator(10.0)]
                  )

    user        = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    tv          = models.ForeignKey(TV, on_delete=models.CASCADE)
    created_at  = models.DateTimeField(auto_now_add=True)
    updated_at  = models.DateTimeField(auto_now=True)
    
    class Meta:
        unique_together = ('user', 'tv')
        indexes = [
        models.Index(fields=['user', 'tv']),
        ]

TMDB API调用代码

data = requests.get(f"https://api.themoviedb.org/3/tv/{tv_id}?api_key={TMDB_API_KEY}&language=en-US")

视图定义

class Comment_List_TV(ListView):
      template_name = 'account/user_comment_list_tv.html'
      def get_queryset(self):
            Comment_list_query = Comment_tv.objects.none()
            if self.request.user.is_authenticated:
                  Comment_list_query = Comment_tv.objects.filter(user=self.request.user)
            return Comment_list_query
解决方案

1. 优化查询,预关联TV对象

修改视图的get_queryset方法,使用select_related预取关联的TV对象,避免N+1数据库查询问题:

class Comment_List_TV(ListView):
    template_name = 'account/user_comment_list_tv.html'
    def get_queryset(self):
        if self.request.user.is_authenticated:
            # 预取关联的TV模型数据,减少数据库查询次数
            return Comment_tv.objects.filter(user=self.request.user).select_related('tv')
        return Comment_tv.objects.none()

2. 获取TMDB TV数据(两种可选方式)

方式一:视图批量获取(推荐,减少API调用次数)

在视图的get_context_data中批量获取所有评论对应的TMDB数据,并存入上下文供模板使用:

import requests
from django.conf import settings

class Comment_List_TV(ListView):
    template_name = 'account/user_comment_list_tv.html'
    def get_queryset(self):
        if self.request.user.is_authenticated:
            return Comment_tv.objects.filter(user=self.request.user).select_related('tv')
        return Comment_tv.objects.none()
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        comments = context['object_list']
        # 收集所有需要查询的TV ID
        tv_ids = [comment.tv.id for comment in comments]
        tmdb_data_map = {}
        
        for tv_id in tv_ids:
            try:
                response = requests.get(
                    f"https://api.themoviedb.org/3/tv/{tv_id}?api_key={settings.TMDB_API_KEY}&language=en-US"
                )
                response.raise_for_status()
                tmdb_data_map[tv_id] = response.json()
            except requests.exceptions.RequestException:
                # 处理请求异常,比如网络错误、API限流等
                tmdb_data_map[tv_id] = None
        
        context['tmdb_data_map'] = tmdb_data_map
        return context

方式二:模型方法获取(适合单条评论场景)

在TV模型中添加方法获取TMDB数据,并加入缓存避免重复请求:

from django.core.cache import cache
import requests
from django.conf import settings

class TV(models.Model):
    # 原有字段和方法...
    
    def get_tmdb_data(self):
        cache_key = f'tv_tmdb_info_{self.id}'
        data = cache.get(cache_key)
        if not data:
            try:
                response = requests.get(
                    f"https://api.themoviedb.org/3/tv/{self.id}?api_key={settings.TMDB_API_KEY}&language=en-US"
                )
                response.raise_for_status()
                data = response.json()
                # 缓存1小时,可根据需求调整时长
                cache.set(cache_key, data, 3600)
            except requests.exceptions.RequestException:
                data = None
        return data

3. 模板中展示评论与TV数据

对应方式一的模板代码

{% for comment in object_list %}
    <div class="comment-card">
        <div class="comment-content">
            <p>评分:{{ comment.stars }}</p>
            <p>评论:{{ comment.comment }}</p>
            <p>评论时间:{{ comment.created_at|date:"Y-m-d H:i" }}</p>
        </div>
        <div class="tv-info">
            {% with tv_info=tmdb_data_map[comment.tv.id] %}
                {% if tv_info %}
                    <h3>{{ tv_info.name }}</h3>
                    <p>{{ tv_info.overview|truncatechars:200 }}</p>
                    {% if tv_info.poster_path %}
                        <img src="https://image.tmdb.org/t/p/w200{{ tv_info.poster_path }}" alt="{{ tv_info.name }}">
                    {% endif %}
                {% else %}
                    <p>无法获取该TV的详细信息</p>
                {% endif %}
            {% endwith %}
        </div>
    </div>
{% empty %}
    <p>暂无评论</p>
{% endfor %}

对应方式二的模板代码

{% for comment in object_list %}
    <div class="comment-card">
        <div class="comment-content">
            <p>评分:{{ comment.stars }}</p>
            <p>评论:{{ comment.comment }}</p>
            <p>评论时间:{{ comment.created_at|date:"Y-m-d H:i" }}</p>
        </div>
        <div class="tv-info">
            {% with tv_info=comment.tv.get_tmdb_data %}
                {% if tv_info %}
                    <h3>{{ tv_info.name }}</h3>
                    <p>{{ tv_info.overview|truncatechars:200 }}</p>
                    {% if tv_info.poster_path %}
                        <img src="https://image.tmdb.org/t/p/w200{{ tv_info.poster_path }}" alt="{{ tv_info.name }}">
                    {% endif %}
                {% else %}
                    <p>无法获取该TV的详细信息</p>
                {% endif %}
            {% endwith %}
        </div>
    </div>
{% empty %}
    <p>暂无评论</p>
{% endfor %}

额外优化建议

  • 对TMDB API请求添加缓存,避免重复调用,降低API限流风险
  • 增加异常处理逻辑,比如记录API请求错误日志
  • 如果评论数量较多,添加分页功能提升页面加载性能

内容的提问来源于stack exchange,提问作者user19553515

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 21:27:12