Apr 13 2016
为什么迁移
blog算是我正式的第一个Python项目,是我入门Python的基石,一直稳定的运行在SAE上,上个月我还进行过一次升级,但是SAE的MySQL服务收费来得太突然,每年大概要花200软妹币,对于一个PaaS平台来说,我认为是不划算的,鉴于静态博客的流行,所以痛下决心迁移到github pages上来。
静态博客生成器的选择
- Jekyll
Jekyll是静态博客生成器的鼻祖,拥有大量的模版,但是基于ruby导致文章较多的情况下会比较慢
- pelican
python是工作语言,所以本来是最可能选择的就是pelican,直到我找到hugo
- hugo
golang实现,最大的优点就是快,而且golang可以编译为二进制文件,所以安装起来非常方便
Mar 11 2016
在公司业务中有很多模块需要记录模型的变更历史,刚开始的时候会针对需要变更记录的表增加一个变更记录表,然后做针对性的开发。后来类似的需求多了,而且不需要很详细的记录,所以单独提取了一个比较简单的模型跟踪模块出来。
原理
使用Django自己的信号实现,创建了一个公用的model跟踪表,所有配置跟踪的model变更记录都会保存到这张表中,通过一个公用的trace_model
函数来保存变更的新老数据,而且只保存修改的字段。
# coding=utf-8
import inspect, json
from django.conf import settings
from django.db.models import ManyToManyField, ManyToOneRel
from django.db.models.fields.related import ForeignKey
from raven.contrib.django.models import client
from models import ModelRecord
def trace_model(sender, instance, raw, using, update_fields, **kwargs):
try:
if instance._state.adding is True:
return
obj = sender.objects.get(pk=instance.pk)
change_fields = {}
for name in sender._meta.get_all_field_names():
if name in ('add_by', 'add_dt', 'update_by', 'update_dt', 'update_by_id'): # 更新人,添加人,时间不记录
continue
field = sender._meta.get_field(name)
if field.auto_created or field.hidden or field.__class__ in (ManyToManyField, ManyToOneRel): # 特殊的字段不记录
continue
old = getattr(obj, name, None)
new = getattr(instance, name, None)
if str(old) == str(new): # 不同类型的字段转为字符串,相等的不记录
continue
if isinstance(field, ForeignKey):# 如果是外键
if name != field.name and not field.name in change_fields:
if old:
old = field.related_model.objects.filter(pk=old).first()
if new:
new = field.related_model.objects.filter(pk=new).first()
elif name == field.name and not name+'_id' in change_fields:
pass # 判断避免同时对外键赋值的清空
else:
continue
if field.choices:
if old:
old = getattr(obj, 'get_'+field.name+'_display', old)
if new:
new = getattr(instance, 'get_'+field.name+'_display', new)
if callable(old):
old = old()
if callable(new):
new = new()
old = str(old) if old is not None else '空'
new = str(new) if new is not None else '空'
verbose_name = getattr(field, 'verbose_name', name)
change_fields[name] = {
'name': verbose_name,
'new': new,
'old': old
}
dbname = getattr(sender, '_database', settings.DATABASES['default']['NAME'])
for frame_record in inspect.stack():
if frame_record[3] == 'get_response':
request = frame_record[0].f_locals['request']
user = request.user
break
# 数据入库
if change_fields and 'user' in locals():
ModelRecord.objects.create(dbname=dbname,
table_name=sender._meta.db_table,
table_pk = instance.pk,
content=json.dumps(change_fields),
add_by=user)
except Exception:
client.captureException()
Mar 9 2016
Tastypie是什么
Tastypie是基于Django的RESTful api开发框架,如果你有一个通过Django实现的网站,那么通过Tastypie写少许的代码就能实现一个全功能的REST api。
我要写些什么
这不是一篇Tastypie的入门教程,如果需要教程,可以从官方文档开始,我写的只在探索Tastypie的过程中我认为值得记录的地方。
Getting Started with Tastypie
Mar 7 2016
周末花了点时间把许久没有动过的Blog做了一些优化,优化的目标:更快,更省。
更快
- 缓存SQL查询结果
- 优化数据库表结构
- 优化SQL查询语句
- 使用misaka(C写的Markdown解析器)
更省
用SAE KVDB替换Memcached
Feb 1 2016
** 手贱把工作电脑的Ubuntu搞挂了好像,不得已重装一下,这里记录一下过程
工作中用到Ubuntu主要是做Python开发环境,在家习惯了用Mac,切换到Ubuntu还是很方便了,比较坑的,是经常莫名其妙的系统错误。
1. 安装系统
必须是Ubuntu 14.04 64bit 选择不在线更新安装
2. 更新系统
在系统设置中选择国内的源,我用的是163的