微信小程序开发第七课

一 人脸识别

1.1 使用步骤

# 1 注册百度人脸识别接口
https://cloud.baidu.com/product/face.html
# 2 免费领取额度:https://console.bce.baidu.com/ai/#/ai/face/overview/index# 3 创建应用:https://console.bce.baidu.com/ai/#/ai/face/app/list# 4 查看人脸库:https://console.bce.baidu.com/ai/#/ai/face/facelib/groupList~appId=4652887

在这里插入图片描述

在这里插入图片描述

1.2 上传-删除-匹配人脸

# https://ai.baidu.com/ai-doc/FACE/ek37c1qizfrom aip import AipFace
import base64
from pypinyin import lazy_pinyin, Style
class BaiDuAI:def __init__(self,APP_ID='62643893',API_KEY='hfAwQUE1fwyCjXG01ZCHbaSG',SECRET_KEY='qgxJneAt0ovmGA2rLrdq99GEFs1apjte'):""" 你的 APPID AK SK """self.APP_ID = APP_IDself.API_KEY = API_KEYself.SECRET_KEY = SECRET_KEYself.client = AipFace(self.APP_ID, self.API_KEY, self.SECRET_KEY)def name_to_pinyin(self,text):style = Style.TONE3name_list=lazy_pinyin(text, style=style)return ''.join(name_list)def add_user(self):data = base64.b64encode(open('./gtl.png','rb').read()).decode('utf-8')image = dataimageType = "BASE64"groupId = "100"userId=self.name_to_pinyin('古天乐')""" 调用人脸注册 """self.client.addUser(image, imageType, groupId, userId);""" 如果有可选参数 """options = {}options["user_info"] = "彭于晏"options["quality_control"] = "NORMAL"options["liveness_control"] = "LOW"options["action_type"] = "REPLACE"""" 带参数调用人脸注册 """self.client.addUser(image, imageType, groupId, userId, options)def search(self):data = base64.b64encode(open('./pyy2.png', 'rb').read()).decode('utf-8')image = dataimageType = "BASE64"groupIdList = "100,2"""" 调用人脸搜索 """self.client.search(image, imageType, groupIdList);""" 如果有可选参数 """options = {}options["match_threshold"] = 70options["quality_control"] = "NORMAL"options["liveness_control"] = "LOW"# options["user_id"] = "233451"options["max_user_num"] = 3""" 带参数调用人脸搜索 """res=self.client.search(image, imageType, groupIdList, options)print(res)def delete(self):userId = "user1"groupId = "group1"faceToken = "face_token_23123"""" 调用人脸删除 """self.client.faceDelete(userId, groupId, faceToken);
if __name__ == '__main__':ai=BaiDuAI()# ai.add_user()ai.search()

1.3 项目中集成

#################### serializer.py########################
class CollectionSaveSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['name', 'avatar', 'area']def create(self, validated_data):# 在百度ai注册from libs.baidu_ai import BaiDuAIbaidu=BaiDuAI()avatar_file_object = validated_data.get('avatar')print(avatar_file_object)name = validated_data.get('name')name_pinyin=baidu.name_to_pinyin(name)res=baidu.add_user(avatar_file_object,name,name_pinyin)validated_data['name_pinyin'] = name_pinyinvalidated_data['face_token'] = res.get('result').get('face_token')instance=super().create(validated_data)return instance###### views.py#######
def destroy(self, request, *args, **kwargs):from libs.baidu_ai import BaiDuAIinstance = self.get_object()# 百度ai中删除baidu=BaiDuAI()res=baidu.delete(instance.name_pinyin,face_token=instance.face_token)print(res)self.perform_destroy(instance)return Response()

二 语音识别

2.1 收费方案

在这里插入图片描述

# 使用百度,科大讯飞等第三方平台
# https://ai.baidu.com/ai-doc/SPEECH/0lbxfnc9b
def speed(file_object):from aip import AipSpeechAPP_ID = ''API_KEY = ''SECRET_KEY = ''client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)data = file_object.read()# 识别本地文件return client.asr(data, 'pcm', 16000, {'dev_pid': 1537})

2.2 免费方案

