在REPL环境中使用django

想在 repl 环境中测试一下 django 的 QueryDict 对象,先装一下这个包:

1
python3 -m pip install django --user

发现直接使用会报错:

1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/lolimay/Library/Python/3.8/lib/python/site-packages/django/http/request.py", line 445, in __init__
self.encoding = encoding or settings.DEFAULT_CHARSET
File "/Users/lolimay/Library/Python/3.8/lib/python/site-packages/django/conf/__init__.py", line 82, in __getattr__
self._setup(name)
File "/Users/lolimay/Library/Python/3.8/lib/python/site-packages/django/conf/__init__.py", line 63, in _setup
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_CHARSET, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
>>>

说人话就是需要先调用 settings.configure() 配置设置项,需要像下面这样用:

1
2
3
4
5
6
7
8
9
10
11
12
I python3
Python 3.8.2 (default, Dec 21 2020, 15:06:04)
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from django.conf import settings
>>> from django.http import QueryDict
>>> settings.configure()
>>> dict = QueryDict("周恩来")
>>> question = list(dict.keys())[0]
>>> print(question)
周恩来
>>>

混入(mixin)

JavaScript 不允许多继承,但是可以通过混入 (mixin)技术来组合其他类的方法。在 JavaScript 中混入的本质其实还是原型委托调用。

假如有一个星球类 Planet,我们想让他拥有另一个 Circle 类的方法和属性,但是这个类本身已经继承了 Component 类,这时就可以使用混入技术:

1
2
3
4
@ccclass('Planet')
export class Planet extends Component {
private _level: number = 2
...

创建一个混入函数 mixinCircle 并导出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { Vec3 } from 'cc'

type Constructor<T = {}> = new (...args: any[]) => T

export interface ICircle {
position: Vec3
radius: number
}

export const mixinCircle = <TBase extends Constructor>(Base: TBase) => {
return class Circle extends Base implements ICircle {
protected _radius!: number
private _position!: Vec3

constructor(...args: any[]) {
super(...args)
this.intersect.bind(this)
}

/**
* @en The position of the circle, which is a Vec3 vector
* @zh 圆的直径,是一个 Vec3 向量
*/
get position() {
return this._position
}

/**
* @en The radius of the circle
* @zh 圆的半径
*/
get radius() {
return this._radius
}

/**
* @en Determines if it intersects with another circle
* @zh 判断是否与另外一个圆相交
*/
public intersect(circle: ICircle) {
return Vec3.distance(this.position, circle.position) < this.radius + circle.radius
}
}
}

这时候再修改 Planet 类,让他继承混入 Circle 类的 Component 类即可。

1
2
3
4
@ccclass('Planet')
export class Planet extends mixinCircle(Component) {
private _level: number = 2
...

如果我们想要混入多个类以上这个方法还可以嵌套使用,如:

1
2
3
4
@ccclass('Planet')
export class Planet extends mixinNode(mixinCircle(Component)) {
private _level: number = 2
...

3D旋转与四元数(Quaternion)

本来只是一个很简单的一个需求:把精灵按z轴随机旋转0-360度。但是 cocos Node 的 setRotation 只接收一个 math.Quat 类型的四元数。

原来我们经常用的那种先按某个坐标轴旋转多少度,再按某个坐标轴旋转多少度,这个叫欧拉旋转。但是欧拉旋转会出现万向节死锁的问题,即可能会出现一个旋转自由度的缺失。只有仅旋转一个轴时,其它两个轴的角度总是为0(不旋转),这时候使用欧拉旋转的结果才是可预期的。

如果我们只旋转z轴,则可以这样:

1
2
3
4
const quat = new Quat()

Quat.fromEuler(quat, 0, 0, getRandomInt(0, 360))
node.setRotation(quat)

其它在3D世界的复杂情况,都需要使用四元数进行旋转来确保结果可预期。

参考链接

  1. 如何形象地理解四元数 - 知乎
  2. 四元数与三维旋转 - PDF
  3. 四元数的可视化 - 3Blue1Brown
  4. 四元数的可视化交互式动画 - 3Blue1Brown
  5. 3D Rotation Converter

非空断言(Non-Null Assertion)

非空断言操作符 ! 是 TypeScript 独有的一项特性,不属于 ECMAScript 标准。非空断言 (Non-Null Assertion) 表示开发者知道这个变量在这里不可能是 null,但是 TypeScript 编译器不知道,这时候就需要我们手动使用 ! 告诉编译器。

在 TypeScript 中,非空断言 (Non-Null Assertion) 的使用场景主要有以下三种:

