⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ormtutorial.txt

📁 SQLAlchemy. 经典的Python ORM框架。学习必看。
💻 TXT
📖 第 1 页 / 共 4 页
字号:
An eagerload targeting across multiple relations can use dot separated names:    {python}    query.options(eagerload('orders'), eagerload('orders.items'), eagerload('orders.items.keywords'))    To roll up the above three individual `eagerload()` calls into one, use `eagerload_all()`:    {python}    query.options(eagerload_all('orders.items.keywords'))    ## Querying with Joins {@name=joins}Which brings us to the next big topic.  What if we want to create joins that *do* change the results ?  For that, another `Query` tornado is coming....One way to join two tables together is just to compose a SQL expression.   Below we make one up using the `id` and `user_id` attributes on our mapped classes:    {python}    {sql}>>> session.query(User).filter(User.id==Address.user_id).\    ...         filter(Address.email_address=='jack@google.com').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password     FROM users, addresses     WHERE users.id = addresses.user_id AND addresses.email_address = ? ORDER BY users.oid    ['jack@google.com']    {stop}[<User('jack','Jack Bean', 'gjffdd')>]Or we can make a real JOIN construct; below we use the `join()` function available on `Table` to create a `Join` object, then tell the `Query` to use it as our FROM clause:    {python}    {sql}>>> session.query(User).select_from(users_table.join(addresses_table)).\    ...         filter(Address.email_address=='jack@google.com').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password     FROM users JOIN addresses ON users.id = addresses.user_id     WHERE addresses.email_address = ? ORDER BY users.oid    ['jack@google.com']    {stop}[<User('jack','Jack Bean', 'gjffdd')>]Note that the `join()` construct has no problem figuring out the correct join condition between `users_table` and `addresses_table`..the `ForeignKey` we constructed says it all.The easiest way to join is automatically, using the `join()` method on `Query`.  Just give this method the path from A to B, using the name of a mapped relationship directly:    {python}    {sql}>>> session.query(User).join('addresses').\    ...     filter(Address.email_address=='jack@google.com').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password     FROM users JOIN addresses ON users.id = addresses.user_id     WHERE addresses.email_address = ? ORDER BY users.oid    ['jack@google.com']    {stop}[<User('jack','Jack Bean', 'gjffdd')>]By "A to B", we mean a single relation name or a path of relations.  In our case we only have `User->addresses->Address` configured, but if we had a setup like `A->bars->B->bats->C->widgets->D`, a join along all four entities would look like:    {python}    session.query(Foo).join(['bars', 'bats', 'widgets']).filter(...)    Each time `join()` is called on `Query`, the **joinpoint** of the query is moved to be that of the endpoint of the join.  As above, when we joined from `users_table` to `addresses_table`, all subsequent criterion used by `filter_by()` are against the `addresses` table.  When you `join()` again, the joinpoint starts back from the root.  We can also backtrack to the beginning explicitly using `reset_joinpoint()`.  This instruction will place the joinpoint back at the root `users` table, where subsequent `filter_by()` criterion are again against `users`:    {python}    {sql}>>> session.query(User).join('addresses').\    ...     filter_by(email_address='jack@google.com').\    ...     reset_joinpoint().filter_by(name='jack').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password     FROM users JOIN addresses ON users.id = addresses.user_id     WHERE addresses.email_address = ? AND users.name = ? ORDER BY users.oid    ['jack@google.com', 'jack']    {stop}[<User('jack','Jack Bean', 'gjffdd')>]In all cases, we can get the `User` and the matching `Address` objects back at the same time, by telling the session we want both.  This returns the results as a list of tuples:    {python}    {sql}>>> session.query(User).add_entity(Address).join('addresses').\    ...     filter(Address.email_address=='jack@google.com').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password, addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id     FROM users JOIN addresses ON users.id = addresses.user_id     WHERE addresses.email_address = ? ORDER BY users.oid    ['jack@google.com']    {stop}[(<User('jack','Jack Bean', 'gjffdd')>, <Address('jack@google.com')>)]Another common scenario is the need to join on the same table more than once.  For example, if we want to find a `User` who has two distinct email addresses, both `jack@google.com` as well as `j25@yahoo.com`, we need to join to the `Addresses` table twice.  SQLAlchemy does provide `Alias` objects which can accomplish this; but far easier is just to tell `join()` to alias for you:    {python}    {sql}>>> session.query(User).\    ...     join('addresses', aliased=True).filter(Address.email_address=='jack@google.com').\    ...     join('addresses', aliased=True).filter(Address.email_address=='j25@yahoo.com').all()    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password     FROM users JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id JOIN addresses AS addresses_2 ON users.id = addresses_2.user_id     WHERE addresses_1.email_address = ? AND addresses_2.email_address = ? ORDER BY users.oid    ['jack@google.com', 'j25@yahoo.com']    {stop}[<User('jack','Jack Bean', 'gjffdd')>]The key thing which occurred above is that our SQL criterion were **aliased** as appropriate corresponding to the alias generated in the most recent `join()` call.The next section describes some "higher level" operators, including `any()` and `has()`, which make patterns like joining to multiple aliases unnecessary in most cases.### Relation OperatorsA summary of all operators usable on relations:* Filter on explicit column criterion, combined with a join.  Column criterion can make usage of all supported SQL operators and expression constructs:        {python}        {sql}>>> session.query(User).join('addresses').\        ...    filter(Address.email_address=='jack@google.com').all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users JOIN addresses ON users.id = addresses.user_id         WHERE addresses.email_address = ? ORDER BY users.oid        ['jack@google.com']        {stop}[<User('jack','Jack Bean', 'gjffdd')>]    Criterion placed in `filter()` usually correspond to the last `join()` call; if the join was specified with `aliased=True`, class-level criterion against the join's target (or targets) will be appropriately aliased as well.          {python}        {sql}>>> session.query(User).join('addresses', aliased=True).\        ...    filter(Address.email_address=='jack@google.com').all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id         WHERE addresses_1.email_address = ? ORDER BY users.oid        ['jack@google.com']        {stop}[<User('jack','Jack Bean', 'gjffdd')>]* Filter_by on key=value criterion, combined with a join.  Same as `filter()` on column criterion except keyword arguments are used.        {python}        {sql}>>> session.query(User).join('addresses').\        ...    filter_by(email_address='jack@google.com').all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users JOIN addresses ON users.id = addresses.user_id         WHERE addresses.email_address = ? ORDER BY users.oid        ['jack@google.com']        {stop}[<User('jack','Jack Bean', 'gjffdd')>]    * Filter on explicit column criterion using `any()` (for collections) or `has()` (for scalar relations).  This is a more succinct method than joining, as an `EXISTS` subquery is generated automatically.  `any()` means, "find all parent items where any child item of its collection meets this criterion":        {python}        {sql}>>> session.query(User).\        ...    filter(User.addresses.any(Address.email_address=='jack@google.com')).all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE EXISTS (SELECT 1         FROM addresses         WHERE users.id = addresses.user_id AND addresses.email_address = ?) ORDER BY users.oid        ['jack@google.com']        {stop}[<User('jack','Jack Bean', 'gjffdd')>]    `has()` means, "find all parent items where the child item meets this criterion":        {python}        {sql}>>> session.query(Address).\        ...    filter(Address.user.has(User.name=='jack')).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE EXISTS (SELECT 1         FROM users         WHERE users.id = addresses.user_id AND users.name = ?) ORDER BY addresses.oid        ['jack']        {stop}[<Address('jack@google.com')>, <Address('j25@yahoo.com')>]    Both `has()` and `any()` also accept keyword arguments which are interpreted against the child classes' attributes:        {python}        {sql}>>> session.query(User).\        ...    filter(User.addresses.any(email_address='jack@google.com')).all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE EXISTS (SELECT 1         FROM addresses         WHERE users.id = addresses.user_id AND addresses.email_address = ?) ORDER BY users.oid        ['jack@google.com']        {stop}[<User('jack','Jack Bean', 'gjffdd')>]    * Filter_by on instance identity criterion.  When comparing to a related instance, `filter_by()` will in most cases not need to reference the child table, since a child instance already contains enough information with which to generate criterion against the parent table.  `filter_by()` uses an equality comparison for all relationship types.  For many-to-one and one-to-one, this represents all objects which reference the given child object:        {python}        # locate a user        {sql}>>> user = session.query(User).filter(User.name=='jack').one() #doctest: +NORMALIZE_WHITESPACE        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE users.name = ? ORDER BY users.oid         LIMIT 2 OFFSET 0        ['jack']        {stop}                # use the user in a filter_by() expression        {sql}>>> session.query(Address).filter_by(user=user).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE ? = addresses.user_id ORDER BY addresses.oid        [5]        {stop}[<Address('jack@google.com')>, <Address('j25@yahoo.com')>]    For one-to-many and many-to-many, it represents all objects which contain the given child object in the related collection:        {python}        # locate an address        {sql}>>> address = session.query(Address).\        ...    filter(Address.email_address=='jack@google.com').one() #doctest: +NORMALIZE_WHITESPACE        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE addresses.email_address = ? ORDER BY addresses.oid         LIMIT 2 OFFSET 0        {stop}['jack@google.com']            # use the address in a filter_by expression        {sql}>>> session.query(User).filter_by(addresses=address).all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE users.id = ? ORDER BY users.oid        [5]        {stop}[<User('jack','Jack Bean', 'gjffdd')>]* Select instances with a particular parent.  This is the "reverse" operation of filtering by instance identity criterion; the criterion is against a relation pointing *to* the desired class, instead of one pointing *from* it.  This will utilize the same "optimized" query criterion, usually not requiring any joins:        {python}        {sql}>>> session.query(Address).with_parent(user, property='addresses').all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE ? = addresses.user_id ORDER BY addresses.oid        [5]        {stop}[<Address('jack@google.com')>, <Address('j25@yahoo.com')>]        * Filter on a many-to-one/one-to-one instance identity criterion.  The class-level `==` operator will act the same as `filter_by()` for a scalar relation:        {python}        {sql}>>> session.query(Address).filter(Address.user==user).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE ? = addresses.user_id ORDER BY addresses.oid        [5]        {stop}[<Address('jack@google.com')>, <Address('j25@yahoo.com')>]    whereas the `!=` operator will generate a negated EXISTS clause:        {python}        {sql}>>> session.query(Address).filter(Address.user!=user).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE NOT (EXISTS (SELECT 1         FROM users         WHERE users.id = addresses.user_id AND users.id = ?)) ORDER BY addresses.oid        [5]        {stop}[]    a comparison to `None` also generates an IS NULL clause for a many-to-one relation:        {python}        {sql}>>> session.query(Address).filter(Address.user==None).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE addresses.user_id IS NULL ORDER BY addresses.oid        []        {stop}[]* Filter on a one-to-many instance identity criterion.  The `contains()` operator returns all parent objects which contain the given object as one of its collection members:        {python}        {sql}>>> session.query(User).filter(User.addresses.contains(address)).all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE users.id = ? ORDER BY users.oid        [5]        {stop}[<User('jack','Jack Bean', 'gjffdd')>]* Filter on a multiple one-to-many instance identity criterion.  The `==` operator can be used with a collection-based attribute against a list of items, which will generate multiple `EXISTS` clauses:        {python}        {sql}>>> addresses = session.query(Address).filter(Address.user==user).all()        SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id         FROM addresses         WHERE ? = addresses.user_id ORDER BY addresses.oid        [5]        {stop}                {sql}>>> session.query(User).filter(User.addresses == addresses).all()        SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password         FROM users         WHERE (EXISTS (SELECT 1         FROM addresses         WHERE users.id = addresses.user_id AND addresses.id = ?)) AND (EXISTS (SELECT 1         FROM addresses         WHERE users.id = addresses.user_id AND addresses.id = ?)) ORDER BY users.oid        [1, 2]        {stop}[<User('jack','Jack Bean', 'gjffdd')>]## Deleting

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -