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

Django类视图预处理模板数据:批量转换广告时间戳为相对时间

问题根因

原有代码存在几个核心问题,导致无法批量处理:

  • 全局context仅存储单个time_ago变量,循环赋值时会被持续覆盖,最终只会保留最后一条广告的计算结果
  • 在get_context_data中单独查询models.Catalogue.objects.all(),绕过了ListView自带的分页逻辑,导致分页功能完全失效
  • 冗余的时间格式转换步骤(先转字符串再转回datetime对象)完全没必要
  • 未处理source_id != 3的场景,会导致这部分广告的时间变量未定义报错
调整方案

方案一:视图层给每条广告绑定时间属性

1. 修改 views.py

不再单独查询全量数据,直接基于ListView已经处理好的分页广告列表,给每个对象动态添加time_ago属性:

import datetime
import timeago
from django.views import generic
from . import models

class crawler(generic.ListView):
    paginate_by = 12
    model = models.Catalogue
    template_name = 'index.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 获取当前分页后的广告列表,复用ListView的分页逻辑
        catalogue_list = context['catalogue_list']
        now = datetime.datetime.now()

        for cat in catalogue_list:
            # 非source_id=3的广告做兜底处理,避免报错
            if cat.source_id != 3:
                cat.time_ago = '' # 可替换为其他需要的展示内容,比如原始时间
                continue
            # 直接转换时间戳为datetime对象,省略冗余的字符串转换步骤
            date = float(cat.datetime)
            d_datetime = datetime.datetime.fromtimestamp(date / 1000.0)
            cat.time_ago = timeago.format(d_datetime, now, 'fa_IR')
        
        return context

2. 修改模板 index.html

直接调用每条广告自身的time_ago属性,不再使用全局变量:

{% for Catalogue in catalogue_list %}
    <h4 class="card-title mt-3" dir="rtl" style="text-align:right;">{{ Catalogue.title }}</h4>
    <br>{{ Catalogue.source }}
    <div class="card-footer" dir="rtl" style="text-align:right">
        <small id="datetime">{{ Catalogue.time_ago }}</small>
    </div>
{% empty %}
    <p>There are no ads in database.</p>
{% endfor %}

可选优化:将时间逻辑封装到模型中

如果后续多个场景都要用到这个相对时间,直接把计算逻辑封装到Catalogue模型的方法里,视图甚至不需要重写get_context_data,复用性更强:

1. 修改 models.py

在Catalogue模型中新增自定义方法:

import datetime
import timeago
from django.db import models

class Catalogue(models.Model):
    # 原有字段定义保持不变
    datetime = models.CharField() # 假设你的时间戳字段是字符串类型
    source_id = models.IntegerField()

    def get_time_ago(self):
        if self.source_id != 3:
            return '' # 兜底逻辑
        date = float(self.datetime)
        d_datetime = datetime.datetime.fromtimestamp(date / 1000.0)
        now = datetime.datetime.now()
        return timeago.format(d_datetime, now, 'fa_IR')

2. 模板直接调用方法

不需要改动任何视图代码,模板里直接用即可:

<small id="datetime">{{ Catalogue.get_time_ago }}</small>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 01:36:01