IOS开发笔记(八)——Django后台,IM聊天工具接口设计,图片、文字信息的发送,保存,读取

中山大学数据科学与计算机学院本科生实验报告

(2019年春季学期)


一、实验题目

IM业务系统后台实现

二、实现内容

基于Django框架实现下列接口api

  • 信息的发送,保存,读取
    • 图片
    • 文字

三、实验结果

信息发送

1.概述

为了实现聊天工具对话的消息传递,这里我们引入了序列号的概念,每一个消息都有它特定的序号,我们根据这个序列号来确定这个消息是否已经发送,是否已经被接受到,是否需要删除等逻辑。

除此之外,为了实现多用户间的对话,例如A->B, A->C, B->C,他们之间如何能找到属于他们各自的信息呢?这里我们利用的是维护一个消息表,每一条消息都有发送用户的id,接受用户的id,内容的id,然后再通过内容的id在内容表格中找具体的内容。

2.数据库设计——Message表
class Msg(models.Model):
    Username = models.CharField(max_length = 20)
    Seq = models.IntegerField(default = 0)
    From = models.CharField(max_length = 20)
    Type = models.CharField(max_length = 10)
    ContentID = models.IntegerField(default = 0)

    def __str__(self):
        return self.Username

消息表,保留的是每一条消息的发送方,接受方,序列号,内容的id,类型(判断是图片或者文本数据)等

3.数据库设计——Content表
class Content_Text(models.Model):
    Cid = models.AutoField(primary_key = True)
    Cstr = models.CharField(max_length = 500)

    def __str__(self):
        return self.Cid

class Content_Image(models.Model):
    Cid = models.AutoField(primary_key = True)
    # 这里的upload_to是指定图片存储的文件夹名称,上传文件之后会自动创建
    Cimage = models.ImageField(upload_to='img')

    def __str__(self):
        return self.Cid

内容表,这里我们设置了两个部分,一个是文字,一个是图片。特别是图片部分使用的是Djungo中的ImageField类型,后面的upload_to是指定图片存储的文件夹名称,上传文件之后会自动创建。

两个表都是简单的包含一个id,一个内容,便于Message表的查询

3. URL设计
用户发送信息:
/content/{ type (text, image) }/
POST
{
to: {username}
data: {}
}

获取内容:
/content/{ type (text, image) }/{id}/
GET
          
用户消息表:
/message/{seq}/
GET
返回:
{
...
data:[ ]
}

在Django的urls.py文件中表现为

from django.urls import path

from . import views

urlpatterns = [
    path('text/', views.text, name='text'),
    path('image/', views.image, name='image'),
    path('text/<int:text_id>', views.text_detail, name='text_detail'),
    path('image/<int:image_id>', views.image_detail, name='image_detail'),
]
4. 具体实现
a.从消息表通过序列号获取消息
from django.forms.models import model_to_dict
from django.http import HttpResponse
import json
from .models import Msg

def messageTable(request, seq):
    response = {'state':'fail', 'msg':'no msg'}

    # 要在登录状态下
    if 'login_id' not in request.session:
        response['msg'] = 'no login'
        return HttpResponse(json.dumps(response), content_type = 'application/json')

    # 只接受 GET 请求
    if request.method != 'GET':
        response['msg'] = 'wrong method'
        return HttpResponse(json.dumps(response), content_type = 'application/json')

    # 已经登录, 所以拿取用户信息
    t_username = request.session['login_id']

    # 数据库操作
    try:
        t_msg = Msg.objects.filter(Username = t_username, Seq__gt = seq)
    except Exception as e:
        response['msg'] = 'db error'
        return HttpResponse(json.dumps(response), content_type = 'application/json')
    else:
        if t_msg.count() <= 0:
            response['msg'] = 'no data'
        else:
            temp = []
            for index in range(t_msg.count()):
                temp.append(model_to_dict(t_user[index]))

            response = {'state':'ok', 'msg':'ok', "data":temp}

            response['state'] = 'ok'
            response['msg'] = 'get message successfully'

    return HttpResponse(json.dumps(response), content_type = 'application/json')

具体逻辑

  • 定义返回体的内容,包括一个state和msg
  • 判断是否已经登陆状态
    • 是,直接返回HttpResponse,告诉前端已经登陆,无须注册
    • 否,下一步
  • 判断方法是否为GET
  • 获取用户注册的用户名以及密码
  • 数据库操作
    • 通过序列号来查找消息内容,最后返回改内容
