Runforever

to be a rock star


  • 首页

  • 归档

  • 标签

Git Flow 重新思考

发表于 2016-11-16 | 分类于 git | | 阅读次数:

一次 Git Flow 的讨论

新项目启动,我建议使用 Fork + Pull Request 模式开发,保持提交的干净整洁,其他的同学则建议用一个 dev 分支中央式开发,方便多人协作和同步代码, 最终使用了一个 dev 分支的模式,后端觉得项目初始阶段相互依赖会比较多,方便协作,前端觉得这样方便同时与多人对接后端的接口。

对于 Git Flow 的思考

讨论结束后,我开始重新思考 Git Flow 的模式和使用,得到的答案是使用最基本的 Git 协作流程就可以适应各种 Git Flow。

Git 是为了管理 Linux 内核源代码而开发的版本控制系统,它与生俱来的特点就是 分布式 和 简单的分支管理

我的需求

  1. 协作方便。
  2. 提交历史要干净整洁。
  3. 方便 code review。

阅读全文 »

djkit 开发记录

发表于 2016-11-04 | 分类于 django | | 阅读次数:

原因

在公司的研发团队中,我除了要写代码,还要做一些项目架构和基础设施搭建的工作,每次搭建一个新项目都会有不少重复的工作,一两次还好,多了我真的有点受不了,于是思索着写这么一个东西来减少工作的痛苦。

技术架构

工作中主要使用 Python,API 主要使用 Django、Django RESTframework 来做,一些 Python 依赖和目录结构都是统一的,我就先减少这部分的重复工作吧。

requirements

Django==1.9.10
django-cors-headers==1.1.0
django-nose==1.4.4
django-rest-swagger==0.3.7
djangorestframework==3.4.6
djangorestframework-jwt==1.8.0
mysqlclient==1.3.7
raven==5.26.0

Django 使用 1.9.10 的原因是这个版本和 django-rest-swagger 的 0.3.7 版本配合比较好,比较适合我们团队, 可以很方便的在浏览器下调试,效果如下:

21986351-ADE1-4AAA-9E2F-CC05B27E5EE1.png

阅读全文 »

迁移 Octopress 到 Hexo

发表于 2016-11-02 | 分类于 blog | | 阅读次数:

不折腾会死

前几天更新了 Python Mixin 学习笔记 这篇文章,文章中有一张图要显示,于是想添加 fancybox 插件来预览图片, 原本以为是非常简单的一件事,结果上 google 果然没有找到,同时发现博客的分页有 bug,再看看 Octopress 的 最后更新时间,想到 Octopress 这些茫茫多的问题于是便有了迁移 Octopress 到 Hexo 的念头。

迁移前的调研

google 找了一些迁移的文章,发现迁移没有想象中难,于是开始准备。

我的需求:

  1. 可以继续使用 Emacs 上的 org-octopress 插件写博客。
  2. 可以兼容我之前写的文章,代码高亮必须漂亮。
  3. 一定要有 fancybox。
  4. 没有分页等乱七八糟的明显 bug。

迁移后的优点

  1. generate 速度大幅提高。
  2. Hexo 更新快,插件多,没有很明显的 bug。
  3. 完美兼容我的写作习惯。

迁移过程

  1. 安装配置 Hexo。
  2. 迁移 source/_posts 里的博客源文件。
  3. 重新配置 org-octopress。
  4. 选择一个兼容 Octopress 文章的主题。
  5. 调整 Hexo 和主题的配置。
  6. 博客代码管理。

阅读全文 »

搭建私有 Docker Registry

发表于 2016-07-06 | 分类于 Docker | | 阅读次数:

为了团队的其他同学可以方便的更新开发环境到本地,我们决定搭建私有的 Docker Registry。
不使用公共服务的原因:

  1. Docker Hub 在国外,同步超级慢。
  2. DaoCloud 的私有 image 需要收费,对于我们小团队来说不太友好。

搭建步骤

  1. 环境准备。
  2. 配置 LetsEncrypt 证书。
  3. 安装 Docker Registry。
  4. 配置 Nginx。
  5. 后续工作。

阅读全文 »

Django项目如何使用Docker搭建环境

发表于 2016-06-28 | 分类于 Docker , Django | | 阅读次数:

背景

公司的项目前后端是分离的,前端使用React作为技术栈,后端使用Django做完web开发框架, 前端的同学调试代码的时候需要启动后端的项目,后端的项目往往需要一堆环境依赖,例如数据库, Redis缓存,Python的库,每次搭建环境更新环境对于前端的同学来说都是一场噩梦,比如安装数据库, 编译Python的库等等都会遇到很多问题,为了提高效率,更好的统一开发环境,所以使用了Docker来做 这件事。