# pip3.11 install --force- SpeechRecognition
# pip3.11 install -i https://pypi.tuna.tsinghua.edu.cn/simple pocketsphinx
#https://pypi.org/project/pocketsphinx/#files# 1 目前speech_recognition只有英文(en-US)的脱机识别库,如果需要脱机识别中文(zh-CN),需要手动加入对应的识别库,可参考如下操作# 2 逐层找到文件夹 pocketsphinx-data (参考如下路径):
\site-packages\speech_recognition\pocketsphinx-data# 3 随后将 【zh-CN文件】 下载解压到pocketsphinx-data 中,如下图所示#4 检查文件是否缺失以及命名、存放的位置是否一致# 5 语音文件准备 speech_recognition 对脱机识别的文件有要求,目前支持的格式有
1.WAV
2.AIFF/AIFF-C
3.FLAC# 6 代码
import speech_recognition as sraudio_file = './test1.wav'r = sr.Recognizer()with sr.AudioFile(audio_file) as source:audio = r.record(source)# 识别音频文件
result = r.recognize_sphinx(audio, language="zh-CN")
print(result)

三 采集统计

小程序端statistics

#############wxml##############
<view class="container"><view class="menu" wx:for="{{dataList}}" wx:key="index"><view> <label class="iconfont  icon-SCHEDULE" ></label>   {{item.date}}</view><label>{{item.count}}</label></view></view>################wxss##################
.container{border-top: 1px solid #ddd;
}.container .menu{font-size: small;padding: 10px 40rpx;border-bottom: 1px dotted #ddd;text-align: center;display: flex;flex-direction: row;justify-content: space-between;background-color: white;
}################js###############
var app = getApp();
var api = require("../../config/settings.js")Page({/*** 页面的初始数据*/data: {dataList:[{'date':'2024年4月20日','count':22},{'date':'2024年4月21日','count':12},{'date':'2024年4月22日','count':232}]},getRecord:function(){wx.showLoading({mask:true})wx.request({url: api.statistics,method:"GET",success :(res) =>{this.setData({dataList:res.data})},complete:()=>{wx.hideLoading()}})},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getRecord();},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {this.getRecord();},})
#####json###
{"usingComponents": {},"navigationBarTitleText": "采集统计","enablePullDownRefresh": true
}

后端接口

###########views.py############
class StatisticsView(GenericViewSet, ListModelMixin):queryset = Collection.objects.annotate(date=Trunc('create_time', 'day')).values('date').annotate(count=Count('id')).values('date', 'count')serializer_class = StatisticsListSerializer############serializer.py################
###采集统计序列化类
class StatisticsListSerializer(serializers.Serializer):date = serializers.DateTimeField(format="%Y年%m月%d日")count = serializers.IntegerField()####models.py###########
class Collection(models.Model):name = models.CharField(max_length=32, verbose_name='采集人员姓名')name_pinyin=models.CharField(max_length=32, verbose_name='姓名拼音',null=True)avatar = models.ImageField(upload_to='collection/%Y/%m/%d/', default='default.png', verbose_name='头像')create_time = models.DateTimeField(verbose_name='采集时间',default=datetime.now())face_token=models.CharField(max_length=128, verbose_name='百度ai的Token',null=True)area = models.ForeignKey(to='Area', null=True, verbose_name='网格区域', on_delete=models.CASCADE)class Meta:verbose_name_plural = '采集表'def __str__(self):return self.name

四 人脸检测

4.1 小程序端

