Skip to content

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)

Doc