  1. 用在属性声明或变量声明时
1
2
3
4
5
6
7
8
@ccclass('PlayerController')
export class PlayerController extends Component {
@property({ type: Animation })
public BodyAnim!: Animation

@property({ type: SkeletalAnimation })
public CocosAnim!: SkeletalAnimation
...

比如这里,BodyAnim 和 CocosAnim 我们都是在 Cocos Creator 编辑器中手动完成资源绑定的。这时候就可以确定 BodyAnim 和 CocosAnim 不可能为空,所以可以在这里使用非空断言操作符 !,如果不使用则需要这样:

1
2
3
4
5
@ccclass('PlayerController')
export class PlayerController extends Component {
@property({ type: Animation })
public BodyAnim: Animation | null = null
...

并且在下面使用 this.BodyAnim 时,由于 this.BodyAnim 的类型是 Animation | null 即可能为空,所以需要多一层 if 条件语句判断:

1
2
3
if (this.BodyAnim) {
this.BodyAnim.play('getOneStep')
}

或者使用可选链

1
this.BodyAnim?.play('getOneStep')

但是下面这种情况就不能使用可选链,因为可选链不能出现在赋值表达式左侧

1
2
3
if (this.BodyAnim) {
this.BodyAnim.property = 'value'
}

不管怎样,这些都无疑使得代码变得更加复杂

  1. 在使用变量时

我们可以把上面的 if 条件语句判断改成以下形式:

1
this.BodyAnim!.play('getOneStep')

这段代码与 if 条件语句等价

  1. 在赋值变量前
1
2
3
4
5
6
7
8
const main = () => {
const game = window['game'] = new Game({
width: 1600,
height: 900,
scene: MainScene,
parent: document.getElementById('app')!,
})
}

这里 document.getElementById('app') 的类型是 HTMLDocument | null,可能为 null,所以我们可以通过非空断言 ! 来手动告诉编译器这里这个变量不会为 null。

总结

非空断言操作符 ! 的使用场景是:当你 (开发者) 明确知道这个变量在这个位置不可能为 null 时,可以使用该操作符来强制将这个变量的类型由 SomeType | null 转为 SomeType (即去掉了 null)。使用非空断言操作符可以减少很多无意义的条件语句判断,使得整个代码变得更加简洁。

参考链接

  1. 3.0 TypeScript问题答疑及经验分享 - Cocos 论坛
  2. Non-null assertion operator - TypeScript Documentation

Cocos Creator 3.0怎么做2D游戏

Cocos Creator 3.0 合并了原有的 Cocos Creator 2.x 和 Cocos Creator 3D 1.x 的所有功能,统一了 2D 和 3D 的开发工作流。打开 Cocos Creator 3.0 创作界面默认是 3D 的,我们需要进行以下配置来切换 2D 创作:

  1. 层级管理器

需要手动创建一个 UI组件 - Canvas (画布),所有 2D 对象节点都应在 Canvas 节点下,主摄像机 Main Camera 和主灯光 Main Light 可以删掉。

  1. 切换场景编辑器到 2D 视角

点击 2D/3D 按钮即可切换场景编辑器到 2D 视角。

  1. 修改贴图资源类型为 sprite-frame

在 Cocos Creator 2.x 中,贴图类型 texture (纹理)。在 Creator 3.0 中,如果需要将该贴图在贴图资源拖到层级管理器中作为一个节点则必须先将其 type 修改为 sprite-frame。

  1. 修改图片节点的 Layer 为 UI_2D

在层级管理器中双击图片节点,这里以 background 这个图片节点为例:

再在右边的属性检查器面板将其 Layer 改成 UI_2D。

参考链接

