首页 > 编程语言 >Python3配合Django来调用钉钉在线api实时监测员工考勤打卡情况

Python3配合Django来调用钉钉在线api实时监测员工考勤打卡情况

时间:2023-01-24 14:44:23浏览次数:44  
标签:00 val res Django token str 打卡 考勤 id

基本上钉钉(dingding)作为一个远程办公平台来用的话,虽然差强人意,但是奈何市面上没有啥更好的选择,矬子里拔将军,也还是可以凑合用的,不过远程办公有个问题,就是每天需要检查员工的考勤,居家办公虽然灵活,但是大家究竟有没有办公,则是另外一回事。

钉钉提供的解决方案就是考勤在线打卡功能,但是检查出勤钉钉在移动端就有点费劲,需要在钉钉app里点击至少5次,还不能实时刷新,pc端的钉钉oa系统做的更烂,还不如移动端来得方便,另外如果你在一家上千人的企业里,这家企业有大大小小几十个部门,你又非常倒霉的担任这家公司的人事主管,每天按部门来出员工考勤报表就不是一件容易事了,所以利用钉钉开放的接口,使用Django自己打造一套实时监控员工考勤的web平台是我们本次的目的。

项目背景是一家普通科技公司,大概有五个部门,每个部门100人左右

 

首先进入钉钉开放平台 :open-dev.dingtalk.com

在企业内部开发中,选择小程序,新建一个小程序应用,这里其实也还有别的选择,比如h5微应用,主要是小程序兼容性更好一点。

填写应用的名称、简介、Logo等基本信息这些按下不表,按照要求填写即可,也不必非得填写真实信息,这里有个坑就是一定不要忘了配置安全域名或者ip,安全域名是当我们的检测平台上线的时候部署的域名,应用可以跟指定的域名进行网络通信,如果不配置的话,请求钉钉接口会报403错误。

 

另外还有一个坑,也就是钉钉默认开放的接口仅限于基础权限接口

 

如果需要考勤或者签到接口的话,还得单独点击申请,这就有点让人看不懂了,那么多接口,全都得靠用鼠标点击开通,不开通就用不了,这个用户体验真是让人非常酸爽,产品设计成这样,钉钉的pm难辞其咎。

 

OK,前置准备工作就已经就绪了,现在我们只要根据官方文档来写接口就可以了,选择服务端api文档:
https://ding-doc.dingtalk.com/doc#/serverapi2/gh60vz

钉钉考勤打卡的接口说明是这样的:

该接口用于返回企业内员工的实际打卡记录。比如,企业给一个员工设定的排班是上午9点和下午6点各打一次卡,但是员工在这期间打了多次,该接口会把所有的打卡记录都返回。
如果只要获取打卡结果数据,不需要详情数据,可使用获取打卡结果接口。
请求方式:POST(HTTPS)
请求地址:
https://oapi.dingtalk.com/attendance/listRecord?access_token=ACCESS_TOKEN
请求包结构体:
{
"userIds": ["001","002"],
"checkDateFrom": "yyyy-MM-dd hh:mm:ss",
"checkDateTo": "yyyy-MM-dd hh:mm:ss",
"isI18n":"false"
}

这里每个接口都需要一个access_token用来鉴权,这个token是用id和秘钥通过接口交换回来的,具体在应用详情里可以获取

 

这里我们封装成方法

import requests

appkey = '你的key'
appsecret = '你的秘钥'

api_url = "https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s"%(appkey,appsecret)

def get_token():
    res = requests.get(api_url)
    if res.status_code == 200:
        str_res = res.text
        token = (json.loads(str_res)).get('access_token')
        return token

搞定了token,还需要获取您的部门下所有员工的员工id,因为考勤接口参数只能接受员工id,而非部门id

#获取用户id
token = get_token()

#获取用户id
res = requests.get('https://oapi.dingtalk.com/user/simplelist?access_token=%s&department_id=235636048' % token)
str_res = res.text
res = json.loads(str_res)
ids = []
id_name = {}
for val in res['userlist']:
    ids.append(val['userid'])
    id_name[val['userid']] = val['name']

n = 50  #大列表中几个数据组成一个小列表
l = ids
biglist = [l[i:i + n] for i in range(0, len(l), n)]

最后请求考勤接口即可

result_all = []

#请求打卡接口
for x in biglist:
    res = requests.post('https://oapi.dingtalk.com/attendance/list?access_token=%s' % token,json ={'access_token':token,'workDateFrom':'%s 00:00:00' % mydate,'workDateTo':'%s 10:00:00' % mydate,'userIdList':str(x),'offset':0,'limit':50})
    str_res = res.text
    #print(str_res)
    res = json.loads(str_res)
    for xy in res['recordresult']:
        result_all.append(xy)

slist = []
for val in result_all:
    if val['timeResult'] == 'NotSigned':
        print(val['timeResult'])
        mydic = {}
        mydic[id_name[val['userId']]] = '未打卡'
        slist.append(mydic)

完整的后台Django后台接口

import requests
from rest_framework.response import Response
from rest_framework.views import APIView
import time

