DJANGO:用AJAX更新div

8 投票
3 回答
5629 浏览
提问于 2025-04-15 16:52

我正在开发一个聊天应用程序。目前我用jquery的$.post()方法添加聊天消息,这个过程很顺利。

现在我需要从数据库中的聊天表里获取最新的聊天消息,并把这些消息添加到聊天页面上。因为我对Django还不太熟悉,所以请慢一点。

那么,我该如何把聊天表里的数据拿回聊天页面呢?

提前谢谢你们!

3 个回答

2

既然你已经在用AJAX发送数据了,为什么不把返回的数据直接放到那个div里呢?处理这个数据的视图可以返回一个渲染好的模板或者JSON格式的数据,然后你的JavaScript可以在回调函数中把它插入进去。

2

为了让这个过程顺利进行,有很多事情需要处理...

  • 客户端会定期向服务器询问有没有新的聊天记录
  • 服务器会检查并只回复最新的记录
  • 客户端收到最新的记录后,会把它们添加到网页上

刚开始的时候,这可能会让人感到困惑,因为不太清楚客户端和服务器各自做了什么。不过如果把这个大问题拆分开来,你会发现其实过程很简单。

如果客户端要定期向服务器询问新的聊天记录,那么服务器(比如用django做的)就需要有某种API来处理这个请求。你最大的决定就是服务器返回什么样的数据。你可以选择:渲染后的HTML、XML、YAML或者JSON。最轻量级的是JSON,而且大多数主流的JavaScript框架都支持它(django也有JSON序列化功能,真是太棒了)。

# Your model I'm assuming is something to the effect of...
class ChatLine(models.Model):
    screenname = model.ChatField(max_length=40)
    value = models.CharField(max_length=100)
    created = models.DateTimeField(default=datetime.now())

# A url pattern to match our API...
url(r'^api/latest-chat/(?P<seconds_old>\d+)/$',get_latest_chat),

# A view to answer that URL
def get_latest_chat(request, seconds_old):
    # Query comments since the past X seconds
    chat_since = datetime.datetime.now() - datetime.timedelta(seconds=seconds_old)
    chat = Chat.objects.filter(created__gte=comments_since)

    # Return serialized data or whatever you're doing with it
    return HttpResponse(simplejson.dumps(chat),mimetype='application/json')

所以每当我们请求API时,应该会得到像这样的数据...

[
    {
        'value':'Hello World',
        'created':'2009-12-10 14:56:11',
        'screenname':'tstone'
    },
    {
        'value':'And more cool Django-ness',
        'created':'2009-12-10 14:58:49',
        'screenname':'leethax0r1337'
    },
]

在我们实际的页面上,有一个<div>标签,我们称它为<div id="chatbox">,它会存放所有进来的聊天消息。我们的JavaScript只需要定期请求我们创建的服务器API,检查是否有响应,如果有数据,就把它们添加到聊天框里。

<!-- I'm assuming you're using jQuery -->
<script type="text/javascript">

    LATEST_CHAT_URL = '{% url get_latest_chat 5 %}';

    // On page start...
    $(function() {
        // Start a timer that will call our API at regular intervals
        // The 2nd value is the time in milliseconds, so 5000 = 5 seconds
        setTimeout(updateChat, 5000)
    });

    function updateChat() {
        $.getJSON(LATEST_CHAT_URL, function(data){
            // Enumerate JSON objects
            $.each(data.items, function(i,item){
                var newChatLine = $('<span class="chat"></span>');
                newChatLine.append('<span class="user">' + item.screenname + '</span>');
                newChatLine.append('<span class="text">' + item.text + '</span>');
                $('#chatbox').append(newChatLine);
            });
        });
    }

</script>

<div id="chatbox">
</div>

当然,我还没有测试过这些,但我希望这能让你对整个过程有个大致的了解。

14

我最喜欢的处理这种情况的方法是使用一个包含标签

简单来说,你需要为页面模板中每个单独的对象创建一个单独的模板来渲染它们。

页面模板:

{% load message_tags %}    

<h3>Messages</h3>
<div class="message_list">
    {% for message in messages %}
        {% render_message message %}
    {% endfor %}
</div>

templatetags/message_tags.py:

from django import template

register = template.Library()

@register.inclusion_tag('individual_message.html')
def render_message(message):
    context_for_rendering_inclusion_tag = {'message': message}
    return context_for_rendering_inclusion_tag

现在你可以使用同一个模板来渲染你想要添加到message_list这个div中的额外消息,这个操作可以在你从ajax代码中调用的一个单独视图中完成。

def ajax_retrieve_latest_message(request):
    # ... Get the lastest message
    render_to_response('individual_message.html', ... 

而你的jQuery代码看起来会像这样...

$.post(url_of_ajax_view, request_data, function(data, status) {
    if (status == 'success') {
        $(".message_list").append(data);
    }
});

为了完整起见,你的individual_message.html文件会包含显示实际消息所需的所有标记...

希望这些对你有帮助 :)

撰写回答