  1. Cocos Creator 3.0 正式版震撼来袭! - 官方论坛
  2. 3.0里怎么做2D游戏 -官方论坛

openGauss用户管理

password_encryption_type 参数说明

该字段决定采用何种加密方式对用户密码进行加密存储。修改此参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。该参数属于 SIGHUP 类型参数,请参考表4-134中对应设置方法进行设置。

修改 password_encryption_type 为 sha256 后,不会影响现有用户的认证方式(默认是通过 md5 认证),我们可以创建一个新的用户,这样可以方便测试 node-opengauss。

启动 gsql 命令行工具后,可以通过下面的命令查询当前所有用户和创建新用户:

1
2
\du # 查看所有数据库用户
create user lolimay Sysadmin password 'Enmo@123'

这里创建了一个用户名为 lolimay 的新用户,角色为 Sysadmin,密码为 Enmo@123

修改环境变量 PG_USERlolimay,重新执行 node-opengauss 测试:

1
PGUSER=lolimay PGPASSWORD=Enmo@123 PGDATABASE=postgres yarn test

会发现,这次会出现 Uncaught Error: SASL: Only mechanism SCRAM-SHA-256 is currently supported 错误,说明对于用户 lolimay,已采用 sha256 的认证方式。对于 node-opengauss 这个项目,我们最终的交互件就是让其支持 sha256 的认证方式,使其成功让 lolimay 用户登录,并能正确执行相应的 SQL 语句。

openGauss GUC参数配置

启动 gsql 工具后,有以下两种方式查询 openGauss 数据库的 GUC 参数:

通过 SQL 查询

所有的 GUC 参数都存储在视图 pg_settings 中,我们可以通过 SQL 语句查询:

1
2
3
select * from pg_settings; # 查看所有 GUC 参数
select * from pg_settings where name='password_encryption_type'; # 查看 password_encryption_type 参数设置
select * from pg_settings where name like 'auth%'; # 查询参数名以 auth 开头的

查询结果:

1
2
3
4
           name           | setting | unit |                           category                           |             short_desc             |                                        extra_desc                                        | context | vartype |       source       | min_val | max_val | enumvals | boot_val | reset_val |               sourcefile                | sourceline
--------------------------+---------+------+--------------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------------------+---------+---------+--------------------+---------+---------+----------+----------+-----------+-----------------------------------------+------------
password_encryption_type | 0 | | Connections and Authentication / Security and Authentication | The encryption method of password. | This controls the encryption type of the password. A value of 2 uses the system default. | sighup | integer | configuration file | 0 | 2 | | 2 | 0 | /var/lib/opengauss/data/postgresql.conf | 870
(1 row)

password_encryption_type 参数说明

该字段决定采用何种加密方式对用户密码进行加密存储。修改此参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。该参数属于 SIGHUP 类型参数,请参考表4-134中对应设置方法进行设置。

取值范围 0、1、2

  • 0 表示使用md5 方式对密码加密
  • 1表示采用sha256和md5两种方式分别对密码加密
  • 2表示采用sha256方式对密码加密

由查询结果可知,当前值为 0,即使用 md5 方式对密码加密;该项配置的源地址在 /var/lib/opengauss/data/postgressql.conf 的第 870 行。

通过 show 命令

此外,我们还可以通过 show 命令直接查询 GUC 参数:

1
2
show all; # 查询所有 GUC 参数
show password_encryption_type; # 查询 GUC 参数 password_encryption_type 的值

参考链接