达到的效果

b91020a400c2106d.png

阅读全文 »

Ansible 使用入门

发表于 2016-02-03 | 分类于 Ansible | | 阅读次数:

背景

由于经常有部署新服务器的需求,服务器部署过程中的配置和基础环境的安装很多都是重复性的 工作,所以使用配置管理工具将这些重复性的工作控制起来最合适不过了,之前有写过一篇用 SaltStack 做自动化运维的文章 saltstack 使用笔记,这次换用 Ansible ,顺便比较一下两种工具。

选用 Ansible 的原因

  1. 轻量级
  2. 通过 SSH 下发命令

阅读全文 »

uwsgi部署Django服务的坑

发表于 2016-01-31 | 分类于 uwsgi , django | | 阅读次数:

uwsgi部署Django服务

部署Django的方式

  • gunicorn + Nginx
  • uwsgi + Nginx

gunicorn + Nginx

http://gunicorn.org 最大的好处就是部署简单,如果没有特殊要求,推荐使用这种方式部署Python Web程序

uwsgi + Nginx

uwsgi 相对 gunicorn来说配置选项相对复杂,但是uwsgi是支持websocket的,出于这个原因选择uwsgi来部署django程序

  • 问题1:uwsgi的默认监听进程的数量100

    解决: 之前由于只知道启动uwsgi worker的数量,不管怎么调worker的数量,并发都很低,
    配置listen参数解决,根据服务器配置和访问来决定,目前我开的是20000

  • 问题2:supervisor没有办法优雅的重启uwsgi worker,导致服务器资源被重启的uwsgi进程占满

    解决:配置no-orphans参数

  • 配置范例
    master = true
    processes = 8
    thread = 100
    thread-stacksize = 512
    stats = 127.0.0.1:9194
    buffer-size = 65535
    enable-threads = true
    http-timeout = 60
    socket-timeout = 60
    chmod-socket = 666
    harakiri = 60
    max-requests = 20000
    listen = 20000
    no-orphans
    

    阅读全文 »

Angular.js入门参考

发表于 2014-12-20 | 分类于 Angular | | 阅读次数:

Angular.js 入门参考

来源

很早听说这个前端MV*框架,最近公司的一个新项目未来可能需要支持手机App,所以决定
使用API驱动的设计,也就是网站后端只提供API,逻辑处理由前端实现,也就是Angular这些
前端框架要做的事情了,以后如果上手机App的话也可以使用同一套API,不用单独为手机App
开发新的API。

前端MV*是什么?

MV* 可以是MVC(Model, View, Controller)模式,也可以是MVVM(Model, View, ViewModel)
你可以把Angular用成你想要的模式,而MVVM正是我项目里面想要的东西,Model和UI的双向绑定
也就是Model变化UI相应的改变,UI改变Model也跟着改变。

Angular的使用场景和优缺点

使用场景

Single Page Application(单页面应用),即MVVM模式发挥优势的地方。

优点

  • 使Javascript开发变得模块化。
  • 保证开发人员的代码风格统一。
  • 资源相对较多,上手相对简单。

缺点

  • 调试很困难

Angular 基本概念

  1. Directive(指令)
  2. Scope(变量空间)
  3. Service(服务)
  4. Controller(控制器)
  5. Module(模块)

Directive

Angular指令,如ng-app, ng-controller, ng-model, ng-repeat等等。

Scope

Controller可以访问的变量空间。

Service

服务,如Http,window,element等服务,可以自定义公用的服务,达到模块化管理的目的。

Controller

View的控制模块。

Module

模块,要使用Angular必须先初始化模块

实例

index.html

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <title>Document</title>
    </head>
    <!-- 使用directive初始化app -->
    <body ng-app="app">
        <!-- 添加controller -->
        <div ng-controller="loginCtrl">
             <!-- 使用ng-model绑定username和input, 两者只要有一个改变都会进行相应的改变 -->
             <input ng-model="username" name="username" type="text"/>
             <input ng-model="password" name="username" type="password"/>
             <!-- controller里面添加相应的函数 -->
             <a href ng-click="login()">登录</a>
        </div>
    </body>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
</html>

app.js

(function() {
    // 初始化App
    var app = angular.module('app', []);

    // 添加Controller
    app.controller(
        'loginCtrl',
        // 依赖注入使用服务 $scope 和 $http
        ['$scope', '$http', function($scope, $http) {
            // 添加登录处理函数
            $scope.login = function() {
                $http.post('/login/', {username: $scope.username, password: $scope.password}).success(function(data) {
                    alert(data.msg);
                });
            }
        }]
    );
})();

