python+Django(3.*)开发日记(二):ajax+vue+django实现简易聊天室功能

一:文件准备

1、在static/js下准备ajax对应的js文件、vue对应的js文件和jquery对应的js文件

2、在templates模板文件夹下准备聊天室的html文件(css文件自行编写)

二:创建子应用

使用 python3 manage.py startapp chart(子应用名) 创建子应用

在settings配置文件中注册子应用

INSTALLED_APPS = [] 这个列表中注册

三:后端程序编写

1、在chart子应用中设计数据库模型(models)

from django.db import models
from WipasWeb.utils.models import BaseModel
from users.models import User


class TalkMesg(BaseModel):

    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
    content = models.TextField('内容')

    def __str__(self):
        return str(self.id)

    class Meta:
        verbose_name = '互动信息管理'
        verbose_name_plural = verbose_name

2、在主路由中编写路由

# 互动交流
    path('', include('chat.urls', namespace='chart')),

3、在chart子应用中编写视图

from django.urls import path, include, re_path
from . import views


app_name = 'chart'
urlpatterns = [
    # 聊天互动
    path('chart/', views.ChartView.as_view(), name='chart'),
    # # 使用ajax每秒请求一次
    path('ajax/', views.ChartAjaxView.as_view()),

]

4、编写视图

# -- coding: utf-8 --**

from django.shortcuts import render
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django import http
import logging
import json

from .models import TalkMesg
from users.models import User
from users.utils import get_chart_content
from users import constant_num

# 创建日志输出器
logger = logging.getLogger('django')


class ChartAjaxView(LoginRequiredMixin, View):

    def post(self, request):
        json_dict = json.loads(request.body.decode())  # ajax请求发送的数据在请求体中
        ajax = json_dict.get('ajax')
        if ajax == '1':
            #  ajax自动发送的post请求无额外参数,实现每3秒刷新一次页面(局部刷新)
            msg = TalkMesg.objects.all().order_by('-create_time')[0:11]
            content_list = get_chart_content(msg=msg)
            name = request.user.name
            content = {
                'content_list': content_list,
                'name': name,
            }
            return http.JsonResponse(content)
        else:
            # 用户点击按钮发送聊天内容,页面刷新一次
            func = json_dict.get('context')
            if func:
                user = request.user.username
                user_id = User.objects.get(username=user).id
                try:
                    msg_into = TalkMesg.objects.create(content=func, user_id=user_id)
                except Exception as e:
                    logger.error(e)
            # msg = TalkMesg.objects.all()[constant_num.ZERO:constant_num.HUNDRED]
            msg = TalkMesg.objects.all().order_by('-create_time')[0:11]

            name = request.user.name
            content_list = get_chart_content(msg=msg)
            content = {
                'content_list': content_list,
                'name': name
            }
            return http.JsonResponse(content)


class ChartView(LoginRequiredMixin, View):

    def get(self, request):
        """互动交流页面"""
        # msg = TalkMesg.objects.all()[constant_num.ZERO:constant_num.HUNDRED]
        msg = TalkMesg.objects.all().order_by('-create_time')[0:11]
        content = get_chart_content(msg=msg)
        name = request.user.name
        return render(request, 'chart.html', locals())


4.1、get_chart_content函数

def get_chart_content(msg):
    """获取聊天内容"""
    cont = []
    for member in msg:
        time = member.create_time + timedelta(hours=8)  # 数据库时间比北京时间慢8小时
        time = time.strftime('%Y-%m-%d %H:%M:%S')
        name = User.objects.get(id=member.user_id).name
        content = member.content
        context = {
            'time': time,
            'name': name,
            'content': content
        }
        cont.append(context)
    return cont

五:前端代码编写

1、在js文件夹创建chart.js文件,chart.js代码如下

