MySQL 按照 in 排序

mysql> select * from auth_permission where id in (23, 4,12, 4,1);
+----+----------------------------+-----------------+-----------------------+
| id | name                       | content_type_id | codename              |
+----+----------------------------+-----------------+-----------------------+
|  1 | Can add bookmark           |               1 | add_bookmark          |
|  4 | Can add pinned application |               2 | add_pinnedapplication |
| 12 | Can delete permission      |               4 | delete_permission     |
| 23 | Can change session         |               8 | change_session        |
+----+----------------------------+-----------------+-----------------------+
4 rows in set (0.00 sec)

默认in查询结果集都会使用id排序

1. 使用field函数

FIELD(str,str1,str2,str3,...)
Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found.

mysql> select * from auth_permission where id in (23, 4,12, 4,1) order by field(id,23,4,12,4,1);
+----+----------------------------+-----------------+-----------------------+
| id | name                       | content_type_id | codename              |
+----+----------------------------+-----------------+-----------------------+
| 23 | Can change session         |               8 | change_session        |
|  4 | Can add pinned application |               2 | add_pinnedapplication |
| 12 | Can delete permission      |               4 | delete_permission     |
|  1 | Can add bookmark           |               1 | add_bookmark          |
+----+----------------------------+-----------------+-----------------------+
4 rows in set (0.00 sec)

2. 使用关联查询

教务系统爬虫的微信小程序

之前在路由器上装的 node.js 运行环境运行的一个抓取脚本现在派上用了。

那么问题来了

1. GBK 编码


首先要解决的教务系统网站 GBK 编码问题,参考过去的记录 《node get post提交中文参数》


更新
发现微信的 wx.request(OBJECT) API 可以直接向 GBK 网站请求,返回的就是 UTF8 字符

wx.request({
  url: 'test.php',
  data: {
     x: '' ,
     y: ''
  },
  header: {
      'Content-Type': 'application/json'
  },
  success: function(res) {
    console.log(res.data) // 自动编码转换
  }
})

2. 使用 npm package

MINA 框架带有require函数加载依赖,但并不是完整的 CommonJS,require 函数仅仅能够加载项目中的文件,而且必须严格定义 JS 文件路径,路径不支持 CommonJS 的路径风格。

需要直接使用相对路径,并且需要指定后缀。

require('node_modules/lodash/map.js');

3. 获取二进制的图片对象

内置的 wx.request(OBJECT) 对象只有返回 Date 和 errorMSg 无法满足需求。

还好 JScore 环境依然提供了本地的 XMLHttpRequest 对象,可以直接调用原生办法。

var getBase64File = function( url, callback ) {
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      var headers = xhr.getAllResponseHeaders();
      callback( reader.result, headers );
    }
    reader.readAsDataURL( xhr.response );
  };
  xhr.open( 'GET', url );
  xhr.send();
}

