@Lenciel

Data Migration in Django 1.7 (2)

在应用开发的过程中,我们会遇到 migration 主要分为:

  1. Schema Migrations:数据库 schema 的变化,也就是我们前面讨论的内容
  2. Data Migrations:数据的变化,比如需要批量变更数据或者备份在其他地方的历史数据

第二种是没法敲几条命令让 Django 自动帮你完成其他的事情的,而是需要手动使用RunPython,这里具体说一下做法。

还是以之前的那个项目来作为例子,我们首先创建一个 migration file:

$ python manage.py makemigrations --empty ts_data

Migrations for ts_data:
  0003_auto_20140811_0110.py:

它的内容如下:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('ts_data', '0002_auto_20140805_1525'),
    ]

    operations = [
    ]

我们在里面加入一个RunPython的部分,来导入数据:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from ts_data.models import PingPongPrice


def load_data(apps, schema_editor):
    PingPongPrice(date=date(2014,07,29),
         price=12.00,
         ).save()
    PingPongPrice(date=date(2014,01,29),
         price=8.00,
         ).save()


class Migration(migrations.Migration):

    dependencies = [
        ('ts_data', '0002_auto_20140805_1525'),
    ]

    operations = [migrations.RunPython(load_data)]

如果你觉得:咦,这样导入数据不是有点儿像用syncdb然后导入fixture么?的确,从效果上它们是一样的,个人觉得,对于测试环境我们可以继续使用 fixture 来保存 mock 的测试数据,然后使用loaddata命令手动加载测试数据。对生产环境使用 migration 来导入数据更好,和使用loaddata命令来导入 fixture 相比,它不需要手动操作,并且由于是通过RunPython来进行,实际上可以对数据进行各种需要的处理。

如何不正确的殴打企鹅

今天在微信朋友圈里面看了 20 来条这游戏的成绩分享,还有的群开始讨论心得。打开链接一看,原来是当年那个小范围流行了一下的Penguin Ball嘛(我记得后来有些人开始玩那个血腥版,正常人就慢慢不玩这游戏了)。

不过,链接指向的那山寨游戏虽然没有再用 flash,但是对手势事件的处理有问题(他们还是挺大方的),所以确实还蛮难的:我打了五六次,最好成绩 6000 多一点。

然后,那个页面除开嵌入了一个「教你如何调情」的广告之外,一直在不停的要你分享,分享,分享……

那我就分享嘛~~~

去看了一下微信的分享是怎么弄出去的,原来有个非官方的叫WeixinJSBridge的东西:只要是通过微信应用内置的 Webview 打开的网页就可以调用到一组特别的接口,比如分享链接到朋友圈或者发送链接给朋友。这两个接口的参数非常类似:

  • 分享链接消息里面的 title image 的 url
  • title image 的宽度和高度
  • 标题
  • 描述
  • 链接指向的 url
  • 微信 APPID

分享出来的链接,以这个「打企鹅」的游戏为例,是长成下面这样子的一条链接消息:

Don't touch me

所以,要伪装一个「打企鹅」的高分数链接就只需要找到 title image 的 url 和链接指向的 url(因为标题和描述照着编就是了)。

本座觉得,那么山寨的游戏作者,肯定是把所有的东西都放在页面上的吧,于是用 Chrome 打开了那个页面,果然没有被拒绝(一般来说,给微信浏览的页面至少应该根据访问上报的 user-agent 等参数判断它是不是移动设备浏览的,如果不是应该 reject),并且源码里面我想要的都在(所以比较敏感的 js 什么的 minify 一下会好一些):

        var mebtnopenurl = 'http://game.2sky.cn/game/';
        var rankurl = mebtnopenurl;
        dataForWeixin = {
            "appId": "wx60c8c12f639f3ef4",
            "imgUrl": "http://game.2sky.cn/vapp/52/3.jpg",
            "url": "http://bingkafei.hnsdcpa.com/game/52/",
            "tTitle": "打企鹅-6e游戏",
            "tContent": "打企鹅-6e游戏"
        };

        dataForWeixin.appId = "wx8820cdf5db680ffa";
        dataForWeixin.url = "http://weiapp.552200.com/game/"+_con["num"]+"/";

        function dp_share(){
            document.title ="你简直霸气侧漏,把企鹅击飞出"+myData.scoreName+",谁还能超越我?";
            document.getElementById("share").style.display="";
            dataForWeixin.tTitle = document.title;
        }

当然,拿到这些了之后,也不是马上一句:

WeixinJSBridge.invoke('shareTimeline',data,callback)

就能把你装神弄鬼消息分享出去的。前面说了,微信那边还是会检查整个事情是不是发生在微信内置的 webview 里面。但是,要绕开也不是那么麻烦,你懂的…

总体感觉微信的这 api 还是挺扯的,本来可以作为身份校验的 appid 其实填不填也无所谓,所以朋友圈里面的链接点起来还是谨慎一点儿吧,骚年们。