let vm = new Vue({
    el: '#app',  // 寻找到id属性值为app的div
    // 修改Vue变量的读取语法
    delimiters: ['[[', ']]'],  // vue渲染语法和jinja2渲染语法冲突,所以更改vue渲染语法
    data: {
        context: '',
        content: JSON.parse(JSON.stringify(content)),
        name: '',
    },
    mounted(){
        // 自动执行,每3秒发送一次请求,更新页面聊天内容
        this.$nextTick(() => {
          setInterval(this.show_message, 3000);
        });
    },
    methods: {
        show_message(){
            let url = '/ajax/';
            axios.post(url, {'ajax': '1'}, {
                responseType: 'json'
            })
                .then(response => {
                    this.content = response.data.content_list;
                    this.name = response.data.name;
                })
                .catch(error => {
                    console.log(error.response);
                });
        },

        // 获取聊天内容
        get_chart(){
            let url = '/ajax/';
            axios.post(url, {'ajax': '0', 'context': this.context}, {
                responseType: 'json'
            })
                .then(response => {
                    this.content = response.data.content_list;
                    this.name = response.data.name;
                })
                .catch(error => {
                    console.log(error.response);
                });
        },
    }
});

2、chart.html部分代码

<div class="msg_ground">
     <div class="msg">
          <div v-for="msg in content">
              <ul>
                  <li>
                       <span class="ttime" style="text-align: right;">[[ msg.time ]]&nbsp;[[ msg.name ]]</span><br>
                       <span style="text-align: right;">[[ msg.content ]]</span>
                   </li>
               </ul>
               <p>&nbsp;&nbsp;</p>
               <p>&nbsp;&nbsp;</p>
           </div>
     </div>
</div>
<div class="sub">
    <form>
          <textarea v-model="context" class="text" name="content"></textarea>
          <input @click="get_chart" class="submit" type="button" value="发送">
    </form>
</div>

chart.html完整代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>畅所欲言</title>
        <link rel="stylesheet" type="text/css" href="{{ static('css/chart.css') }}">
        <script type="text/javascript" src="{{ static('js/jquery.min.js') }}"></script>
        <script type="text/javascript" src="{{ static('js/vue.global.js') }}"></script>
        <script type="text/javascript" src="{{ static('js/axios.min.js') }}"></script>
    </head>
    <body>
        <-- 这个div必须有,且必须设置id属性为app -->
        <div id="app">
            <div class="ground">
                <div class="navigation">
                    <ul class="ul_nav">
                        <li class="li0">导&nbsp;&nbsp;航</li>
                        <li class="li1"><a class="ind" href="{{ url('content:index') }}">首页</a></li>
                        <li class="li2"><a class="ind" href="{{ url('organize:team')}}">组织架构</a></li>
                        <li class="li3"><a class="ind" href="{{ url('tools:toollist')}}">工具大全</a></li>
                        <li class="li4"><a class="ind" href="{{ url('golden:golden')}}">智权中心</a></li>
                        <li class="li5"><a class="ind" href="#">文档资料</a></li>
                        <li class="li6"><a class="ind" href="#">交流互动</a></li>
                        <li class="li7"><a class="ind" href="{{ url('content:worktime')}}">加班情况</a></li>
                        <li class="li8"><a class="ind" href="#">用户中心</a></li>
                    </ul>
                </div>
                <div class="talk">
                    <div class="first">

                    </div>
                    <div class="msg_ground">
                        <div class="msg">
                            <div v-for="msg in content">
                                <ul>
                                    <li>
                                        <span class="ttime" style="text-align: right;">[[ msg.time ]]&nbsp;[[ msg.name ]]</span><br>
                                        <span style="text-align: right;">[[ msg.content ]]</span>
                                    </li>
                                </ul>
                                <p>&nbsp;&nbsp;</p>
                                <p>&nbsp;&nbsp;</p>
                            </div>
                        </div>
                    </div>
                    <div class="sub">
                        <form>
                            <textarea v-model="context" class="text" name="content"></textarea>
                            <input @click="get_chart" class="submit" type="button" value="发送">
                        </form>
                    </div>
                    <div class="end">

                    </div>
                </div>
            </div>
        </div>
        <script type="text/javascript">
            let content = {{ content | safe }};
        </script>
        <script type="text/javascript" src="{{ static('js/chart.js') }}"></script>
    </body>
</html>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值