  1. 配置GUC参数> 查看参数当前取值 - 华为云文档
  2. 数据仓库服务 GaussDB(DWS) - 华为云文档

gsql命令行客户端工具

gsql 是与 openGauss 数据库配套的命令行工具,我们可以利用它来连接数据库、执行SQL语句和执行一些元命令。

基本操作

1
2
3
4
5
6
7
8
[omm@4ae1997a3f9a ~]$ gsql
gsql ((openGauss 1.1.0 build 392c0438) compiled at 2020-12-31 20:07:42 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.

omm=#
omm=# \? # 获取帮助
omm=# \q # 退出

注意,除了执行一些元命令,如 \q 等外,执行 SQL 语句都要记住在末尾加上 ;,以防止和下一条语句冲突。

1
2
omm=# show server_version;
omm=# show all;

参考链接

  1. gsql命令行客户端工具/gsql概述 - 华为云文档

yum更换国内源

编辑 /etc/yum.repos.d/CentOS-Base.repo` 文件,将文件内容覆盖为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[base]
name=CentOS-$releasever - Base
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:/etc/pki/rpm-gpg/RPM-GPG-KEY-7

[updates]
name=CentOS-$releasever - Updates
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:/etc/pki/rpm-gpg/RPM-GPG-KEY-7

[extras]
name=CentOS-$releasever - Extras
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:/etc/pki/rpm-gpg/RPM-GPG-KEY-7

[centosplus]
name=CentOS-$releasever - Plus
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:/etc/pki/rpm-gpg/RPM-GPG-KEY-7

openGauss鉴权配置文件pg_hba.conf

准确来说是 Postgres 的鉴权配置文件,因为 openGauss 源于 PostgresSQL 数据库,主要对内核进行和很大的改动,客户端和服务端的驱动协议修改比较少,但支持了 SHA256 等新的密码存储鉴权方式。

首先进入 docker 容器,

1
2
docker ps # 查看 openGauss 容器的 id
docker exec -it <container-id> /bin/bash; exit # 进入 docker 容器进行操作

切换到 omm 用户,启动 gsql:

1
2
su - omm # 切换到 omm 用户
gsql # 启动 gsql

在 gsql 交互式终端中输入以下命令获取 pg_hba.conf 鉴权配置文件的路径:

1
2
3
4
5
6
7
8
9
10
[omm@4ae1997a3f9a opengauss]$ gsql
gsql ((openGauss 1.1.0 build 392c0438) compiled at 2020-12-31 20:07:42 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.

omm=# show hba_file;
hba_file
-------------------------------------
/var/lib/opengauss/data/pg_hba.conf
(1 row)

此外,对于 enmotech/opengauss 镜像,openGauss 的安装路径在:

1
/usr/local/opengauss

数据路径在:

1
/var/lib/opengauss

pg_hba.conf

  • hba.conf 为 trust,跳过认证;
  • 配置 hba.conf 为 MD5 方式,修改 postgresq.conf 配置文件中的 GUC 参数 password_encryption_type 为 0,表示 MD5 密码存储方式。在这种方式下,与原来PG基本是一样,方便调通流程。可以看一下MD5 认证的基本流程;
  • 配置 hba.conf 为 SHA256 方式,修改 postgresq 配置文件中的 GUC 参数 pssword_encryption_type 为 2 表示 SHA256 密码存储方式(这是 openGauss 新的鉴权方式)调整 SHA256 认证方式;

对于 authmethod-options,其支持以下选项 (cert 和 gss 不要求,但如果有时间的话可以试试):

  • trust: 不验密,禁止远程主机使用trust 方式访问集群
  • reject: 拒绝访问
  • md5: md5认证,默认不支持
  • sha256: sha256认证(推荐使用)
  • cert: 客户端证书认证
  • gss: kerberos认证

password_encryption_type 参数说明

该字段决定采用何种加密方式对用户密码进行加密存储。修改此参数的配置不会自动触发已有用户密码加密方式的修改,只会影响新创建用户或修改用户密码操作。该参数属于 SIGHUP 类型参数,请参考表4-134中对应设置方法进行设置。

取值范围 0、1、2

  • 0 表示使用md5 方式对密码加密
  • 1表示采用sha256和md5两种方式分别对密码加密
  • 2表示采用sha256方式对密码加密

将 trust 方式改为 sha256 认证后,通过 gsql 登录数据库需要指定数据库名,用户名及密码,如:

1
2
3
4
5
6
7
8
9
[omm@4ae1997a3f9a ~]$ gsql -d postgres -U gaussdb -W Enmo@123
gsql: invalid option -- 'D'
Try "gsql --help" for more information.
[omm@4ae1997a3f9a ~]$ gsql -d postgres -U gaussdb -W Enmo@123
gsql ((openGauss 1.1.0 build 392c0438) compiled at 2020-12-31 20:07:42 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.

postgres=>

其中,postgres 是数据库名,gaussdb 是用户名,Enmo@123 是密码。

更多详细信息查阅参考链接中的官方文档 The pg_hba.conf - Postgres Documentation

参考链接

  1. How do I find the path to pg_hba.conf from the shell?
  2. The pg_hba.conf - Postgres Documentation