Alpha database system
Automatic structure
Compared to native SqlAlchemy in alpha you only need to instantiate the table model:
from alphaz.models.database.models import AlphaTable, AlphaColumn
DB = core.db
class DuckType(DB.Model, AlphaTable):
__bind_key__ = DB
__tablename__= "duck_type"
type_id = AlphaColumn(INTEGER, primary_key=True, autoincrement=True)
name = AlphaColumn(TEXT,nullable = False, default = "SuperDuck")
class DuckMedal(DB.Model, AlphaTable):
__bind_key__ = DB
__tablename__= "duck_medal"
name = AlphaColumn(TEXT,nullable = False, default = "Lucky")
duck_id = AlphaColumn(INTEGER, ForeignKey ('duck.duck_id' ), nullable = False, default= -1)
class Duck(DB.Model, AlphaTable):
__bind_key__ = DB
__tablename__= "duck"
duck_id = AlphaColumn(INTEGER, primary_key=True, autoincrement=True, visible=False)
name = AlphaColumn(TEXT,nullable = False, default = "")
# Many to one
duck_type_id = AlphaColumn(INTEGER, ForeignKey ('duck_type.type_id'), nullable = False, default = -1, visible=False)
duck_type = relationship("DuckType")
# One to many
medals = relationship("DuckMedals")
By default a select query on Duck class defined like this:
master_duck = DuckType(ame="Master Duck")
DB.add(master_duck)
ducky = Duck(name="Ducky",duck_type=master_duck)
DB.add(ducky)
honnor_medal = DuckMedal(name="Honnor",duck_id=ducky.duck_id)
lucky_medal = DuckMedal(name="Lucky",duck_id=ducky.duck_id)
DB.add(ducky)
ducks = DB.select(Duck, filters=[Duck.name=="Ducky"], first=True)
Will result in this:
{
"duck_id": 1,
"name": "Ducky",
"duck_type": {
"type_id": 1,
"duck_type": "Master Duck"
},
"medals": [{ "name": "Honnor" }, { "name": "Lucky" }]
}
Schema
Note
The associated Schema is created automatically, with classic and nested fields.
However Marshmallow schema could be defined using the classic way Marshmallow:
- Set visible to False if you dont want the column to appears in the Schema.
Important
Schema must be defined after the Model
DB = core.db
class DuckTypeSchema(Schema):
type_id = fields.Integer()
name = fields.String()
class DuckMedalSchema(Schema):
name = fields.String()
class DuckSchema(Schema):
name = fields.String()
# Many to One
duck_type = fields.Nested(DuckTypeSchema)
# One to many
medals = fields.List(fields.Nested(DuckMedalSchema))
Important
Alpha will automatically detect the schema if the name is defined as "{ModelName}Schema"
and is located in the same file.
Note
In this mode, Schema could be defined automatically, excepted for nested fields.
Specific Schema
Schema could be specified for every request:
DB.select(model = Duck, schema = DuckSchema)
Alpha notation
init
This enable the use of model columns which is not possible using SqlAlchemy:
attr = {
Duck.name: name,
Duck.duck_type_id: duck_type_id,
}
duck = Duck()
duck.init(attr)
or
duck = Duck()
duck.init({
Duck.name: name,
Duck.duck_type_id: duck_type_id,
})
Instead of:
attr = {
Duck.name: name,
Duck.duck_type_id: duck_type_id,
}
duck = Duck()
duck.init(**{x.key:y for x,y in attr.items()})
Update
Classic SQLAlchemy
Select query
duck = Duck.query.filter_by(name=name).first()
duck.duck_type_id = duck_type_id
db.session.commit()
Init
new_duck = Duck("name": name, "duck_type_id": duck_type_id)
db.session.merge(new_duck)
db.session.commit()
or
attr = {
"name": name,
"duck_type_id": duck_type_id,
}
duck = Duck(**attr)
db.session.merge(new_duck)
db.session.commit()
Init and update
new_duck = Duck()
new_duck.name = name
new_duck.duck_type_id = duck_type_id
db.session.merge(new_duck)
db.session.commit()
Update
Alphaz include a special update method that simplifies updates via api routes
Model as a parameter
Warning
This is not recommanded because you could not specified if a field of Duck is required or not
@route(
path='duck',
methods=["PUT"],
parameters=[
Parameter("duck", ptype=Duck, required=True)
],
)
def update_duck():
return DB.update(api["duck"])
Route parameters to model
@route(
path='duck',
methods=["PUT"],
parameters=[
Parameter("name", ptype=str, required=True),
Parameter("duck_type_id", ptype=int)
],
)
def update_duck():
return DB.update(Duck(**api.get_parameters()), not_none=True) # not_none is to set if you dont want None values to update fields
or using a function:
def update_duck(name:str, duck_type_id:str):
return DB.update(Duck(**locals()))
@route(
path='duck',
methods=["PUT"],
parameters=[
Parameter("name", ptype=str, required=True),
Parameter("duck_type_id", ptype=int)
],
)
def update_duck():
return update_duck(**api.get_parameters())
Relations
Relation filter
return DB.select(
Duck,
filters=[Duck.duck_type.has(DuckType.name.like(name))]
)
Will produce a query like:
SELECT * FROM DUCK WHERE EXISTS (SELECT 1 FROM DUCKTYPE where DUCKTYPE.id==DUCK.ducktype_id and DUCKTYPE.name=name)