初始渲染页面并通过相同模板HTML使用AJAX更新

10 投票
3 回答
2888 浏览
提问于 2025-04-15 15:55

假设你有一个叫“查看故事”的页面,这只是一个通过Python/Django在后台生成的网页。在这个页面的底部,有一串评论列表,这些评论是通过Django的模板系统(在一个循环中)作为“查看故事”模板的一部分渲染出来的。这个页面还允许你添加评论到列表中。这是通过AJAX实现的,页面会更新显示新评论(而不需要重新加载整个页面)。

现在,当我在列表末尾添加新评论时,我希望生成的新评论的HTML(放在一个<li>标签里)能使用和原始评论相同的代码,这些原始评论是在最初请求时发送到客户端的。

有几种方法可以做到这一点:

  1. 在最初渲染时,把评论数据放到一个JavaScript变量里,等页面渲染完后通过JavaScript添加内容。然后当添加新评论时,可以用同样的JavaScript来渲染新的评论。问题是:从搜索引擎的角度来看,我不确定谷歌能否索引那些在页面渲染后生成的评论——我猜可能不能。

  2. 每次通过AJAX添加新评论时,让AJAX请求返回实际的HTML,而不仅仅是新评论的JSON数据。这个HTML可以使用和原始页面渲染时相同的模板片段生成。这个方法的问题是,它把AJAX请求绑定到特定的视图或渲染方式,这让我不太喜欢。

  3. 和第二种方法类似,不过是单独发请求来获取新评论的HTML,或者可能是所有评论的HTML,然后把列表清空并重新渲染。我不喜欢这个方法,因为效率低下,耗时不必要。

所以,总结一下,我想找到一种方法,避免为同一个视图重复模板/HTML代码。我希望能得到一些其他人成功的建议,因为我很确定这是一个常见的情况,不管后台使用什么技术。

谢谢!

3 个回答

1

还有一种选择,叫做选项4:

就是复制列表中已有的元素,然后改变它的值。当然,这种方法没有模板那么灵活。你也可以复制一个隐藏的元素,这样在列表为空的时候也能处理。

你还可以尝试选项2b:

像选项2那样在服务器上生成HTML,但不是直接访问数据库,而是把生成的过程传入JSON(或者可以很容易转成JSON的对象)。这需要更多的工作,但意味着你在写自己的网站的同时,实际上也在写一个API。

选项1是任何非网页应用都会使用的方法。虽然搜索引擎在处理AJAX方面越来越好,但还是强烈建议返回所有内容的HTML。我觉得现代浏览器中的JavaScript速度足够快,除了非常大的页面,选项1在SEO方面是相当合理的。

还有选项5 - 在服务器上用JavaScript生成页面,并在客户端使用相同的代码。这可能是最复杂的方法,除非你有很好的理由,否则我不推荐这样做。

6

你需要做的事情如下:

首先是 view_story.html 文件:

bla bla bla

Comments:
<ul id="comments">
{% for comment in comments %}
   <li>{% include "comment_item.html" %}</li>
{% endfor %}
</ul>
<from>Ajax form here</form>

接下来,你需要创建一个用于添加评论的视图(使用 ajax):

def add_comment(request):
    comment = Comment(...)
    return render_to_response('comment_item.html', {'comment': comment})

所以,当你提交 ajax 请求到 add_comment 视图后,你会得到评论的内容(就是一条评论)……然后只需要把它添加到列表中……比如,可以用 jQuery 这样做:

$('ul#comments').append('<li>'+comment_content+'</li>')
3

我觉得第二个选项最好。它是渐进式的(只在添加评论时再渲染一条评论),而且可以重复使用渲染的部分。如果你不喜欢从Ajax请求中只返回HTML,那就让响应返回一个JSON结构,其中包含HTML作为一个部分。这样你还可以在不额外请求HTML的情况下,传递状态(或者其他信息)。

第一个选项是浪费的:服务器应该先渲染出页面的初始样子。

第三个选项也是浪费的:为什么要为了添加一条评论而发出两个请求呢?

撰写回答