上传一个string
# 上传一个string,只允许post方法
def text(request):
    response = {'state':'fail', 'msg':'no msg'}

    # 要在登录状态下
    if 'login_id' not in request.session:
        response['msg'] = 'no login'
        return HttpResponse(json.dumps(response), content_type = 'application/json')

    # 只允许POST方法
    if request.method != 'POST':
        response['msg'] = 'wrong method'
        return HttpResponse(json.dumps(response), content_type = 'application/json')
    
    # 已经登录, 所以拿取用户信息
    from_username = request.session['login_id']

    # 获取参数
    try:
        t_data = request.POST['data']
        to_username = request.POST['to']
    except Exception as e:
        response['msg'] = 'POST parameter error'
        return HttpResponse(json.dumps(response), content_type = 'application/json')

    # 为消息设定一个id,这里使用的是消息表的长度+1
    cid = len(Content_Text.objects.all()) + 1

    seq = 1
    # 处理seq,在Msg根据接收方用户名找到上一个seq,若不存在则初始化为1
    try:
        t_msg = Msg.objects.filter(Username = to_username)

    except Exception as e:
        response['msg'] = 'db error'
        return HttpResponse(json.dumps(response), content_type = 'application/json')
    else:
        # 找到该用户最大的seq
        if t_msg.count() > 0:
            for msg in t_msg:
                seq = max(seq, msg.Seq)
            seq += 1

    # 数据库操作,插入消息,并插入到message
    try:
        Content_Text.objects.create(
            Cid = cid,
            Cstr = t_data
        )
        Msg.objects.create(
            Username = to_username,
            Seq = seq,
            From = from_username,
            Type = 'text',
            ContentID = cid
        )
        response['state'] = 'ok'
        response['msg'] = 'send successfully'
    except Exception as e:
        response['msg'] = 'db error'

    return HttpResponse(json.dumps(response), content_type = 'application/json')

具体逻辑

  • 判断是否为登陆的状态
  • 定义返回体的内容,包括一个state和msg
  • 判断方法是否为POST,不允许GET方法
  • 获取post方法传递的两个参数
    • 这时能得到用户上传的data与发送的对象名
  • 为这个用户上传的消息安排一个cid,这里使用的是消息表的长度+1
  • 处理seq,在Msg根据接收方用户名找到上一个seq,若不存在则初始化为1
  • 数据库操作
    • 插入内容
    • 插入消息
  • 返回消息
获取一个string
def text_detail(request, text_id):
    response = {'state':'fail', 'msg':'no msg'}

    # 要在登录状态下
    if 'login_id' not in request.session:
        response['msg'] = 'no login'
        return HttpResponse(json.dumps(response), content_type = 'application/json')

    # 只允许GET方法
    if request.method != 'GET':
        response['msg'] = 'wrong method'
        return HttpResponse(json.dumps(response), content_type = 'application/json')
    
    # 数据库操作,查询消息
    try:
        t_text = Content_Text.objects.filter(Cid = text_id)
    except Exception as e:
        response['msg'] = 'db error'
        return HttpResponse(json.dumps(response), content_type = 'application/json')
    else:
        if t_text.count() == 1:
            temp = model_to_dict(t_text[0])
            response = {'state':'ok', 'msg':'ok', "data":temp}
        else:
            response['msg'] = 'no data'

    return HttpResponse(json.dumps(response), content_type = 'application/json')

具体逻辑

  • 判断是否为登陆的状态
  • 定义返回体的内容,包括一个state和msg
  • 判断方法是否为GET方法
  • 数据库操作
    • 根据这个id来查找数据库是否存在该信息
  • 返回消息
上传图片与获取图片

这两个部分与上面也是类似,上传图片实际上是 把图片存在服务器的硬盘中,将图片存储的路径存在数据库中。

首先要配置静态路径保存图片,setting.py

#设置静态文件路径为主目录下的media文件夹
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')     
#url映射
MEDIA_URL = '/media/'    

新增的逻辑在与对数据库操作:

# 数据库操作,插入图片
try:
    Content_Image.objects.create(
        Cid = cid,
        Cimage = "img/"+ t_data.name
    )
    Msg.objects.create(
        Username = to_username,
        Seq = seq,
        From = from_username,
        Type = 'image',
        ContentID = cid
    )

    # 保存文件
    fname = settings.MEDIA_ROOT + "/img/" + f1.name
    with open(fname,'wb') as pic:
        for c in f1.chunks():
            pic.write(c)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值