Django中实现页面定时获取新文章并更新的技术问询
嘿,这个实时更新文章的需求很典型,我来给你梳理一套完整的实现方案,分后端(Django)和前端两部分来讲,保证你能快速落地!
后端实现(Django部分)
首先咱们先把后端的API接口搭起来,用来处理前端的轮询请求:
1. 确保Article模型的status字段配置正确
你的Article模型里已经有status字段了,记得把默认值设为1,最好加上选项让管理后台更直观:
from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() # status=1展示,status=0不展示,默认值1 status = models.IntegerField( default=1, choices=[(0, '不展示'), (1, '展示')] ) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['-created_at'] # 按创建时间倒序,最新的在前
2. 写一个处理轮询的视图函数
这个视图要接收前端传的last_shown_id参数,返回所有status=1且ID大于last_shown_id的新文章(用ID过滤简单直接,你也可以换成创建时间来判断):
from django.http import JsonResponse from .models import Article def get_new_articles(request): # 获取前端传的最后展示的文章ID,默认0(第一次请求时没有这个参数) last_shown_id = request.GET.get('last_shown_id', 0) # 过滤出符合条件的文章,只返回需要的字段(按需调整) new_articles = Article.objects.filter( status=1, id__gt=last_shown_id ).values('id', 'title', 'content') # 转成列表返回JSON格式 return JsonResponse(list(new_articles), safe=False)
3. 配置URL路由
把上面的视图映射到一个API路径,比如在你的app的urls.py里:
from django.urls import path from . import views urlpatterns = [ # 其他业务路由... path('api/get-new-articles/', views.get_new_articles, name='get_new_articles'), ]
前端实现(AJAX轮询)
接下来写前端的逻辑,实现每隔N秒请求一次后端,自动更新页面内容:
1. 页面结构
先准备一个展示文章的容器,别忘了加上Django要求的CSRF令牌(否则AJAX请求会被拒绝):
<!-- 文章展示容器 --> <div id="articles-container"> <!-- 初始加载的文章可以用Django模板循环渲染 --> {% for article in initial_articles %} <div class="article" data-id="{{ article.id }}"> <h3>{{ article.title }}</h3> <p>{{ article.content }}</p> </div> {% endfor %} </div> <!-- Django的CSRF令牌,必须添加 --> {% csrf_token %}
2. JavaScript轮询逻辑
用原生JS的fetch API来实现,逻辑清晰易维护:
// 获取CSRF令牌的值 const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; // 保存最后展示的文章ID,初始值从页面已有的文章里取最大的ID let lastShownId = 0; const articlesContainer = document.getElementById('articles-container'); const existingArticles = articlesContainer.querySelectorAll('.article'); if (existingArticles.length > 0) { lastShownId = parseInt(existingArticles[existingArticles.length - 1].dataset.id); } // 定义获取新文章的函数 function fetchNewArticles() { fetch(`/api/get-new-articles/?last_shown_id=${lastShownId}`, { method: 'GET', headers: { 'X-CSRFToken': csrfToken, // 带上CSRF令牌 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.length > 0) { // 把新文章添加到容器末尾 data.forEach(article => { const articleDiv = document.createElement('div'); articleDiv.className = 'article'; articleDiv.dataset.id = article.id; articleDiv.innerHTML = ` <h3>${article.title}</h3> <p>${article.content}</p> `; articlesContainer.appendChild(articleDiv); // 更新最后展示的文章ID为最新的那个 lastShownId = article.id; }); } }) .catch(error => { console.error('获取新文章失败:', error); // 可以在这里加简单的重试逻辑,避免一次失败就停更 }); } // 设置定时器,每隔N秒调用一次(比如N=5就是5秒) const pollInterval = 5 * 1000; // 单位是毫秒 setInterval(fetchNewArticles, pollInterval); // 页面加载完成后先调用一次,不用等N秒才更新 window.addEventListener('load', fetchNewArticles);
一些优化小建议
- 如果文章更新频率不高,可以用**长轮询(Long Polling)**代替普通轮询:后端收到请求后,如果没有新文章就不立即返回,而是等待有新文章或者超时才响应,能大幅减少请求次数,节省服务器资源。
- 可以加个标签页监听逻辑:用户切到其他标签页时暂停轮询,切回来再恢复,节省浏览器资源。
- 如果文章数量很大,后端可以加分页限制,比如每次最多返回10条新文章,避免一次返回过多数据影响性能。
内容的提问来源于stack exchange,提问作者Rustam Rakhimov
相关产品推荐
相关产品推荐