总结

本篇提供angular的入门,后续会有一些使用心得,总体来说angular上手还是很简单的。

阅读全文 »

Python使用支付宝接口

发表于 2014-10-02 | 分类于 Python , Alipay | | 阅读次数:

Python使用支付宝接口

来源

www.pinbot.me需要支持线上支付,先从支持支付宝开始。

使用支付宝什么接口

支付宝接口有很多,而线上支付使用的是即时到账接口,这里有官方介绍

如何使用该接口

实现代码参考了python-alipay

获取PID和32位KEY

只能是企业才能申请该接口的使用,实名认证通过后,你只要拿到PID和KEY
就行了。

使用该接口

  • 使用该接口需要实现两个工具函数:
    1. 构造支付宝的支付链接,如果链接请求成功会生存支付宝的支付页面。
    2. 支付成功后需要验证支付宝返回的结果是否正确,如果正确就做相应的订单更新。
  • 实现构造支付链接

    注意事项:

    1. 传给支付宝的url参数需要字母顺序排序,且不能含有空格,空值。
    2. 验证,使用MD5验证,构造除了sign和sign_type的url参数和key做md5。
  • 实现验证支付宝返回数据的验证

    验证支付宝请求return_url和notify_url的数据
    注意事项

    1. 支付宝的notify_id在一分钟后会实效。
    2. 支付宝异步请求如果没有收到success的话会间隔发请求,直到获取到success,或者超过24小时。

    代码: 一个配置类AlipayConfig
    一个工具类AlipayUtils

    AlipayConfig代码:

    # coding: utf-8
    
    
    class AlipayConfig(object):
    
        ALIPAY_PID = 'your apply pid'
        ALIPAY_KEY = 'your apply key'
    
        ALIPAY_SELLER_EMAIL = 'your apply email'
    
        ALIPAY_INPUT_CHARSET = 'utf-8'
        ALIPAY_SIGN_TYPE = 'MD5'
    
        ALIPAY_GATEWAY = 'https://mapi.alipay.com/gateway.do?'
        ALIPAY_NOTIFY_GATEWAY = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'
    
        ALIPAY_RETURN_URL = 'your return url'
    

    AlipayUtils代码:

    # coding: utf-8
    
    import urllib
    import requests
    from hashlib import md5
    from collections import OrderedDict
    
    from alipay_config import AlipayConfig
    
    from Pinbot.settings import DEBUG
    
    
    class AlipayUtils(object):
    
        @classmethod
        def _convert_str_encode(cls, pay_option, encoding='utf-8'):
            '''
           将unicode编码转换成utf-8编码
            '''
            for key, value in pay_option.iteritems():
                if not value:
                    continue
                if isinstance(value, unicode):
                    pay_option[key] = value.encode(encoding)
            return pay_option
    
        @classmethod
        def _get_url_params(cls, pay_option):
            '''
            使用OrderedDict将url参数按字母顺序排序
            去除空的字段和sign, sign_type字段
            '''
            url_params = OrderedDict(
                sorted(
                    [
                        item for item in pay_option.iteritems()
                        if item[1] and item[0] not in ('sign', 'sign_type')
                    ],
                    key=lambda x: x[0]
                )
            )
            return url_params
    
        @classmethod
        def _get_sign(cls, url_params):
            '''
            md5加密url参数和key
            '''
            key = AlipayConfig.ALIPAY_KEY
            prestr = '&'.join('%s=%s' % item for item in url_params.iteritems())
            sign = md5(prestr + key).hexdigest()
            return sign
    
        @classmethod
        def submit_order_url(cls, order):
            '''
            构造支付宝即时到账链接
            '''
            pay_option = dict([
                ('service', 'create_direct_pay_by_user'),
                ('payment_type', '1'),
    
                ('_input_charset', AlipayConfig.ALIPAY_INPUT_CHARSET),
                ('partner', AlipayConfig.ALIPAY_PID),
                ('seller_email', AlipayConfig.ALIPAY_SELLER_EMAIL),
                ('return_url', AlipayConfig.ALIPAY_RETURN_URL),
                ('notify_url', ''),
                ('show_url', ''),
    
                ('out_trade_no', order.order_id),
                ('subject', order.subject_name()),
                ('body', order.order_detail()),
                ('total_fee', order.total_price if not DEBUG else 0.1),
            ])
    
            # 将支付参数的编码统一成utf-8
            pay_option = cls._convert_str_encode(
                pay_option,
                encoding=AlipayConfig.ALIPAY_INPUT_CHARSET,
            )
    
            # 排序去除空值和sign,sign_type选项
            url_params = cls._get_url_params(pay_option)
    
            # 加密和加密类型
            url_params['sign'] = cls._get_sign(url_params)
            url_params['sign_type'] = AlipayConfig.ALIPAY_SIGN_TYPE
    
            # 生成支付url
            submit_url = AlipayConfig.ALIPAY_GATEWAY + urllib.urlencode(url_params)
    
            return submit_url
    
        @classmethod
        def verify_alipay_notify(cls, url_data):
            '''
            验证支付宝支付成功的返回信息
            两个步骤:
               1. 验证签名
               2. 查询此notify是否在支付宝中有效
            '''
            # 验证签名
            alipay_sign = url_data.get('sign')
            alipay_url_params = cls._get_url_params(url_data)
            sign = cls._get_sign(alipay_url_params)
    
            if sign != alipay_sign:
                return False
    
            # 查询信息是否在支付宝中有效
            check_params = {
                'partner': AlipayConfig.ALIPAY_PID,
                'notify_id': url_data.get('notify_id')
            }
            result = requests.get(
                AlipayConfig.ALIPAY_NOTIFY_GATEWAY,
                params=check_params
            )
            if result.text.lower().strip() == 'true':
                return True
    
            return False
    

    一些运行结果:

    # 生成支付的url
    https://mapi.alipay.com/gateway.do?_input_charset=utf-8&body=hehehehhe&out_trade_no=20140928110814-8cd3
    &partner=xxxxx&payment_type=1&paymenthod=directPay&seller_email=xxx%40xxx.com&
    service=create_direct_pay_by_user&subject=hehehe&total_fee=2599&sign=603b228b7e6663d217dc44bdc12a5106&
    sign_type=MD5
    
    # 支付宝返回数据的url
    127.0.0.1:8000/payment/alipay_return/?body=套餐B&buyer_email=xxxx%40163.com&buyer_id=xxxxxxx&
    exterface=create_direct_pay_by_user&is_success=T&
    notify_id=RqPnCoPT3K9%252Fvwbh3InQ9JC%252Ft24wOkxbC3d3NsqzK9v6KWsnZ2vWqks9o41CFgeCkbai&
    notify_time=2014-09-30+14%3A21%3A22&notify_type=trade_status_sync&out_trade_no=20140928110814-8cd4&
    payment_type=1&seller_email=xxx%40xxxx.com&seller_id=xxxx&subject=套餐B&total_fee=0.10&
    trade_no=2014093000715684&trade_status=TRADE_SUCCESS&sign=de81410e5fba18e8d97823a31c0724ac&sign_type=MD5
    

