Model
Model
は、jsonスキーマまたはyaml形式で記述されたテーブル定義からデータベーステーブルを自動生成し、SQLAlchemy
でORマップしてmodel
共通コンテキストにエントリするサービスです。ATOM
サービスから生成されるテーブルオブジェクトも本サービスを内部的に利用しています。
プラグイン開発者がテーブルスキーマを記述して本サービスを直接利用することが可能ですが、ATOM
サービスを利用してデータベースモデルを生成する方が圧倒的に単純です。
モデルが保有する属性
属性 |
概要 | 備考 |
---|---|---|
name |
モデルの名前をユニークに指定します。 | データベースのテーブル名となります。ATOM から生成される場合は、ATOMのクラス名が使用されます。 |
category |
テーブルのカテゴリを指定します。 | カテゴリには特別な役割はありません。シンプルなラベルです。 |
schema |
jsonschema またはyaml を使用してテーブルのカラム定義を記述します。 |
|
constraints | テーブル属性の制約を指定します。 | - |
primary key |
テーブルの主キーを指定します。 | - |
unique key |
テーブルのユニークキーを指定します。 | - |
unique key list |
テーブルの複合ユニークキーを指定します。 | - |
foreign key | テーブルの外部キーを指定します。 | - |
scenario auto generate mode |
テーブルのCRUDシナリオを自動的に生成するためのモードを指定します。 | ATOM の利用を推奨している為、将来的には廃止される予定です。デフォルトは False です。 |
base path |
シナリオ自動生成モードがTrue の場合に生成されるAPIの基底パスを指定できます。 |
scenario auto generate mode 同様に現在は非推奨としています。 |
Caution
データベースにPostgreSQLを利用する場合、モデルの名前を先頭大文字の名前で生成すると生のSQL文で操作しにくくなりますので注意してください。テーブル名をクォーテーションで括るなどする必要が出てきます。
カラム定義について
列定義は、次のパラメーターを指定します。
type
- JSONの型表現でデータベースの列型を指定します。SQLAlchemyタイプへの変換ルールは次のとおりです。
json type | database type |
---|---|
integer | sqlalchemy.types.Integer |
number | sqlalchemy.types.Float |
boolean | sqlalchemy.types.Boolean |
string | sqlalchemy.types.String |
object | sqlalchemy.types.Text |
array | sqlalchemy.types.Text |
dbtype
char
やsmallint
などを使用したい場合は、データベース特化した型の指定は、dbtype
を使用します。length
- 列の桁数を指定します。typeがstringで、長さが64に指定されている場合、それは
sqlalchemy.types.String(64)
に変換されます。指定しない場合、デフォルトの長さは、Text
タイプの場合は65535
、String
タイプの場合は255
です。 default
- 列のPythonレイヤのデフォルト値を指定します。CREATE TABLEステートメントには影響しません。
server_default
- 列のデータベースレイヤのデフォルト値を指定します。CREATE TABLEステートメントに影響します。
integer
などの数値型を指定するときは注意してください。SQLAlchemy仕様では、server_default:0
は許可されておらず、server_default:"0"
として指定する必要があります。 func
- SQLAlchemyの組込み関数を指定します。関数名は
sqlalchemy.func
の下に存在する必要があります。指定された関数は、列default
に設定されます。
Note
Not NULL制約は、jsonschemaのrequired
で制御されます。
Example
# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
name: countrylanguage
schema:
type: object
properties:
CountryCode:
type: string
dbtype: CHAR
length: 3
Language:
type: string
dbtype: CHAR
length: 30
IsOfficial:
type: boolean
server_default: 'false'
Percentage:
type: number
default: 0
required:
- CountryCode
- Language
- IsOfficial
constraints:
primary_key: CountryCode
# Database terminal
mysql> desc countrylanguage;
+-------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+-------+
| CountryCode | char(3) | NO | PRI | NULL | |
| Language | char(30) | NO | | NULL | |
| IsOfficial | tinyint(1) | NO | | 0 | |
| Percentage | float | YES | | NULL | |
+-------------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
... await conn.execute(model.countrylanguage.insert().values(CountryCode="ABW", Language="English", Percentage=9.5))↵
... ↵
... async with model.aiodb() as conn:↵
... cursor = await conn.execute(model.countrylanguage.select())↵
... rows = await cursor.fetchall()↵
... [print(row) for row in rows]↵
... ↵
('ABW', 'English', False, 9.5)↵
↵
# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
name: country
schema:
type: object
properties:
Code:
type: string
dbtype: CHAR
length: 3
Name:
type: string
dbtype: CHAR
length: 52
Continent:
type: string
Region:
type: string
dbtype: CHAR
length: 26
default: Asia
SurfaceArea:
type: number
default: 0
IndepYear:
type: integer
dbtype: SMALLINT
Population:
type: integer
LifeExpectancy:
type: number
GNP:
type: number
LocalName:
type: string
dbtype: CHAR
length: 45
GovernmentForm:
type: string
dbtype: CHAR
length: 45
HeadOfState:
type: string
dbtype: CHAR
length: 60
Capital:
type: integer
required:
- Code
- Name
- Continent
- Region
- SurfaceArea
- Population
- LocalName
- GovernmentForm
constraints:
primary_key: Code
unique_keys:
- Name
# Database terminal
mysql> desc country;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| Code | char(3) | NO | PRI | NULL | |
| Name | char(52) | NO | UNI | NULL | |
| Continent | varchar(255) | NO | | NULL | |
| Region | char(26) | NO | | NULL | |
| SurfaceArea | float | NO | | NULL | |
| IndepYear | smallint(6) | YES | | NULL | |
| Population | int(11) | NO | | NULL | |
| LifeExpectancy | float | YES | | NULL | |
| GNP | float | YES | | NULL | |
| LocalName | char(45) | NO | | NULL | |
| GovernmentForm | char(45) | NO | | NULL | |
| HeadOfState | char(60) | YES | | NULL | |
| Capital | int(11) | YES | | NULL | |
+----------------+--------------+------+-----+---------+-------+
13 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
... await conn.execute(model.country.insert().values(Code="AFG", Name="Afghanistan", Region="Southern and Central Asia", Continent="Asia",↵
... SurfaceArea=652090.00, Population=22720000, LocalName="Afganistan/Afqanestan", GovernmentForm="Islamic Emirate"))↵
... ↵
... async with model.aiodb() as conn:↵
... cursor = await conn.execute(model.country.select())↵
... rows = await cursor.fetchall()↵
... [print(row) for row in rows]↵
... ↵
('AFG', 'Afghanistan', 'Asia', 'Southern and Central Asia', 652090.0, None, 22720000, None, None, 'Afganistan/Afqanestan', 'Islamic Emirate', None, None)↵
↵
# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
name: city
schema:
type: object
properties:
ID:
type: integer
Name:
type: string
dbtype: CHAR
length: 35
CountryCode:
type: string
dbtype: CHAR
length: 3
District:
type: string
dbtype: CHAR
length: 20
Population:
type: integer
default: 0
required:
- ID
- Name
- CountryCode
- District
constraints:
primary_key: ID
unique_keys:
- Name
foreign_keys:
- table: country
column: Code
key: CountryCode
# Database terminal
mysql> desc city;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | UNI | NULL | |
| CountryCode | char(3) | NO | MUL | NULL | |
| District | char(20) | NO | | NULL | |
| Population | int(11) | YES | | NULL | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
... await conn.execute(model.city.insert().values(Name="Kabul", CountryCode="AFG", District="Kabol", Population=1780000))↵
... ↵
... async with model.aiodb() as conn:↵
... cursor = await conn.execute(model.city.select())↵
... rows = await cursor.fetchall()↵
... [print(row) for row in rows]↵
... ↵
(1, 'Kabul', 'AFG', 'Kabol', 1780000)↵
↵