Category: Python

Python Django Vue PostgreSQL搭建前后端分离项目

准备工作

安装环境

  • Pycharm
  • webpack
  • python 3
  • npm
  • vue-cli
  • postgresql
npm install -g webpack
npm install -g vue-cli

创建Django项目

django-admin startproject ServerList

创建成功后的目录如下

.
├── manage.py
└── pc_admin
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

进入项目根目录,创建一个APP作为项目后端

cd ServerList
python manage.py startapp backend //backend乃App名称

成功后目录如下

.
├── backend
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── ServerList
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

创建前端项目

使用vue-cli在根目录创建一个frontend的Vue.js项目作为项目前端。

vue-init webpack frontend

配置数据源及前端模板

# 数据库设定
DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'odam',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    }
}
# 模版设定
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # 'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'DIRS': ['frontend/dist'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

# Add for Vue.js
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "frontend/dist/static"),
]

结束

python manage.py runserver

Odoo12 开发之重写List记录打开方式

在Odoo中,记录的打开方式都是通过事件绑定的方式进行的,但要如何才能知道我在点击这个记录的时候触发了什么操作呢。这篇日志主要就是说明一下,在遇到这类情况的时候如何来找到正确的处理方式。

首先我们得到明确的需求,我们需要在Odoo的列表视图中重写打开记录指向的Form。

Odoo 列表视图

一、准备工作

进入Assets Debug模式

或者使用修改Url的方式

 http://localhost:8069/web?debug=assets#home

进入浏览器开发者模式(F12)

Chrome Debug

二、找寻需要的事件

事件管理

如果事件太多可以使用如下方式移除不必要的事件

接下来我们可以将不必要的实践移除后再点击行记录,如果能正确执行,那么代表我们需要的事件就还在这个列表中。

最终在我移除了大部分事件后,保留如下事件的情况下,功能还正常。那么可以断定,我需要的点击事件就是它。

跟进Js代码中,发现这个代码是这样的

proxy: function (method) {
        var self = this;
        return function () {
            var fn = (typeof method === 'string') ? self[method] : method;
            if (fn === void 0) {
                throw new Error("Couldn't find method '" + method + "' in widget " + self);
            }
            return fn.apply(self, arguments);
        };
    },

从代码中可以看出,这又是一个代理事件,那么继续打断点跟踪

最终在list_renderer.js文件见找到如何方法

    _onRowClicked: function (event) {
        // The special_click property explicitely allow events to bubble all
        // the way up to bootstrap's level rather than being stopped earlier.
        if (!$(event.target).prop('special_click')) {
            var id = $(event.currentTarget).data('id');
            if (id) {
                this.trigger_up('open_record', { id: id, target: event.target });
            }
        }
    }

再看方法引用

至此,就可以直接复写该方法来实现了。。

附上最后实现的代码~

odoo.define('ps.web.ListRenderer', function (require) {
"use strict";
var ListRenderer = require('web.ListRenderer');

ListRenderer.include({
		_onRowClicked: function (event) {
			if (this.state.model === 'combined.statements.working.paper.project') {
				let record = this.state.data.find(record => record.id === $(event.currentTarget).data('id')).data;
				this.do_action({
					type: "ir.actions.client",
					tag: 'working.papers',
					params: record
				});
			}else{
				this._super.apply(this, arguments);
			}
		}
	});
});

Python 转数字为Excel列,转列为数字

def convent_column_to_char(column):
	"""
	将数字转换为Excel列
	1 => A, 2 => B, ......, 27 => AA
	:param column: int
	:return: str
	"""
	if not isinstance(column, int):
		return column
	tStr = str()
	while column != 0:
		res = column % 26
		if res == 0:
			res = 26
			column -= 26
		tStr = chr(ord('A') + res - 1) + tStr
		column = column // 26
	return tStr


def colname_to_num(colname):
	if not isinstance(colname, str):
		return colname
	col = 0
	power = 1

	for i in range(len(colname) - 1, -1, -1):
		ch = colname[i]
		col += (ord(ch) - ord('A') + 1) * power
		power *= 26
	return col


if __name__ == "__main__":
    l = list()
    n = list()
    for a in range(1, 1001):
        l.append(convent_column_to_char(a))
    print(l)
    for a in l:
        n.append(colname_to_num(a))
    print(n)

Odoo 10 Could not execute command lessc

这个问题出现的十分突然,早上打开项目,直接抛出“Could not execute command lessc”这个Error,导致界面加载异常。

现将处理过程做一次分析整理。

再看系统环境变量

启动程序,问题依旧。。

跟进代码

发现 os.environ 这个变量中的PATH里面被覆盖了。

调整启动配置

再次跟进代码
Over...

Odoo Javascript & Widget

定义一个OdooClass

odoo.define('addon_name.service', function (require) {
    "use strict";
    var utils = require('web.utils');
    var Model = require('web.Model');

    // do things with utils and Model
    var something_useful = 15;
    return  {
        something_useful: something_useful,
    };
});

重写记录打开方式

odoo.define('combined_statements.working_papers', function(require) {
    "use strict";
	var core = require('web.core');
	var ListView = require('web.ListView');
	var utils = require('web.utils');
	var web_client = require('web.web_client');
	var Model = require('web.Model');

	var QWeb = core.qweb;
	var _t = core._t;

	/**
	 * 打开工作底稿创建向导页面
	 */
	function open_wording_papers_wizard_action() {
		web_client.action_manager.do_action({
			name: "底稿定义",
			type: "ir.actions.act_window",
			res_model: "working.papers.define.wizard",
			target: 'new',
			xml_id: 'combined_statements.working_papers_define_wizard_form',
			views: [
                [
                    false, 'form'
                ]
            ]
        });
    }

	ListView.include({
        // 为增加按钮绑定点击事件
		render_buttons: function($node) {
			let add_button = false;
			if (!this.$buttons) {
				add_button = true;
            }

			this._super.apply(this, arguments);

			if (add_button) {
				this.$buttons.on('click', '.o_button_open', open_wording_papers_wizard_action.bind(this));
            }
        },
        // 重写Tree视图点击行打开记录的方式
		do_activate_record: function(index, id, dataset, view) {
			if (this.model === 'combined.statements.working.paper') {
				let record = this.records.get(id);
				this.do_action({
					type: "ir.actions.client",
					tag: 'working.papers',
					params: record,
                });
            }else {
				this._super.apply(this, arguments);
            }
        }
    });
});

Archives