#####wxml########
<!--pages/face/face.wxml-->
<view class="header"><camera class="camera" device-position="{{ backFront ? 'back' : 'front' }}" flash="off" frame-size="medium"></camera><view class="switch" bindtap="switchCamera"><image src="/images/camera/rotate-camera-white.png"></image></view><button class="submit" bindtap="takePhoto"> 拍照检测 </button>
</view><view class="table"><view class="item"><view class="title">检测记录</view></view><view class="item" wx:for="{{record}}" wx:for-item="row" wx:key="index"><view class="record"><view class="avatar"><image src="{{row.avatar}}"></image></view><view class="desc"><view wx:if="{{row.code == 100}}" class="username">检测成功:{{row.user_id}}</view><view wx:else class="username">检测失败:{{row.msg}}</view><view><view class="txt-group"><label class="zh">{{row.error_msg}}</label></view></view></view><view class="delete"><block wx:if="{{row.code == 100}}"><label class="iconfont icon-ziyuanxhdpi" style="color:green"></label></block><block wx:else><label class="iconfont icon-ziyuanxhdpi" style="color:red"></label></block></view></view></view></view>#######wxss#####
/* pages/face/face.wxss */
.header{position: relative;
}
.camera{height: 600rpx;width: 100%;
}.switch{position: absolute;top: 10rpx;right: 20rpx;height: 80rpx;width: 80rpx;
}.switch image{height: 100%;width: 100%;
}.submit{margin-top: 40rpx;color: #fff;border: 2rpx solid #00c8b6;background-color: #00c8b6;font-size: 32rpx;font-weight: normal;
}.table{margin-top: 40rpx;border-top: 1rpx solid #e7e7e7;
}.table .item {border-bottom: 1rpx solid #e7e7e7;}.table .item .title{margin: 20rpx 30rpx;padding-left: 10rpx;border-left: 5rpx solid #02bfae;font-size: 26rpx;
}.record{margin: 10rpx 40rpx;display: flex;flex-direction: row;justify-content: space-between;
}.record .avatar{width: 100rpx;height: 100rpx;
}.record .avatar image{width: 100%;height: 100%;border-radius: 30rpx;
}.record .desc{margin: 0 40rpx;
}
.desc{width: 290rpx;display: flex;flex-direction: column;justify-content: space-around;
}
.desc .username{font-size: 25rpx;
}.txt-group{font-size: 20rpx;margin: 5rpx 0;
}
.txt-group .zh{color: #8c8c8c;
}.txt-group .en{color: #cccccc;
}.area{color: #00c8b6;font-weight: bold;
}.delete{width: 100rpx;text-align: center;display: flex;flex-direction: column;justify-content: center;
}######js
var api = require("../../config/settings.js")Page({data: {backFront:true,record:[]},switchCamera(e) {var old = this.data.backFrontthis.setData({backFront: !old})},takePhoto(e){wx.showLoading({title: '检测中',mask:true})const ctx = wx.createCameraContext()ctx.takePhoto({quality: 'high',success: (res) => {wx.uploadFile({url: api.face,filePath: res.tempImagePath,name: 'avatar',success:(response)=>{let resdata = JSON.parse(response.data)console.log(resdata)if(resdata.code==100 || resdata.code==102){console.log(resdata)resdata.avatar = res.tempImagePathvar oldRecord = this.data.recordoldRecord.unshift(resdata)console.log(oldRecord)this.setData({record:oldRecord})}else{wx.showToast({title: '请正常拍照'})}},complete:function(){wx.hideLoading()}})}})},})###### json####
{"usingComponents": {},"navigationBarTitleText": "人脸检测"
}

4.2 后端

###############views.py###############
###人脸检测接口
class FaceView(GenericViewSet):def create(self, request, *args, **kwargs):avatar_object = request.data.get('avatar')if not avatar_object:return Response({"msg": "未提交图像", "code": 101})from libs.baidu_ai import BaiDuAIai = BaiDuAI()result = ai.search(avatar_object)if result.get('error_code') == 0:  # 查询到# {'error_code': 0, 'error_msg': 'SUCCESS', 'log_id': 2159604393, 'timestamp': 1713864959, 'cached': 0, 'result': {'face_token': '095994eca64424cee347b59e0a7edc0e', 'user_list': [{'group_id': '100', 'user_id': 'li3si1xian4', 'user_info': '', 'score': 98.035797119141}]}}user = result.get('result').get('user_list')[0]user_info = user.get('user_info')user_id = user.get('user_id')score = user.get('score')return Response({"code": 100, 'msg': '匹配成功', 'user_info': user_info, 'user_id': user_id, 'score': score,'avatar':''})else:return Response({"code": 102, 'msg': '匹配失败,该人员可能不是我社区人员,注意防范'})############baidu_ai.py#########
# https://ai.baidu.com/ai-doc/FACE/ek37c1qizfrom aip import AipFace
import base64
from pypinyin import lazy_pinyin, Styleclass BaiDuAI:def __init__(self, APP_ID='62643893', API_KEY='hfAwQUE1fwyCjXG01ZCHbaSG',SECRET_KEY='qgxJneAt0ovmGA2rLrdq99GEFs1apjte'):""" 你的 APPID AK SK """self.APP_ID = APP_IDself.API_KEY = API_KEYself.SECRET_KEY = SECRET_KEYself.client = AipFace(self.APP_ID, self.API_KEY, self.SECRET_KEY)def name_to_pinyin(self, text):style = Style.TONE3name_list = lazy_pinyin(text, style=style)return ''.join(name_list)def add_user(self, path, name, userId,groupId=100):# image = base64.b64encode(open(path).read()).decode('utf-8')image = base64.b64encode(path.read()).decode('utf-8')imageType = "BASE64"""" 调用人脸注册 """res=self.client.addUser(image, imageType, groupId, userId);# """ 如果有可选参数 """# options = {}# options["user_info"] = name# options["quality_control"] = "NORMAL"# options["liveness_control"] = "LOW"# options["action_type"] = "REPLACE"## """ 带参数调用人脸注册 """# res = self.client.addUser(image, imageType, groupId, userId, options)print(res)return resdef search(self,img_obj):image = base64.b64encode(img_obj.read()).decode('utf-8')image_type = "BASE64"group_id_list = "100,101"""" 调用人脸搜索 """res=self.client.search(image, image_type, group_id_list);# """ 如果有可选参数 """# options = {}# options["match_threshold"] = 70# options["quality_control"] = "NORMAL"# options["liveness_control"] = "LOW"# # options["user_id"] = "233451"# options["max_user_num"] = 3## """ 带参数调用人脸搜索 """# res = self.client.search(image, imageType, groupIdList, options)print(res)return resdef delete(self,user_id,face_token,group_id=100):""" 调用人脸删除 """res=self.client.faceDelete(user_id, group_id, face_token)return resif __name__ == '__main__':ai = BaiDuAI()# ai.add_user()ai.search()