总结:

支付宝的文档确实有点看不懂,上面放了两个运行结果,希望大家做起来有点方向,知道构造什么,验证什么,
感谢github上这个repo, 给了我很大的帮助。

阅读全文 »

Python Mixin 学习笔记

发表于 2014-07-19 | 分类于 Python | | 阅读次数:

2016-10-25 17:04 的邮件

正思考着如何给 djkit(Django starter)项目添加 admin 和 models 的支持, 此时收到一封邮件,来自 uhayate,内容如下:

5EB59FBA-21CC-4BAB-98CB-BCA70237C5DD.png

看了他的 github 和博客,我确定我不认识这个同学,这下有意思了,我的博客居 然被人搜索到而且还发现了一个错误,赶紧回了邮件然后审查文章压压惊,之后便有了 这次更新,不得不说,两年前写的东西还是欠火候,至于评论功能,使用 Issue。

主要更新

  1. 新式类 MRO 的机制理解。
  2. 文章排版按照 中文文案排版指北 重排。
  3. Mixin 使用场景。

更新总结

  1. 多继承真的很复杂。
  2. 博客和代码一样,每当你过一段时间回头来看会问自己当时为什么要这样写,代码要经常重构,文章也需要经常更新,当别人看到你写的东西的时候就要拿出最好的给读者。

来由

对 Python 的面向对象编程研究的比较少,Django 是从 1.3 推荐使用 class base view, 免不了会用到 Python 的面向对象的特性,所以把研究的东西记录一下。

知识点

  1. Python 面向对象的基本使用和多继承 MRO(method resolution order)的机制。
  2. Mixin 和多继承有什么区别及应用场景。
  3. Python 中的静态方法、类方法、实例方法。

阅读全文 »
1234
runforever

runforever

K.I.S.S

34 日志
30 分类
RSS
GitHub Bitbucket Issue
© 2020 runforever
由 Hexo 强力驱动
|
主题 — NexT.Gemini
蜀ICP备16025642号-2