首页
关于
留言
友联
更多
壁纸
统计
Search
1
VUE codemirror插件 设置回显对象
67 阅读
2
js前端密码校验
65 阅读
3
HTML媒体查询Demo
60 阅读
4
Vue 和element的实现table表格数据的模糊匹配搜索
46 阅读
5
python 爬虫
35 阅读
默认分类
前端
后端
其他
登录
Search
标签搜索
python
React
Django
爬虫
css
2c
累计撰写
19
篇文章
累计收到
12
条评论
首页
栏目
默认分类
前端
后端
其他
页面
关于
留言
友联
壁纸
统计
搜索到
19
篇与
的结果
2023-01-09
IP批量格式化处理vue
最近遇到个IP批量格式化的功能,废话不说 开始上代码首先输入框输入 大量IP 用户会输入各种恶心变态的 中文的 逗号 句号 反正就是各种符号我们要先处理一下formIp() { // console.log(this.formData.ip); // 非数字和点的字符变成逗号 let str = this.formData.ip.replace(/[^\d.\-\/]/gi, ","); // console.log(str); // 把ip截取成数组 let ipArr = str.split(","); // console.log(ipArr); this.ipArr = ipArr; //验证IP和IP段 this.ipformData(); },接下来验证IP或IP段是否 正确 // ip一键格式化 ipformData() { //提交创建状态(可以删除,我的项目用到了) this.formIP = true; this.charIp = []; let ip = []; let errorIp = []; this.ipArr.forEach((item) => { // console.log(item); // 判断ip不是空 if (item != "") { // 先判断是否是正常的ip 如果不是 判断是否是IP段 if (this.isValidIP(item)) { // 如果是正常IP添加到数组 ip.push(item); } else { // 不是正常IP验证是否是IP段 // console.log(this.isValidIPs(item)); if (this.isValidIPs(item)) { // 如果是IP段添加数组 ip.push(item); } else { // 不是IP段添加到错误的IP数组 errorIp.push(item); } } } else { } }); // console.log(errorIp); // console.log(ip); this.processingIp = ip; this.errorIp = errorIp; // 如果有错误IP显示错误提示 if (errorIp.length > 0) { this.ipState = true; //这个换行 是结果放在头部 提醒用户 IP不正确 errorIp.push("\n"); errorIp.push("\n"); } else { this.ipState = false; } //每隔一行换行 ip.forEach((item, index) => { this.charIp.push(item + "," + "\n"); }); if (errorIp.length > 0) { this.charIp.unshift(errorIp); } // console.log(this.charIp.join("")); var reg = /,$/gi; this.formData.ip = this.charIp .join("") .replace(reg, "") .replace(/,/g, ""); // console.log(this.formData.ip); }, 然后就是IP和IP段的校验 // IP正则 isValidIP(ip) { var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/; return reg.test(ip); }, // IP段正则(可以是-也可以是/) isValidIPs(ip) { var reg = /^(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/|\-([1-9]|[1-2]\d|3[0-2])$/; return reg.test(ip); },
2023年01月09日
18 阅读
0 评论
0 点赞
2022-11-24
js 本地搜索(多条件)+本地分页
let arr = [{ name: "q1121", age: 12, address: "辽宁大连1" }, { name: "q44", age: 12, address: "辽宁大连4" }, { name: "q55", age: 12, address: "辽宁大连5" }, { name: "q222", age: 13, address: "辽宁大连2" }, { name: "q332", age: 12, address: "辽宁沈阳1" } ]; //筛选条件 let filter = { name: "", age: 12, address: "辽宁", }; //拿到有值的参数 let tempFilter = {}; for(key in filter) { if(typeof(filter[key]) != "undefined" && typeof(filter[key]) != "null" && filter[key] != null && filter[key] != "") { tempFilter[key] = filter[key]; } } //筛选 let resultArr = arr.filter( (item) => { let flag = false; for(key in tempFilter) { if(item[key].toString().indexOf(tempFilter[key].toString()) >= 0) { flag = true; } else { flag = false; break; } } if(flag) { return item; } } ); console.log(JSON.stringify(resultArr)); //[ // {"name":"q1121","age":12,"address":"辽宁大连1"}, // {"name":"q44","age":12,"address":"辽宁大连4"}, // {"name":"q55","age":12,"address":"辽宁大连5"}, // {"name":"q332","age":12,"address":"辽宁沈阳1"} //] } 分页pagination: { total: 0, currentPage: 1, pageSize: 10, pageSizes: [10, 20, 30, 50, 100], }, ------------ tableList: function () { return this.tableData.slice( (this.pagination.currentPage - 1) * this.pagination.pageSize, this.pagination.currentPage * this.pagination.pageSize ); },原文章
2022年11月24日
16 阅读
0 评论
0 点赞
2022-10-25
jenkins docker 部署 前端
搭建好Jenkins 下载插件 Publish Over SSH Node Docker文件格式 DockerfileFROM nginx:1.17.0-alpine LABEL maintainer = 1054711110@qq.com COPY nginx/nginx.conf /etc/nginx/nginx.conf COPY nginx/default.conf /etc/nginx/conf.d COPY src /usr/share/nginx/htmldocker-compose.yamlversion: '3' services: # 前端 service-front: hostname: service-front container_name: service-front image: registry.cn-hangzhou.aliyuncs.com/lazycat520/moka-frontend:V-NUMBER restart: always ports: - "81:80" volumes: - /etc/timezone:/etc/timezone - /etc/localtime:/etc/localtimenginx/default.confserver { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; # try_files $uri $uri/ /index.html; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }nginx/nginx.confuser nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; #gzip_http_version 1.0; gzip_comp_level 8; gzip_types application/json application/octet-stream text/plain application/javascript application/css text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary off; gzip_disable "MSIE [1-6]\."; include /etc/nginx/conf.d/*.conf; }jenkins 节点配置 阿里镜像 registry.cn-hangzhou.aliyuncs.com/lazycat520/moka-frontend:V${BUILD_NUMBER}sed -i 's/V-NUMBER/V${BUILD_NUMBER}/g' docker-compose.yaml && docker-compose up -d
2022年10月25日
27 阅读
0 评论
0 点赞
2022-10-20
nas内网穿透
用到了frp穿透 剩下跟着参考资料 直接穿透 Windows Linux
2022年10月20日
25 阅读
0 评论
0 点赞
2022-07-25
VUE codemirror插件 设置回显对象
this.code = JSON.stringify(this.code, null, "\t");JSON.stringify(this.code, null, "\t"); 这个最重要,JSON.stringify的第三个属性就是让我们格式化代码用的,你也可以直接传入数字x(10以内),就表示前面是x个空格的距离,我是用'\t',这样就是一个tab的距离了。原文章
2022年07月25日
67 阅读
0 评论
0 点赞
2022-06-16
js前端密码校验
强密码校验的校验规则长度8-20位必须包含数字必须包含字母可以包含常用特殊字符不能含有4位连续相同的字符(例如:1111, aaaa)不能含有4位连续的字母(例如:Abcd, lmno)不能含有4位连续的数字(例如:1234, 8901)不能含有4位键盘横向方向连续的字母(例如:qwer)不能含有4位键盘斜向方向连续的字符(例如:1qaz)function validPwd (pwd) { let regex = /(?=.*[0-9])(?=.*[a-zA-Z]).{8,20}/ // 字母连续规则 let strReg = /(a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)|z(?=a)){3}[a-z]/i // 数字连续规则 let numReg = /(0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){3}\d/ // 键盘字母横向连续规则 let keyboardHorizontalReg = /(q(?=w)|w(?=e)|e(?=r)|r(?=t)|t(?=y)|y(?=u)|u(?=i)|i(?=o)|o(?=p)|p(?=q) |a(?=s)|s(?=d)|d(?=f)|f(?=g)|g(?=h)|h(?=j)|j(?=k)|k(?=l)|l(?=a) | z(?=x)|x(?=c)|c(?=v)|v(?=b)|b(?=n)|n(?=m)|m(?=z)){3}[a-z]/i // 多个相同字母、数字规则 let sameReg = /(\w)\1{3}/i /** * 键盘斜线的4个字符是否在pwd里面 */ function isStrInSlope(pwd){ let keyboardSlopeArr = ["1qaz", "2wsx", "3edc", "4rfv", "5tgb", "6yhn", "7ujm", "8ik,","9ol.", "0p;/", "=[;.", "-pl,", "0okm", "9ijn", "8uhb", "7ygv", "6tfc", "5rdx", "4esz"] return keyboardSlopeArr.some(v => pwd.toLowerCase().indexOf(v) > -1) } if (regex.test(pwd)){ if (sameReg.test(pwd)) { return '密码不能含有连续4位相同的数字或字母' } else if (strReg.test(pwd)){ return '密码不能含有4位连续的字母' } else if (numReg.test(pwd)){ return '密码不能含有4位连续的数字' } else if (keyboardHorizontalReg.test(pwd)){ return '密码不能含有4位键盘横向方向连续的字母' } else if (isStrInSlope(pwd)){ return '密码不能含有4位键盘斜向方向连续的字符' } return '' } return '您的密码复杂度太低(密码中必须包含字母、数字、特殊字符),请重新设置密码' } 字母数字不重复3次 var arr = str.split(""); var flag = true; for (var i = 1; i < arr.length - 1; i++) { var firstIndex = arr[i - 1].charCodeAt(); var secondIndex = arr[i].charCodeAt(); var thirdIndex = arr[i + 1].charCodeAt(); thirdIndex - secondIndex == 1; secondIndex - firstIndex == 1; if (thirdIndex - secondIndex == 1 && secondIndex - firstIndex == 1) { flag = false; } } if (!flag) { console.log("不能输入连续字符", str); console.log(flag, "flag"); return flag; } return flag;包含数字 字母 包含某一字符 10位 "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[\@]).{10,}$"原文章 原文章
2022年06月16日
65 阅读
2 评论
0 点赞
2022-06-09
js标准时间转换
转换成2022-06-09 00:00:00这种formatDateTime(e) { var date = new Date(e); var y = date.getFullYear(); var m = date.getMonth() + 1; //返回值(0~11) m = m < 10 ? ('0' + m) : m; var d = date.getDate(); d = d < 10 ? ('0' + d) : d; var h = date.getHours(); h = h < 10 ? ('0' + h) : h; var minute = date.getMinutes(); minute = minute < 10 ? ('0' + minute) : minute; var second = date.getSeconds(); second = second < 10 ? ('0' + second) : second; return y + '-' + m + '-' + d +' '+ h + ':' + minute + ':' + second; }原文章
2022年06月09日
18 阅读
0 评论
0 点赞
2022-05-23
Vue 和element的实现table表格数据的模糊匹配搜索
<template> <div class="dormitory"> <div class="searchWord"> <div style="display: inline-block"> 搜索:</div> <el-input v-model="search" style="display: inline-block;width: 1300px" placeholder="请输入搜索内容"> </el-input> </div> // 遍历表格 <div class="dormitoryData"> <el-table ref="dormitoryTable" :data="tables" tooltip-effect="dark" stripe style="width: 100%"> <el-table-column type="selection" width="45"></el-table-column> <el-table-column label="序号" type="index" width="65"></el-table-column> <el-table-column label="人物" prop="people"> </el-table-column> <el-table-column label="关系" prop="relationship"> </el-table-column> <el-table-column label="初见" prop="meet"> </el-table-column> <el-table-column label="地点" prop="place"> </el-table-column> <el-table-column label="昵称" prop="execg"> </el-table-column> <el-table-column label="认识年限" prop="year"> </el-table-column> <el-table-column label="成名之做" prop="works"> </el-table-column> </el-table> </div> </div> </template> <script> export default { data () { return { dormitory: [{ people: '雷森', relationship: '大学室友', meet: '2010-09-02', place: '图书馆', execg: '胖子', year: '8年', works: '海阔天空' }, { people: '刘利伟', relationship: '大学室友', meet: '2010-09-02', place: '5#633', execg: '老大', year: '8年', works: '勇气' }, { people: '李金龙', relationship: '大学室友', meet: '2010-09-02', place: '5#633', execg: '二哥', year: '8年', works: '碰见' }, { people: '马康', relationship: '大学室友', meet: '2010-09-02', place: '餐饮大厦', execg: '康哥', year: '8年', works: '再也不联系' }, { people: '牛光卫', relationship: '大学室友', meet: '2010-09-02', place: '图书馆', execg: '牛牛娃', year: '8年', works: '断点' }, { people: '陆兆攀', relationship: '大学室友', meet: '1991-07-27', place: '百浪', execg: '帅哥', year: '27年', works: '再也不犹豫' }, { people: '小甜', relationship: '亲密的人', meet: '2016-10-05', place: '小寨', execg: '甜甜圈', year: '2年', works: 'Forever Love' }], search: '' } }, computed: { // 模糊搜索 tables () { const search = this.search if (search) { // filter() 方法建立一个新的数组,新数组中的元素是经过检查指定数组中符合条件的全部元素。 // 注意: filter() 不会对空数组进行检测。 // 注意: filter() 不会改变原始数组。 return this.dormitory.filter(data => { // some() 方法用于检测数组中的元素是否知足指定条件; // some() 方法会依次执行数组的每一个元素: // 若是有一个元素知足条件,则表达式返回true , 剩余的元素不会再执行检测; // 若是没有知足条件的元素,则返回false。 // 注意: some() 不会对空数组进行检测。 // 注意: some() 不会改变原始数组。 return Object.keys(data).some(key => { // indexOf() 返回某个指定的字符在某个字符串中首次出现的位置,若是没有找到就返回-1; // 该方法对大小写敏感!因此以前须要toLowerCase()方法将全部查询到内容变为小写。 return String(data[key]).toLowerCase().indexOf(search) > -1 }) }) } return this.dormitory } }, methods: { } } </script>
2022年05月23日
46 阅读
0 评论
0 点赞
2022-05-23
vue 动态列筛选
实现代码:HTML部分就是用一个多选框组件展示列选项用v-if="colData[i].istrue"控制显示隐藏,把列选项传到checkbox里再绑定勾选事件。<el-popover placement="right" title="列筛选" trigger="click" width="420"> <el-checkbox-group v-model="checkedColumns" size="mini"> <el-checkbox v-for="item in checkBoxGroup" :key="item" :label="item" :value="item"></el-checkbox> </el-checkbox-group> <el-button slot="reference" type="primary" size="small" plain><i class="el-icon-arrow-down el-icon-menu" />列表项展示筛选</el-button> </el-popover><el-table :data="attendanceList" @sort-change="sort" highlight-current-row :row-class-name="holidayRow" @selection-change="editAll" ref="multipleTable"> <el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column label="员工基本信息"> <el-table-column v-if="colData[0].istrue" align="center" prop="user_id" label="工号" width="80" fixed></el-table-column> <el-table-column v-if="colData[1].istrue" align="center" prop="name" label="姓名" width="80" fixed></el-table-column> <el-table-column v-if="colData[2].istrue" align="center" prop="age" label="年龄" width="60"></el-table-column> <el-table-column v-if="colData[3].istrue" align="center" prop="gender" label="性别" width="80"></el-table-column> <el-table-column v-if="colData[4].istrue" align="center" prop="department" label="部门名称" width="100"></el-table-column> </el-table-column> </el-table>js 数据存放的data部分//列表动态隐藏 colData: [ { title: "工号", istrue: true }, { title: "姓名", istrue: true }, { title: "年龄", istrue: true }, { title: "性别", istrue: true }, { title: "部门名称", istrue: true }, ], checkBoxGroup: [], checkedColumns: [],js 方法实现部分created() { // 列筛选 this.colData.forEach((item, index) => { this.checkBoxGroup.push(item.title); this.checkedColumns.push(item.title); }) this.checkedColumns = this.checkedColumns let UnData = localStorage.getItem(this.colTable) UnData = JSON.parse(UnData) if (UnData != null) { this.checkedColumns = this.checkedColumns.filter((item) => { return !UnData.includes(item) }) } }, // 监控列隐藏 watch: { checkedColumns(val,value) { let arr = this.checkBoxGroup.filter(i => !val.includes(i)); // 未选中 localStorage.setItem(this.colTable, JSON.stringify(arr)) this.colData.filter(i => { if (arr.indexOf(i.title) != -1) { i.istrue = false; } else { i.istrue = true; } }); } },
2022年05月23日
18 阅读
0 评论
0 点赞
2022-05-19
js通过id pid 遍历集合获得树结构
node=[{id:1,pid:0,name:"吉林省"}, {id:2,pid:1,name:"长春市"}, {id:3,pid:1,name:"松原市"}, {id:4,pid:0,name:"辽宁省"}, {id:5,pid:4,name:"沈阳市"}, {id:6,pid:3,name:"扶余县"} ] /* 通过定义map,key当前对象id, value该对象 遍历集合,得到对象顶级节点放到集合中返回 不是顶级的就是当前对象的子节点,将对象放到该节点下,这一段比较抽象 */ function toTree(node){ node.forEach(function(it){ delete it.children; }) // 定义map/ var map = {}; // 这里可以重构数据类型,放回字段值 node.forEach(function(it){ map[it.id]=it; }) // 定义返回集合 var val=[]; node.forEach(function(it){ var parent = map[it.pid]; if(parent){ // 有数据说明不是顶级节点,将数据放到该 children 子节点下 ((parent.children) || (parent.children=[])).push(it); }else{ // 没有数据说明是顶级节点放到val中 val.push(it); } }); return val; } console.log(JSON.stringify(toTree(node)))`` 原文章
2022年05月19日
23 阅读
0 评论
0 点赞
2022-04-28
css渐变
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> </body> </html> <style> body { width: 100%; height: 100vh; /* background: linear-gradient(#0088dd, #e493d0, #e63123); */ background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 254, 1), rgba(170, 142, 254, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0)); animation: identifier 10s infinite; } body::after { content: ''; display: block; position: fixed; width: 100%; height: 100%; top: 0; left: 0; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); } @keyframes identifier { 0% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax; } 10% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -70vmax -70vmax, 50vmax -20vmax, 10vmax 10vmax, -10vmax -10vmax, 40vmax 20vmax; } 20% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -20vmax -50vmax, 60vmax -20vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 60vmax; } 30% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -40vmax -10vmax, 20vmax 10vmax; } 50% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -80vmax -80vmax, 50vmax -10vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax; } 60% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -10vmax -20vmax, 10vmax -10vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax; } 70% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -10vmax -20vmax, 70vmax -50vmax, 50vmax 40vmax, -30vmax -10vmax, 20vmax 10vmax; } 100% { background-size: 130vmax 140vmax, 130vmax 140vmax; background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax; } } </style>
2022年04月28日
20 阅读
2 评论
0 点赞
2022-04-28
HTML媒体查询Demo
<meta name="viewport" content="width=device-width, initial-scale=1.0">首页代码<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="./index1.css"> <link rel="stylesheet" href="./index2.css"> <link rel="stylesheet" href="./index3.css"> </head> <body> <div class="myDiv"> </div> </body> </html>通过 @media (min-width:1200px) and (max-width:1920px){} 来设定屏幕大小来触发这个CSSindex1.css@media (min-width:1200px) and (max-width:1920px){ .myDiv{ width: 100%; height: 100vh; background: yellow; } }index2.css@media (min-width:800px) and (max-width:1200px){ .myDiv{ width: 100%; height: 100vh; background: red; } }index3.css@media (min-width:300px) and (max-width:800px){ .myDiv{ width: 100%; height: 100vh; background: pink; } }
2022年04月28日
60 阅读
1 评论
0 点赞
2022-04-28
python Django增删改查 快速体验
先创建个app子级python .\manage.py startapp app01 ## 然后创建数据模型 **app01下的** **modules.py文件**from django.db import models # Create your models here. class UserInfo(models.Model): name=models.CharField(max_length=32) password=models.CharField(max_length=12) age=models.IntegerField() tel=models.IntegerField(max_length=11)配置数据库'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '数据库名', 'USER': '数据库用户名', 'PASSWORD': '密码', 'HOST': '127.0.0.1', 'PORT': '3306', }迁移数据库python manage.py makemigrations 和 python manage.py migrate写路由urlfrom django.contrib import admin from django.urls import path,include from app01 import views urlpatterns = [ # path('admin/', admin.site.urls), # path('index/',views.index), # path('user/list/', views.user_list), # path('login/', views.ApiLogin.as_view()), # path('del/', views.ApiDel.as_view()), path('add/', views.addUser.as_view()), path('user/', views.UserList.as_view()), path('updateuser/', views.upDateUser.as_view()), path('del/', views.deluser.as_view()), ] 4.view页面编写增删改查from django.shortcuts import render,HttpResponse from rest_framework.views import APIView # Create your views here. from django import views from app01.models import UserInfo from rest_framework.response import Response from app01.ser import APIViewUserInfo class addUser(APIView): def post(self,request): obj=APIViewUserInfo(data=request.data) if obj.is_valid(): obj.save() return Response({"data":obj.data, "status" : 201,"message":"添加用户成功"}) return Response(data=obj.errors,status=400) class UserList(APIView): def get(self,request): obj=UserInfo.objects.all() ser=APIViewUserInfo(instance=obj,many=True) return Response(ser.data) class upDateUser(APIView): def post(self,request): print(request.data.get('id')) i=request.data.get('id') try: user=UserInfo.objects.get(id=i) except Exception as e: return Response(data='不存在', status=201) # 创建序列化对象,并将要反序列化的数据传递给data构造参数,进而进行验证 user.password=request.data.get('password') if request.data.get('name')!='': print(request.data.get('name')=='') user.name=request.data.get('name') user.save() return Response(status=400) class deluser(APIView): def post(self,request): id=request.data.get('id') UserInfo.objects.filter(id=id).delete() return Response({"msg":'删除成功',"state":"true"}) # def index(request): # return HttpResponse("欢迎使用") # # # def user_list(request): # return render(request,"user_list.html") # # class ApiLogin(APIView): # def get(self,request): # return HttpResponse('get') # def post(self,request): # UserInfo.objects.create(name='张三',password='123456',age=15,tel='1234567891') # obj=UserInfo.objects.all() # print(obj) # return HttpResponse('post') # # class ApiDel(APIView): # def post(self,request): # UserInfo.objects.filter(id=4).delete() # return HttpResponse('删除成功')5.序列化 反序列化# -*- coding: utf-8 -*- from rest_framework import serializers from app01.models import UserInfo class APIViewUserInfo(serializers.Serializer): """图书数据序列化器""" id = serializers.IntegerField(label='ID', read_only=True) # 主键序列化 # 第一:普通字段序列化 name = serializers.CharField(label='名称', max_length=20) password = serializers.CharField(label='密码') age = serializers.IntegerField(label='年龄', required=False) tel = serializers.IntegerField(label='电话', required=False) # # 第二:一对多字段序列化 # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # # 第三:自定义显示(显示多对多) # xxx = serializers.SerializerMethodField(read_only=True) class Meta: model = UserInfo # 自定义显示 多对多 字段 # 定义创建语法:ser.save()执行,就会立刻调用create方法用来创建数据 def create(self, validated_data): '''validated_data: 表单或者vue请求携带的json:{"username":"zhangsan","password":"123456"}''' return self.Meta.model.objects.create(**validated_data)
2022年04月28日
20 阅读
0 评论
0 点赞
2022-04-28
Django JWT token 登录注册
setting.py INSTALLED_APPS = [ ... 'rest_framework', 'rest_framework.authtoken', 'corsheaders', # 添加 django-cors-headers 使其可以进行 cors 跨域 'app01', ... ]MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] CORS_ORIGIN_ALLOW_ALL=True # jwt载荷中的有效期设置 JWT_AUTH = { # 1.token前缀:headers中 Authorization 值的前缀 'JWT_AUTH_HEADER_PREFIX': 'JWT', # 2.token有效期:一天有效 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # 3.刷新token:允许使用旧的token换新token,接口对接需要设置为true 'JWT_ALLOW_REFRESH': True, # 4.token有效期:token在24小时内过期, 可续期token 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24), # 5.自定义JWT载荷信息:自定义返回格式,需要手工创建 'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.views.jwt_response_payload_handler', } # AUTHENTICATION_BACKENDS = ['user.utils.EmailAuthBackend'] # 在DRF配置文件中开启认证和权限 REST_FRAMEWORK = { # 用户登陆认证方式 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 在DRF中配置JWT认证 # 'rest_framework.authentication.SessionAuthentication', # 使用session时的认证器 # 'rest_framework.authentication.BasicAuthentication' # 提交表单时的认证器 ], # 权限配置, 顺序靠上的严格 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAdminUser', # 管理员可以访问 'rest_framework.permissions.IsAuthenticated', # 全局配置只有认证用户可以访问接口 # 'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 认证用户可以访问, 否则只能读取 # 'rest_framework.permissions.AllowAny', # 所有用户都可以访问 ], }urls.pyfrom django.urls import include, path from rest_framework.authtoken.views import obtain_auth_token from app01 import views from rest_framework_jwt.views import obtain_jwt_token from django.contrib import admin urlpatterns = [ path('admin/', admin.site.urls), path('login/', obtain_jwt_token), # 登录url,用于获取token path('register/', views.RegisterView.as_view()), # 注册视图, /user/register/ path('adduser/',views.adduserList.as_view()), path('getuserlist/', views.getuserlist.as_view()), ] views.pyfrom rest_framework.permissions import AllowAny from .models import * from .ser import seruserlist,sergetuserList from django.contrib.auth.backends import ModelBackend from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination def jwt_response_payload_handler(token, user=None, request=None): """ 自定义jwt认证成功返回数据 """ return { 'token': token, 'user_id': user.id, 'username': user.username, "code": 200, "state": True } class RegisterView(APIView): """ 用户注册, 权限是: 匿名用户可访问 """ # 自定义权限类 permission_classes = (AllowAny,) def post(self, request): """ 接收邮箱和密码, 前端校验两遍一致性, 注册成功后返回成功, 然后用户自行登录获取token 1. 随机用户名 2. 生成用户 3. 设置用户密码 4. 保存用户 :param request: :return: {'code':0,'msg':'注册成功'} """ email = request.data.get('email') passwrod = request.data.get('password') username = request.data.get('username') if all([email, passwrod]): pass else: return Response({'code': 9999, 'msg': '参数不全'}) user = User(username=username, email=email) user.set_password(passwrod) # 密码加密 user.save() return Response({'code': 0, 'msg': '注册成功'}) # 用户添加 class adduserList(APIView): # 自定义权限类 def post(self, request): ser=seruserlist(data=request.data) if ser.is_valid(): ser.save() return Response({"msg": '成功',"code":200}) return Response(data=ser.errors,status=400) # 分页(局部):自定义分页器 局部 class PageNum(PageNumberPagination): # 查询字符串中代表每页返回数据数量的参数名, 默认值: None page_size_query_param = 'page_size' # 查询字符串中代表页码的参数名, 有默认值: page page_query_param = 'page' # 一页中最多的结果条数 # max_page_size = 2 # 查询用户 class getuserlist(APIView): def get(self, request): queryset = userlist.objects.all() print(request) if request.GET.get('page'): print(queryset) # 分页 pg = PageNum() page_objs = pg.paginate_queryset(queryset=queryset, request=request, view=self) ser = sergetuserList(instance=page_objs, many=True) # 关联数据多条 return Response(ser.data) ser = sergetuserList(instance=queryset, many=True) # 关联数据多条 return Response(ser.data)
2022年04月28日
18 阅读
0 评论
0 点赞
2022-04-28
react 封装API
http.js/** * 网络请求配置 */ import axios from "axios"; axios.defaults.timeout = 100000; axios.defaults.baseURL = "http://127.0.0.1:8000/"; /** * http request 拦截器 */ axios.interceptors.request.use( (config) => { config.data = JSON.stringify(config.data); config.headers = { "Content-Type": "application/json", }; return config; }, (error) => { return Promise.reject(error); } ); /** * http response 拦截器 */ axios.interceptors.response.use( (response) => { if (response.data.errCode === 2) { console.log("过期"); } return response; }, (error) => { console.log("请求出错:", error); } ); /** * 封装get方法 * @param url 请求url * @param params 请求参数 * @returns {Promise} */ export function get(url, params = {}) { return new Promise((resolve, reject) => { axios.get(url, { params: params, }).then((response) => { landing(url, params, response.data); resolve(response.data); }) .catch((error) => { reject(error); }); }); } /** * 封装post请求 * @param url * @param data * @returns {Promise} */ export function post(url, data) { return new Promise((resolve, reject) => { axios.post(url, data).then( (response) => { //关闭进度条 resolve(response.data); }, (err) => { reject(err); } ); }); } /** * 封装patch请求 * @param url * @param data * @returns {Promise} */ export function patch(url, data = {}) { return new Promise((resolve, reject) => { axios.patch(url, data).then( (response) => { resolve(response.data); }, (err) => { msag(err); reject(err); } ); }); } /** * 封装put请求 * @param url * @param data * @returns {Promise} */ export function put(url, data = {}) { return new Promise((resolve, reject) => { axios.put(url, data).then( (response) => { resolve(response.data); }, (err) => { msag(err); reject(err); } ); }); } //统一接口处理,返回数据 export default function (fecth, url, param) { let _data = ""; return new Promise((resolve, reject) => { switch (fecth) { case "get": console.log("begin a get request,and url:", url); get(url, param) .then(function (response) { resolve(response); }) .catch(function (error) { console.log("get request GET failed.", error); reject(error); }); break; case "post": post(url, param) .then(function (response) { resolve(response); }) .catch(function (error) { console.log("get request POST failed.", error); reject(error); }); break; default: break; } }); } //失败提示 function msag(err) { if (err && err.response) { switch (err.response.status) { case 400: alert(err.response.data.error.details); break; case 401: alert("未授权,请登录"); break; case 403: alert("拒绝访问"); break; case 404: alert("请求地址出错"); break; case 408: alert("请求超时"); break; case 500: alert("服务器内部错误"); break; case 501: alert("服务未实现"); break; case 502: alert("网关错误"); break; case 503: alert("服务不可用"); break; case 504: alert("网关超时"); break; case 505: alert("HTTP版本不受支持"); break; default: } } } /** * 查看返回的数据 * @param url * @param params * @param data */ function landing(url, params, data) { if (data.code === -1) { } } api.jsimport http from './http'; /** * 获取首页列表 */ function login(data) { return http("post", '/login/',data); } export { login }
2022年04月28日
17 阅读
0 评论
0 点赞
1
2