getBase64('test.jpg', function (base64, headers){
  console.log(headers);
}

4. 微信小程序跨域限制

这是从 Chrome 控制台看到的响应头

HTTP/1.1 200 OK
Date: Fri, 30 Sep 2016 12:46:33 GMT
Server: Microsoft-IIS/6.0
MicrosoftOfficeWebServer: 5.0_Pub
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Set-Cookie: ASP.NET_SessionId=hw4tpo55f4005ojii14d2e3r; path=/
Cache-Control: private
Content-Type: image/Gif; charset=gb2312
Content-Length: 2245

这是从 XMLHttpRequest.getAllResponseHeaders() 获取到的信息

Date: Fri, 30 Sep 2016 12:46:33 GMT
Server: Microsoft-IIS/6.0
X-AspNet-Version: 1.1.4322
X-Powered-By: ASP.NET
MicrosoftOfficeWebServer: 5.0_Pub
Content-Type: image/Gif; charset=gb2312
Access-Control-Allow-Origin: *
Cache-Control: private
Access-Control-Allow-Headers: X-Requested-With, Content-Type
Content-Length: 2245

浏览器同源策略,为了安全,同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式

CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

因为跨域限制,暂时没找到小程序去获取 Cookie 的办法,当然这里指的是是仅仅依靠小程序而不依赖自己的应用服务器去处理的情况(实际上小程序也不应当有过多的逻辑处理,仅仅当作一个显示的层面)。

5. Nginx 反向代理解决跨域问题

参考阮一峰的《跨域资源共享 CORS 详解》

解决方案是在服务端响应头加入允许跨域的字段说明

location ~/ {
    add_header 'Access-Control-Allow-Origin' 'https://docs.domain.com';  
    add_header 'Access-Control-Allow-Credentials' 'true';  
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS'; 
    proxy_pass http://target.com;
}

如果需要匹配所有访问域名可以使用 add_header 'Access-Control-Allow-Origin' '*'

还是写个服务端吧,客户端不适合做这么多处理

黑客马拉松

QQ图片20161007204633.jpg

这几天参加了 ifanr 和 segmentfault 举办的未来小程序为主题的和黑客马拉松活动,作为一名志愿者围观了几十位参赛选手的开发过程,见识到了八个短短二十个小时内完成的设计别出心裁新颖的项目。

关于技术:

  1. ECMAScript 6 在 iOS 10 上出现兼容问题问题,模拟器上运行正常,真机演示却出现了问题;
  2. 限制访问域名,只有五个安全域名可以授权,可能需要反代解决外部资源引用的问题;
  3. 突出“小”的内容,微信小程序限制打包资源 1MB,如果使用图片资源最好使用矢量图或者使用适当的压缩,如果使用外部资源,也只能够提供 5MB 的本地存储,过多的资源也会导致首次使用的时候加载过慢;
  4. 由于还是在内测阶段,内置的地图控件(原生控件,不在 WebView)仅仅开放提供了定位显示的功能,根本无法添加其他视图层实现地理标签等功能

无关技术:

  1. 场地很有互联网公司的范,绿树掩映、陈旧厂房、新潮装修、文艺十足;
  2. 有一半参赛选手是学生,大一的新生表现突出,可见微信的想象力宽泛,早早影响到了初生代

使用 Shipyar 管理 Docker

Shipyard是一个集成管理 Docker 容器、镜像、镜像仓库的系统,相比较于 Docker 出品的 Swarm,Shipyard可以使用多个节点调度管理,可以动态加载节点,可以托管各个节点下的容器。官方文档https://shipyard-project.com/docs/deploy/automated/

1. 首次部署脚本

curl -sSL https://shipyard-project.com/deploy | bash -s

ACTION: 可以使用的指令 (deploy, upgrade, node, remove)
DISCOVERY: 集群系统采用Swarm进行采集和管理(在节点管理中可以使用‘node’)
IMAGE: 镜像,默认使用shipyard的镜像
PREFIX: 容器名字的前缀
SHIPYARD_ARGS: 容器的常用参数
TLS_CERT_PATH: TLS证书路径
PORT: 主程序监听端口 (默认端口: 8080)
PROXY_PORT: 代理端口 (默认: 2375)

1.1 脚本可选项

action:指令有效变量
deploy: 部署新的shipyard实例
upgrade: 更新已存在的实例(注意:你要保持相同的系统环境、变量来部署同样的配置)
node: 使用Swarm增加一个新的node

......

3. 增加一个节点

Shipyard节点部署脚本可以自动的安装 key/value 存储系统(etcd系统)。
在将要被添加的节点主机上执行脚本增加一个节点到swarm集群

curl -sSL https://shipyard-project.com/deploy | ACTION=node  DISCOVERY=etcd://applehater.cn:4001 bash -s

其中DISCOVERY是你运行 Shipyard 容器的域名或者地址

4. 操作

  1. 创建容器
    2.png

  2. 容器列表
    1.png

  3. 查看某个容器状态
    3.png

  4. 没办法变更容器配置
    这可能是最大弊端,无法找到变更配置的控制面板,如果创建 mysql 容器的时候忘记配置初始密码,可肯需要重新创建。像 Rancher 这样的平台可以自由对容器配置扩展,建立应用堆栈
    4.png

5. 移除

使用以下脚本移除 Shipyard Agent 或者 Shipyard Node

curl -sSL https://shipyard-project.com/deploy | ACTION=remove bash -s

有关 Django 的一些

1. 时区设置

python默认时区会根据系统的时区设置,如果没有设置,插入数据表的数据将出现时区错误,造成一些时间判断上的偏差

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True

2. fixtures

在项目根目录执行

./manage.py dumpdata > data.json

载入

./manage.py migrate
./manage.py loaddata data.json

注意要将当中包含contenttypepermission的数据去掉,避免Duplicate entry错误,因为已经在migrate过程中创建了

3. 数据库编码

如果数据编码使用了utf8mb4*之类的编码,会导致Django的Model的datetime类型全部会None。请使用非utf8mb4编码