五 语音识别

5.1 小程序前端

#####js#########
// https://developers.weixin.qq.com/miniprogram/dev/api/media/recorder/RecorderManager.start.html
const recorderManager = wx.getRecorderManager()
var api = require("../../config/settings.js")Page({/*** 页面的初始数据*/data: {content:"",record:false},recordStart:function(){this.setData({record:true})const options = {// duration: 6000,//指定录音的时长,单位 mssampleRate: 16000,//采样率numberOfChannels: 1,//录音通道数encodeBitRate: 48000,//编码码率format: 'wav'//音频格式,有效值 }//开始录音recorderManager.start(options)},recordCancel:function(){console.log("停止");this.setData({record:false})wx.hideLoading()},recordStop:function(){if(!this.data.record){return}recorderManager.stop();recorderManager.onStop((res) => {// this.tempFilePath = res.tempFilePathwx.showLoading()wx.uploadFile({filePath: res.tempFilePath,name: 'voice',url: api.voice,success:(response)=>{console.log(response)// {'code': 100, 'msg':'成功','result': ['欢迎欢迎']}let voiceResponse = JSON.parse(response.data)if(voiceResponse.code == 100){console.log(voiceResponse)this.setData({content:this.data.content + voiceResponse.result[0]})}else{wx.showToast({title: '识别失败,请重新操作!',icon: "none"})}},complete:()=>{wx.hideLoading()}},)})this.setData({record:false})},})#####wxml#########
<!--pages/voice/voice.wxml-->
<textarea class="text" placeholder="等待语音识别自动录入..." placeholder-class="hoder" model:value="{{content}}" maxlength="{{-1}}"></textarea><button class="btn" hover-class="press" bind:longpress="recordStart" bind:touchcancel="recordCancel" bind:touchend="recordStop"> <label class="fa fa-microphone"></label> 按住说话</button>####wxss#####
/* pages/voice/voice.wxss */
page{background-color: #f5f5f5;
}
.text{height: 400rpx;background-color: white;width: 100%;padding: 20rpx;
}.btn{margin-top: 30rpx;/* color: #fff; */border: 2rpx solid #ddd;background-color: white; font-size: 32rpx;font-weight: normal;
}.press label{color: #179B16;
}
.press{background-color: #ddd;
}
.hoder{font-size: 28rpx;
}#####json####
{"usingComponents": {},"navigationBarTitleText": "语音识别"
}

5.2 后端

######views.py########
### 语音识别
from libs.baidu_ai import BaiDuVoiceclass VoiceView(GenericViewSet):def create(self, request, *args, **kwargs):voice_object = request.data.get('voice')# with open('./a.wav','wb') as f:#     f.write(voice_object.read())ai = BaiDuVoice()result = ai.speed(voice_object)# {'corpus_no': '6847771638436561158', 'result': ['你是不是打过来?'], 'sn': '15921476781594371078', 'err_msg': 'success.', 'err_no': 0}if result.get('err_no') == 0:return Response({'code': 100, 'msg': '识别成功', 'result': result.get('result')})else:return Response({'code': 101, 'msg': '识别失败'})#######baidu_ai.py
# https://ai.baidu.com/ai-doc/FACE/ek37c1qizfrom aip import AipFace
import base64
from pypinyin import lazy_pinyin, Style
from aip import AipSpeechclass BaiDuAI:def __init__(self, APP_ID='62643893', API_KEY='hfAwQUE1fwyCjXG01ZCHbaSG',SECRET_KEY='qgxJneAt0ovmGA2rLrdq99GEFs1apjte'):""" 你的 APPID AK SK """self.APP_ID = APP_IDself.API_KEY = API_KEYself.SECRET_KEY = SECRET_KEYself.client = AipFace(self.APP_ID, self.API_KEY, self.SECRET_KEY)def name_to_pinyin(self, text):style = Style.TONE3name_list = lazy_pinyin(text, style=style)return ''.join(name_list)def add_user(self, path, name, userId,groupId=100):# image = base64.b64encode(open(path).read()).decode('utf-8')image = base64.b64encode(path.read()).decode('utf-8')imageType = "BASE64"""" 调用人脸注册 """res=self.client.addUser(image, imageType, groupId, userId);# """ 如果有可选参数 """# options = {}# options["user_info"] = name# options["quality_control"] = "NORMAL"# options["liveness_control"] = "LOW"# options["action_type"] = "REPLACE"## """ 带参数调用人脸注册 """# res = self.client.addUser(image, imageType, groupId, userId, options)print(res)return resdef search(self,img_obj):image = base64.b64encode(img_obj.read()).decode('utf-8')image_type = "BASE64"group_id_list = "100,101"""" 调用人脸搜索 """res=self.client.search(image, image_type, group_id_list);# """ 如果有可选参数 """# options = {}# options["match_threshold"] = 70# options["quality_control"] = "NORMAL"# options["liveness_control"] = "LOW"# # options["user_id"] = "233451"# options["max_user_num"] = 3## """ 带参数调用人脸搜索 """# res = self.client.search(image, imageType, groupIdList, options)print(res)return resdef delete(self,user_id,face_token,group_id=100):""" 调用人脸删除 """res=self.client.faceDelete(user_id, group_id, face_token)return resclass BaiDuVoice:def __init__(self, APP_ID='63701411', API_KEY='b0tYjKxPmcuoSm4SAen19p2c',SECRET_KEY='m8ramzeLtMLHEa9XRPXQJNbcAWGiIuZ8'):""" 你的 APPID AK SK """self.APP_ID = APP_IDself.API_KEY = API_KEYself.SECRET_KEY = SECRET_KEYself.client = AipSpeech(self.APP_ID, self.API_KEY, self.SECRET_KEY)def speed(self, voice_object):res=self.client.asr(voice_object.read(), 'pcm', 16000, {'dev_pid': 1537,})return resif __name__ == '__main__':ai = BaiDuVoice()# file=open('../test1.wav','rb')file=open('../a.wav','rb')res=ai.speed(file)print(res)

六 公告

6.1 微信小程序端

#js###const api = require("../../config/settings.js")
Page({data: {noticeList: [{title: '公告标题1',create_time: '2024-04-25',content: '公告内容描述1,公告内容描述1,公告内容描述1。', // 可以根据实际情况添加更多内容igm: '/images/notice/notice1.jpg' // 图片路径,根据实际情况修改},{title: '公告标题2',create_time: '2024-04-26',content: '公告内容描述2,公告内容描述2,公告内容描述2。', // 可以根据实际情况添加更多内容igm: '/images/notice/notice2.jpg' // 图片路径,根据实际情况修改},// 可以添加更多社区公告数据]},onLoad: function () {// 页面加载时执行的逻辑this.refresh()},refresh(){wx.showLoading({mask: true})wx.request({url: api.notice,method: "GET",success: (res) => {this.setData({noticeList: res.data})},complete() {wx.hideLoading()}})}
})#####wxml##
<!-- community_notice.wxml -->
<view class="container"><!-- 使用wx:for循环遍历社区公告列表 --><view wx:for="{{noticeList}}" wx:key="index" class="notice-item"><!-- 左侧图片 --><image class="notice-image" src="{{item.igm}}" mode="aspectFill"></image><!-- 右侧内容 --><view class="notice-content"><view class="notice-title">{{item.title}}</view><view class="notice-time">{{item.create_time}}</view><view class="notice-details">{{item.content}}</view></view></view>
</view>###wxss###
/* community_notice.wxss */
.container {padding: 20rpx;
}.notice-item {display: flex;align-items: flex-start;margin-bottom: 20rpx; /* 添加间距 */border-bottom: 1px solid #f0f0f0; /* 添加底部边框 */padding-bottom: 20rpx; /* 增加底部内边距 */
}.notice-image {width: 150rpx;height: 120rpx;border-radius: 6rpx;margin-right: 20rpx;
}.notice-content {flex: 1;
}.notice-title {font-size: 28rpx;font-weight: bold;margin-bottom: 10rpx;
}.notice-time {font-size: 24rpx;color: #666666;margin-bottom: 10rpx;
}.notice-details {font-size: 24rpx;color: #333333;
}

6.2 后端接口

####views.py######
from .models import Notice
from .serializer import NoticeSerializer
class NoticeView(GenericViewSet,ListModelMixin):queryset =Notice.objects.all().order_by('create_time')serializer_class = NoticeSerializer###serilizer.py#######
class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = ['id', 'title','igm','create_time','content']extra_kwargs={'create_time':{'format':"%Y-%m-%d"}}

七 活动列表

小程序端

##### js####
var app = getApp();
var api = require("../../config/settings.js")
Page({data: {activityList: []},onLoad: function () {// 页面加载时执行的逻辑this.refresh()},refresh(){wx.showLoading({mask: true})wx.request({url: api.activity,method: "GET",success: (res) => {this.setData({activityList: res.data})},complete() {wx.hideLoading()}})},handleSignup: function (event) {// 处理报名按钮点击事件var index = event.currentTarget.dataset.index; // 获取当前点击的活动索引console.log('点击了报名按钮,索引为:', index);}
})
###wxml#####
<!-- activity_signup.wxml -->
<view class="container"><!-- 使用wx:for循环遍历活动报名列表 --><view wx:for="{{activityList}}" wx:key="index" class="activity-item"><!-- 活动内容 --><view class="activity-content"><view class="activity-title">{{item.title}}</view><view class="activity-enrollment">报名人数:{{item.count}}  |  总人数:{{item.total_count}}</view><view class="activity-time">获得积分:{{item.score}}</view><view class="activity-time">{{item.date}}</view><view class="activity-description">{{item.text}}</view> </view><!-- 报名按钮 --><button class="signup-btn" bindtap="handleSignup">报名</button></view>
</view>###wxss###
/* activity_signup.wxss */
.container {padding: 20rpx;
}.activity-item {display: flex;align-items: flex-start;justify-content: space-between;margin-bottom: 20rpx;border-bottom: 1px solid #ebebeb;padding-bottom: 20rpx;
}.activity-content {flex: 1;
}.activity-title {font-size: 28rpx;font-weight: bold;margin-bottom: 10rpx;
}.activity-time {font-size: 24rpx;color: #666666;margin-bottom: 10rpx;
}.activity-enrollment {font-size: 24rpx;color: #999999;margin-bottom: 10rpx;
}.activity-description {font-size: 24rpx;color: #333333;margin-top: 10rpx;white-space: pre-wrap; /* 自动换行 */
}.signup-btn {background-color: #50c8ff;color: #ffffff;border: none;border-radius: 4rpx;padding: 10rpx 20rpx;font-size: 24rpx;
}

后端接口

####视图类
from .models import Activity
from .serializer import ActivitySerializer
class ActivityView(GenericViewSet,ListModelMixin):queryset =Activity.objects.all().order_by('date')serializer_class = ActivitySerializer
### 序列化类
class ActivitySerializer(serializers.ModelSerializer):class Meta:model = Activityfields = ['id', 'title','text','date','count','score','total_count']extra_kwargs={'date':{'format':"%Y-%m-%d"}}
##表模型
class UserInfo(models.Model):name = models.CharField(verbose_name="姓名", max_length=32)avatar = models.FileField(verbose_name="头像", max_length=128, upload_to='avatar')create_date = models.DateField(verbose_name="日期", auto_now_add=True)score = models.IntegerField(verbose_name="积分", default=0)class Meta:verbose_name_plural = '用户表'def __str__(self):return self.name#  活动表
class Activity(models.Model):title = models.CharField(verbose_name="活动标题", max_length=128)text = models.TextField(verbose_name="活动描述", null=True, blank=True)date = models.DateField(verbose_name="举办活动日期")count = models.IntegerField(verbose_name='报名人数', default=0)total_count = models.IntegerField(verbose_name='总人数', default=0)score = models.IntegerField(verbose_name="积分", default=0)join_record = models.ManyToManyField(verbose_name="参与者",through="JoinRecord",through_fields=("activity", "user"),to="UserInfo")class Meta:verbose_name_plural = '活动表'def __str__(self):return self.title
#  活动报名记录
class JoinRecord(models.Model):user = models.ForeignKey(verbose_name='用户', to="UserInfo", on_delete=models.CASCADE)activity = models.ForeignKey(verbose_name="活动", to="Activity", on_delete=models.CASCADE, related_name='ac')exchange = models.BooleanField(verbose_name="是否已兑换", default=False)class Meta:verbose_name_plural = '活动报名记录'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148734.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【自动驾驶】控制算法(八)横向控制Ⅳ | 调试与优化——让车辆行驶更平稳!

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

iPhone锁屏密码忘了怎么解锁?轻松解锁攻略来了

在日常生活中&#xff0c;智能手机已成为我们不可或缺的伙伴。其中&#xff0c;iPhone以其出色的性能和优雅的设计&#xff0c;赢得了全球用户的喜爱。然而&#xff0c;即便是最忠实的iPhone用户&#xff0c;也可能会遇到一些棘手的问题&#xff0c;比如忘记了锁屏密码。面对这…

【高效且应用广泛的排序 —— 快速排序算法】

高效且应用广泛的排序 —— 快速排序算法 快速排序是一种常用的排序算法&#xff0c;主要采用分治的思想。以下是对快速排序算法的详细介绍及代码示例&#xff1a; 快速排序的基本思路是&#xff0c;每次将一个位置上的数据归位&#xff0c;使得该数左边的所有数据都比该数小…

工业物联网关为工业生产数字化转型赋能-天拓四方

一、引言 在工业4.0的大背景下&#xff0c;工业物联网关成为了制造业转型升级的关键技术之一。它通过连接设备和系统&#xff0c;实现数据的实时采集、处理和传输&#xff0c;从而提升生产效率、降低成本、优化资源配置&#xff0c;并最终推动整个制造业的数字化进程。本文将详…

AJAX 入门 day3 XMLHttpRequest、Promise对象、自己封装简单版的axios

目录 1.XMLHttpRequest 1.1 XMLHttpRequest认识 1.2 用ajax发送请求 1.3 案例 1.4 XMLHttpRequest - 查询参数 1.5 XMLHttpRequest - 数据提交 2.Promise 2.1 Promise认识 2.2 Promise - 三种状态 2.3 案例 3.封装简易版 axios 3.1 封装_简易axios_获取省份列表 3…

Android OpenGLES2.0开发(二):环境搭建

世界没有悲剧和喜剧之分&#xff0c;如果你能从悲剧中走出来&#xff0c;那就是喜剧&#xff0c;如果你沉缅于喜剧之中&#xff0c;那它就是悲剧。——科马克麦卡锡《路》 ​​​ OpenGL ES环境搭建 Android 应用中使用 OpenGL ES 绘制图形&#xff0c;必须创建一个显示容器。…

Rust - 字符串:str 与 String

在其他语言中&#xff0c;字符串通常都会比较简单&#xff0c;例如 “hello, world” 就是字符串章节的几乎全部内容了。 但是Rust中的字符串与其他语言有所不同&#xff0c;若带着其他语言的习惯来学习Rust字符串&#xff0c;将会波折不断。 所以最好先忘记脑中已有的关于字…

【一起学NLP】Chapter2-学习神经网络

目录 学习神经网络损失函数Tip:One-hot向量导数与梯度Tip:严格地说链式法则计算图反向传播其他典型的运算结点乘法结点分支节点Repeat节点Sum节点MatMul节点 Tip:浅拷贝和深拷贝的差异梯度的推导和反向传播的实现Sigmoid层Affine层Softmax with Loss层 权重的更新——随机梯度下…

机械手末端快换技术:工业自动化的强大新动力

在飞速发展的工业自动化领域&#xff0c;机械手无疑是生产线上的关键成员&#xff0c;其性能与效率对整个生产流程的顺畅性与高效性起着至关重要的作用。而机械手末端快换技术&#xff0c;作为这一领域的创新性突破&#xff0c;正以其卓越的优势引领着工业生产的巨大变革。 机…

迷雾大陆免费辅助:强流派推荐攻略!VMOS云手机自动辅助挂机教程!

使用VMOS云手机辅助《迷雾大陆》游戏&#xff0c;让你的游戏体验更轻松高效。VMOS云手机专为《迷雾大陆》提供了定制版的云手机&#xff0c;内置游戏安装包&#xff0c;无需再次下载安装。同时&#xff0c;VMOS云手机支持免费的辅助工具&#xff0c;可以24小时不间断地辅助游戏…

多肽合成的一般步骤 -- 固相合成篇

1.1 溶剂的处理 DMF、甲醇在使用前用G3孔的分子筛浸泡过夜除杂质和水。 1.2 树脂的充分溶胀 称取2.0 g 空白Wang树脂于洁净干燥的反应管中&#xff0c;加入15 mL DMF&#xff0c;室温活化30 min左右。 1.3 接第一个氨基酸 室温下&#xff0c;通过沙芯抽滤掉上步溶剂&#xf…

中电金信 :基于开放架构的私有云建设实践

01开放架构私有云诞生背景 随着国产化创新建设的深化&#xff0c;产业侧行业软件持续进行云原生改造&#xff0c;金融机构拥抱云和容器技术&#xff0c;实现数智化转型已是大势所趋。近年&#xff0c;云原生技术以及架构发展速度更是惊人&#xff0c;私有云开始有了新架构、有了…

<刷题笔记> 力扣105/106题 使用中序+前(后)序构造二叉树

在曾经的博客中&#xff0c;曾经记录过这样一题&#xff1a; 二叉树遍历_牛客题霸_牛客网 (nowcoder.com) 这是一个只需要前序就能构造二叉树的题&#xff0c;因为一旦遇到空&#xff0c;就有"#"作为返回的标志&#xff0c;能够立刻返回。 1. 中序前序 完全可以借鉴…

select查询表单

select查询语法&#xff1a; select 【1】from 【2】where 【3】 1若为*表示显示全部数据列&#xff0c;若为某一列列名则只显示本列内容&#xff08;也可为多列列名&#xff09;。若在1后面加as ‘c’&#xff0c;则表示把查询的列名换成c。 2为要查询的表表名。 3为查询的…

众数信科 AI智能体智慧文旅解决方案——智能旅行助手

智慧文旅解决方案 智能旅行助手方案 利用先进的AI算法 提供个性化旅游体验的智能服务 众数信科AI智能体 产品亮点 旅游路线智能规划 旅游景点智能问答 旅行游记智能生成等 构建旅行实用指南 让旅游更加便捷、高效、智能化 关于我们 众数信科成立于2021年&#xff0c;由…

CentOS Linux教程(6)--CentOS目录

文章目录 1. 根目录2. cd目录切换命令3. CentOS目录介绍4. pwd命令介绍5. ls命令介绍5.1 ls5.2 ls -a5.3 ls -l 1. 根目录 Windows电脑的根目录是计算机(我的电脑)&#xff0c;然后C盘、D盘。 Linux系统的根目录是/&#xff0c;我们可以使用cd /进入根目录&#xff0c;然后使…

【mysql】case...when...、group...by、sum() 聚合函数... 企业组合使用实际场景示例

文章目录 查询需求场景预设查询结果SQL实现查询 查询需求场景 -- 统计当月不同流程类型的审批通过流程数、审批终止流程数、审批驳回流程数、新增流程数&#xff08;归档终止退回&#xff09;、申请总条目数&#xff08;关联任务单申请条目数总数&#xff09;-- 查询思路&…

蘑菇成熟待收检测系统源码分享

蘑菇成熟待收检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

最适配达梦、人大金仓的sql工具是什么?

SQLynx是一款功能强大的数据库管理工具&#xff0c;它不仅支持Oracle、MySQL等国际主流数据库&#xff0c;还很好地支持了武汉达梦、人大金仓等国产数据库。这款工具具有以下几个特点&#xff1a; 1.广泛支持&#xff1a;SQLynx支持多种数据库系统&#xff0c;包括PostgreSQL、…

ADC 位的作用

示波器的横轴表示时间基准&#xff08;秒/格或 s/p&#xff09;&#xff0c;而纵轴表示电压&#xff08;伏/格或 V/p&#xff09;。垂直精度是指示波器显示信号电压的准确程度&#xff0c;这对于视觉呈现和测量至关重要。示波器屏幕上的电压读数越接近实际信号电压&#xff0c;…