gino.crud module
class gino.crud.Alias
(model, \args, **kwargs*)
基类:object
Experimental proxy for table alias on model.
distinct
(\columns*)load
(\column_names, **relationships*)on
(on_clause)
class gino.crud.CRUDModel
(\*values*)
The base class for models with CRUD support.
Don’t inherit from this class directly, because it has no metadata. Use db.Model
instead.
classmethod
alias
(\args, **kwargs*)Experimental proxy for table alias on model.
append_where_primary_key
(q)Append where clause to locate this model instance by primary on the given query, and return the new query.
This is mostly used internally in GINO, but also available for such usage:
await user.append_where_primary_key(User.query).gino.first()
which is identical to:
await user.query.gino.first()
0.7.6 版后已移除: Use
lookup()
instead.create
(bind=None, timeout=<object object>, \*values*)This
create
behaves a bit different on model classes compared to model instances.On model classes,
create
will create a new model instance and insert it into database. On model instances,create
will just insert the instance into the database.Under the hood
create()
usesINSERT ... RETURNING ...
to create the new model instance and load it with database default data if not specified.Some examples:
user1 = await User.create(name='fantix', age=32)
user2 = User(name='gino', age=42)
await user2.create()
参数
bind — A
GinoEngine
to execute theINSERT
statement with, orNone
(default) to use the bound engine on the metadata (Gino
).timeout — Seconds to wait for the database to finish executing,
None
for wait forever. By default it will use thetimeout
execution option value if unspecified.values — Keyword arguments are pairs of attribute names and their initial values. Only available when called on a model class.
返回
The instance of this model class (newly created or existing).
delete
Similar to
update()
, thisdelete
is also different on model classes than on model instances.On model classes
delete
is an attribute of typeDelete
for massive deletes, for example:await User.delete.where(User.enabled.is_(False)).gino.status()
Similarly you can add a
returning()
clause to the query and it shall return the deleted rows as model objects.And on model instances,
delete()
is a method to remove the corresponding row in the database of this model instance. and returns the status returned from the database:print(await user.delete()) # e.g. prints DELETE 1
注解
delete()
only removes the row from database, it does not affect the current model instance.参数
bind — An optional
GinoEngine
if current metadata (Gino
) has no bound engine, or specifying a differentGinoEngine
to execute theDELETE
.timeout — Seconds to wait for the database to finish executing,
None
for wait forever. By default it will use thetimeout
execution option value if unspecified.
classmethod
distinct
(\columns*)Experimental loader feature to yield only distinct instances by given columns.
async classmethod
get
(ident, bind=None, timeout=<object object>)Get an instance of this model class by primary key.
For example:
user = await User.get(request.args.get('user_id'))
参数
ident — Value of the primary key. For composite primary keys this should be a tuple of values for all keys in database order, or a dict of names (or position numbers in database order starting from zero) of all primary keys to their values.
bind — A
GinoEngine
to execute theINSERT
statement with, orNone
(default) to use the bound engine on the metadata (Gino
).timeout — Seconds to wait for the database to finish executing,
None
for wait forever. By default it will use thetimeout
execution option value if unspecified.
返回
An instance of this model class, or
None
if no such row.
classmethod
in_query
(query)Convenient method to get a Model object when using subqueries.
Though with filters and aggregations, subqueries often return same columns as the original table, but SQLAlchemy could not recognize them as the columns are in subqueries, so technically they’re columns in the new “table”.
With this method, the columns are loaded into the original models when being used in subqueries. For example:
query = query.alias('users')
MyUser = User.in_query(query)
loader = MyUser.distinct(User1.id).load()
users = await query.gino.load(loader).all()
classmethod
load
(\column_names, **relationships*)Populates a
loader.Loader
instance to be used by theloader
execution option in order to customize the loading behavior to load specified fields into instances of this model.The basic usage of this method is to provide the
loader
execution option (if you are looking for reloading the instance from database, checkget()
orquery
) for a given query.This method takes both positional arguments and keyword arguments with very different meanings. The positional arguments should be column names as strings, specifying only these columns should be loaded into the model instance (other values are discarded even if they are retrieved from database). Meanwhile, the keyword arguments should be loaders for instance attributes. For example:
u = await User.query.gino.load(User.load('id', 'name')).first()
小技巧
gino.load
is a shortcut for setting the execution optionloader
.This will populate a
User
instance with onlyid
andname
values, all the rest are simplyNone
even if the query actually returned all the column values.q = User.join(Team).select()
u = await q.gino.load(User.load(team=Team)).first()
This will load two instances of model
User
andTeam
, returning theUser
instance withu.team
set to theTeam
instance.Both positional and keyword arguments can be used ath the same time. If they are both omitted, like
Team.load()
, it is equivalent to justTeam
as a loader.Additionally, a
loader.Loader
instance can also be used to generate queries, as its structure is usually the same as the query:u = await User.load(team=Team).query.gino.first()
This generates a query like this:
SELECT users.xxx, ..., teams.xxx, ...
FROM users LEFT JOIN teams
ON ...
The
Loader
delegates attributes on thequery
, so.query
can be omitted. TheLEFT JOIN
is built-in behavior, while theON
clause is generated based on foreign key. If there is no foreign key, or the condition should be customized, you can use this:u = await User.load(
team=Team.on(User.team_id == Team.id)).gino.first()
And you can use both
load()
andon()
at the same time in a chain, in whatever order suits you.参见
lookup
()Generate where-clause expression to locate this model instance.
By default this method uses current values of all primary keys, and you can override it to behave differently. Most instance-level CRUD operations depend on this method internally. Particularly while
lookup()
is called inupdate()
, the where condition is used inUpdateRequest.apply()
, so that queries likeUPDATE ... SET id = NEW WHERE id = OLD
could work correctly.- 返回
0.7.6 新版功能.
classmethod
none_as_none
(enabled=True)classmethod
on
(on_clause)Customize the on-clause for the auto-generated outer join query.
注解
This has no effect when provided as the
loader
execution option for a given query.参见
query
Get a SQLAlchemy query clause of the table behind this model. This equals to
sqlalchemy.select([self.__table__])
. If this attribute is retrieved on a model instance, then a where clause to locate this instance by its primary key is appended to the returning query clause. This model type is set as the execution optionmodel
in the returning clause, so by default the query yields instances of this model instead of database rows.select
()Build a query to retrieve only specified columns from this table.
This method accepts positional string arguments as names of attributes to retrieve, and returns a
Select
for query. The returning query object is always set with two execution options:model
is set to this model typereturn_model
is set toFalse
So that by default it always return rows instead of model instances, while column types can be inferred correctly by the
model
option.For example:
async for row in User.select('id', 'name').gino.iterate():
print(row['id'], row['name'])
If
select()
is invoked on a model instance, then aWHERE
clause to locate this instance by its primary key is appended to the returning query clause. This is useful when you want to retrieve a latest value of a field on current model instance from database:db_age = await user.select('age').gino.scalar()
参见
to_dict
()Convenient method to generate a dict from this model instance.
Keys will be attribute names, while values are loaded from memory (not from database). If there are
JSONProperty
attributes in this model, their source JSON field will not be included in the returning dict - instead the JSON attributes will be.参见
update
This
update
behaves quite different on model classes rather than model instances.On model classes,
update
is an attribute of typeUpdate
for massive updates, for example:await User.update.values(enabled=True).where(...).gino.status()
Like
query
, the update query also has themodel
execution option of this model, so if you use thereturning()
clause, the query shall return model objects.However on model instances,
update()
is a method which accepts keyword arguments only and returns anUpdateRequest
to update this single model instance. The keyword arguments are pairs of attribute names and new values. This is the same asUpdateRequest.update()
, feel free to read more about it. A normal usage example would be like this:await user.update(name='new name', age=32).apply()
Here, the
await ... apply()
executes the actualUPDATE
SQL in the database, whileuser.update()
only makes changes in the memory, and collect all changes into anUpdateRequest
instance.
class gino.crud.QueryModel
基类:type
Metaclass of Model classes used for subqueries.
class gino.crud.UpdateRequest
(instance: gino.crud.CRUDModel)
基类:object
A collection of attributes and their new values to update on one model instance.
UpdateRequest
instances are created by CRUDModel.update
, don’t instantiate manually unless required. Every UpdateRequest
instance is bound to one model instance, all updates are for that one specific model instance and its database row.
async
apply
(bind=None, timeout=<object object>)Apply pending updates into database by executing an
UPDATE
SQL.参数
bind — A
GinoEngine
to execute the SQL, orNone
(default) to use the bound engine in the metadata.timeout — Seconds to wait for the database to finish executing,
None
for wait forever. By default it will use thetimeout
execution option value if unspecified.
返回
self
for chaining calls.
update
(\*values*)Set given attributes on the bound model instance, and add them into the update collections for
apply()
.Given keyword-only arguments are pairs of attribute names and values to update. This is not a coroutine, calling
update()
will have instant effect on the bound model instance - its in-memory values will be updated immediately. Therefore this can be used individually as a shortcut to update several attributes in a batch:user.update(age=32, disabled=True)
update()
returnsself
for chaining calls to eitherapply()
or anotherupdate()
. If one attribute is updated several times by the sameUpdateRequest
, then only the last value is remembered forapply()
.Updated values can be SQLAlchemy expressions, for example an atomic increment for user balance looks like this:
await user.update(balance=User.balance + 100).apply()
注解
Expression values will not affect the in-memory attribute value on
update()
beforeapply()
, because it has no knowledge of the latest value in the database. Afterapply()
the new value will be automatically reloaded from database withRETURNING
clause.