appkey = '你的key'
appsecret = '你的秘钥'

api_url = "https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s"%(appkey,appsecret)

def get_token():
    res = requests.get(api_url)
    if res.status_code == 200:
        str_res = res.text
        token = (json.loads(str_res)).get('access_token')
        return token

class GetQianHandler(APIView):

    def get(self,request):


        mydate = request.GET.get('date',None)

        if mydate == None:

            return Response({'message':'需要传递日期'})

        
        dt_start = '%s 00:00:00' % mydate
        dt_end = '%s 23:59:59' % mydate
        ts_start = int(time.mktime(time.strptime(dt_start, "%Y-%m-%d %H:%M:%S"))) * 1000
        ts_end = int(time.mktime(time.strptime(dt_end, "%Y-%m-%d %H:%M:%S"))) * 1000

        token = get_token()

        #获取用户id
        res = requests.get('https://oapi.dingtalk.com/user/simplelist?access_token=%s&department_id=235636048' % token)
        str_res = res.text
        res = json.loads(str_res)
        ids = []
        id_name = {}
        for val in res['userlist']:
            ids.append(val['userid'])
            id_name[val['userid']] = val['name']

        n = 50  #大列表中几个数据组成一个小列表
        l = ids
        biglist = [l[i:i + n] for i in range(0, len(l), n)]

        result_all = []

        print('workDateFrom %s 00:00:00' % mydate)

        #请求打卡接口
        for x in biglist:
            res = requests.post('https://oapi.dingtalk.com/attendance/list?access_token=%s' % token,json ={'access_token':token,'workDateFrom':'%s 00:00:00' % mydate,'workDateTo':'%s 10:00:00' % mydate,'userIdList':str(x),'offset':0,'limit':50})
            str_res = res.text
            #print(str_res)
            res = json.loads(str_res)
            for xy in res['recordresult']:
                result_all.append(xy)

        slist = []
        for val in result_all:
            if val['timeResult'] == 'NotSigned':
                print(val['timeResult'])
                mydic = {}
                mydic[id_name[val['userId']]] = '未打卡'
                slist.append(mydic)

        return Response(slist)

这样,就可以愉快的通过线上平台来实时监测部门员工考勤了,效果是这样的:

标签:00,val,res,Django,token,str,打卡,考勤,id
From: https://www.cnblogs.com/dituirenwu/p/17066074.html

相关文章

  • Django rest framework
    今天慢慢睁开眼睛,做了好吃的,看到下雪了,不过也没有小时候那种看到雪就要去打雪仗堆雪人的兴致,便打开教程刷了起来。昨天100多米买了Django的极客时间课程,说实话讲得还......
  • Django书籍学习记录
    没有记录回顾的学习都是白学,那天偶尔搜到这本书,其中除了一部分官网的中文翻译,还有一些没有了解到的地方,比如模型查询filter的链式调用,Q.F方法在定义化SQL中起到的作......
  • django rest_framework 视图api开发
     importjsonfromdjango.httpimportJsonResponsefromdjango.views.decorators.csrfimportcsrf_exemptfromdjango.viewsimportViewfromdjango.utils.decorator......
  • 【Django drf】 序列化类常用字段类和字段参数 定制序列化字段的两种方式 关系表外键
    目录序列化类常用字段类和字段参数常用字段类常用字段参数选项参数通用参数序列化类高级用法之sourcesource填写类中字段source填写模型类中方法source支持跨表查询定制序......
  • Django接入drf_yasg2 API接口文档-完整操作(包含错误处理)
    drf_yasg2的简介:drf-yasg是DjangoRestFramework的一个扩展,使⽤drf_yasg2下载⾃动⽣成的api⽂档的json或yaml⽂件配置项。drf_yasg2的安装:pipinstalldrf-yasg......
  • django-rest-swagger
    在日常工作中,程序员最苦恼的事情大概就是写文档了吧,虽然文档能够利于程序的传承,但是由于业务口径频繁变更,导致维护文档也变成了一件费时又费力的事情。因此,如果能够自动生......
  • Django[三]配置文件settings.py
    一.配置文件详细说明参考:http://c.biancheng.net/view/7475.html二、根据自己的需要修改配置文件1.修改DATABASES连接mysqlDATABASES={'default':{'E......
  • django FilteredRelation 的用法
    有两大用处FilteredRelation类允许为查询集增加一个ON从句可以在多个join中语句直接引用变量fromdjango.db.modelsimportFilteredRelation,Qresult_1=Restaur......
  • django的 prefetch_related 只能 all() 可以用 filter ?
    直接说答案<=Django1.6只能在使用代码过滤somethings=Foo.objects.filter(author="author").prefetch_related("bar_set")forainsomethings:somebars=[p......
  • Django一个“高质量”小白的学习之路(给自己看)
     第一天day1:人类的思维倾向于直白、视觉和线性,还有好奇心,这是祖先遗传下来的思维习惯。如果论结果,显然我是一个计算机学习的失败者。因为我作为一个已经刚到不惑之年......