mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-31 21:08:36 -04:00
This commit is contained in:
Vendored
+201
@@ -1,3 +1,204 @@
|
||||
<%flags>inherit='document_base.myt'</%flags>
|
||||
<&|doclib.myt:item, name="datamapping", description="Basic Data Mapping" &>
|
||||
|
||||
<&|doclib.myt:item, name="synopsis", description="Synopsis" &>
|
||||
|
||||
<&|formatting.myt:code&>
|
||||
from sqlalchemy.schema import *
|
||||
from sqlalchemy.mapper import *
|
||||
import sqlalchemy.sqlite as sqlite
|
||||
engine = sqllite.engine(':memory:', {})
|
||||
|
||||
# table <& formatting.myt:link, path="metadata", text="metadata" &>
|
||||
users = Table('users', engine,
|
||||
Column('user_id', INTEGER, primary_key = True),
|
||||
Column('user_name', VARCHAR(16), nullable = False),
|
||||
Column('email_address', VARCHAR(60), key='email'),
|
||||
Column('password', VARCHAR(20), nullable = False)
|
||||
)
|
||||
|
||||
# class definition
|
||||
class User(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
# obtain a Mapper
|
||||
m = mapper(User, users)
|
||||
|
||||
# select
|
||||
user = m.select(users.c.user_name == 'fred')[0]
|
||||
|
||||
# modify
|
||||
user.user_name == 'fred jones'
|
||||
|
||||
# commit
|
||||
objectstore.commit()
|
||||
|
||||
</&>
|
||||
</&>
|
||||
|
||||
<&|doclib.myt:item, name="onetomany", description="One to Many" &>
|
||||
|
||||
<&|formatting.myt:code&>
|
||||
# second table <& formatting.myt:link, path="metadata", text="metadata" &>
|
||||
addresses = Table('email_addresses', engine,
|
||||
Column('address_id', INT, primary_key = True),
|
||||
Column('user_id', INT, foreign_key = ForeignKey(users.c.user_id)),
|
||||
Column('email_address', VARCHAR(20)),
|
||||
)
|
||||
|
||||
# second class definition
|
||||
class Address(object):
|
||||
def __init__(self, email_address = None):
|
||||
self.email_address = email_address
|
||||
|
||||
# obtain a Mapper. "private=True" means deletions of the user
|
||||
# will cascade down to the child Address objects
|
||||
m = mapper(User, users, properties = dict(
|
||||
addresses = relation(Address, addresses, lazy=True, private=True)
|
||||
))
|
||||
|
||||
# select
|
||||
user = m.select(users.c.user_name == 'fred')[0]
|
||||
address = user.addresses[0]
|
||||
|
||||
# modify
|
||||
user.user_name == 'fred jones'
|
||||
user.addresses[0].email_address = 'fredjones@foo.com'
|
||||
user.addresses.append(Address('freddy@hi.org'))
|
||||
|
||||
# commit
|
||||
objectstore.commit()
|
||||
|
||||
</&>
|
||||
</&>
|
||||
|
||||
<&|doclib.myt:item, name="onetoone", description="One to One" &>
|
||||
|
||||
<&|formatting.myt:code&>
|
||||
# a table to store a user's preferences for a site
|
||||
prefs = Table('user_prefs', engine,
|
||||
Column('pref_id', INT, primary_key = True),
|
||||
Column('stylename', VARCHAR(20)),
|
||||
Column('save_password', BOOLEAN, nullable = False),
|
||||
Column('timezone', CHAR(3), nullable = False)
|
||||
)
|
||||
|
||||
# user table gets 'preference_id' column added
|
||||
users = Table('users', engine,
|
||||
Column('user_id', INTEGER, primary_key = True),
|
||||
Column('user_name', VARCHAR(16), nullable = False),
|
||||
Column('email_address', VARCHAR(60), key='email'),
|
||||
Column('password', VARCHAR(20), nullable = False)
|
||||
Column('preference_id', INTEGER, foreign_key = ForeignKey(prefs.c.pref_id))
|
||||
)
|
||||
|
||||
# class definition for preferences
|
||||
class UserPrefs(object):
|
||||
pass
|
||||
|
||||
# obtain a Mapper.
|
||||
m = mapper(User, users, properties = dict(
|
||||
addresses = relation(Address, addresses, lazy=True, private=True),
|
||||
preferences = relation(UserPrefs, prefs, lazy=False, private=True),
|
||||
))
|
||||
|
||||
# select
|
||||
user = m.select(users.c.user_name == 'fred')[0]
|
||||
save_password = user.preferences.save_password
|
||||
|
||||
# modify
|
||||
user.preferences.stylename = 'bluesteel'
|
||||
|
||||
# commit
|
||||
objectstore.commit()
|
||||
|
||||
</&>
|
||||
</&>
|
||||
|
||||
<&|doclib.myt:item, name="manytomany", description="Many to Many" &>
|
||||
<&|formatting.myt:code&>
|
||||
# create articles table. note the usage of "key=<synonym>" to redefine the
|
||||
# names of properties that will be used on the object.
|
||||
articles = Table('articles', engine,
|
||||
Column('article_id', INT, primary_key = True),
|
||||
Column('article_headline', key='headline', VARCHAR(150)),
|
||||
Column('article_body', key='body', CLOB),
|
||||
)
|
||||
|
||||
keywords = Table('keywords', engine,
|
||||
Column('keyword_id', INT, primary_key = True),
|
||||
Column('name', VARCHAR(50))
|
||||
)
|
||||
|
||||
itemkeywords = Table('article_keywords', engine,
|
||||
Column('article_id', INT, foreign_key = ForeignKey(articles.c.article_id)),
|
||||
Column('keyword_id', INT, foreign_key = ForeignKey(keywords.c.keyword_id))
|
||||
)
|
||||
|
||||
# class definitions
|
||||
class Article:pass
|
||||
|
||||
class Keyword:
|
||||
def __init__(self, name = None):
|
||||
self.name = name
|
||||
|
||||
# create mapper. we will eager load keywords.
|
||||
m = mapper(Article, articles, properties = dict(
|
||||
keywords = relation(Keyword, keywords, itemkeywords, lazy=False)
|
||||
))
|
||||
|
||||
# select articles based on some keywords. the extra selection criterion
|
||||
# won't get in the way of the separate eager load of all the article's keywords
|
||||
articles = m.select(sql.and_(keywords.c.keyword_id==articles.c.article_id, keywords.c.keyword_name.in_('politics', 'entertainment')))
|
||||
|
||||
# modify
|
||||
del articles.keywords[articles.keywords.index('politics')]
|
||||
articles.keywords.append(Keyword('topstories'))
|
||||
articles.keywords.append(Keyword('government'))
|
||||
|
||||
# commit. individual INSERT/DELETE operations will take place only for the list
|
||||
# elements that changed.
|
||||
objectstore.commit()
|
||||
</&>
|
||||
|
||||
<p>Many to Many can also be done with an Association object, that adds additional information about how two items are related:</p>
|
||||
<&|formatting.myt:code&>
|
||||
# add "attached_by" column which will reference the user who attached this keyword
|
||||
itemkeywords = Table('article_keywords', engine,
|
||||
Column('article_id', INT, foreign_key = ForeignKey(articles.c.article_id)),
|
||||
Column('keyword_id', INT, foreign_key = ForeignKey(keywords.c.keyword_id)),
|
||||
Column('attached_by', INT, foreign_key = ForeignKey(users.c.user_id))
|
||||
)
|
||||
|
||||
# define an association class
|
||||
class KeywordAssociation:pass
|
||||
|
||||
# define the mapper. when we load an article, we always want to get the keywords via
|
||||
# eager loading. but the user who added each keyword, we usually dont need so specify
|
||||
# lazy loading for that.
|
||||
m = mapper(Article, articles, properties=dict(
|
||||
keywords = relation(KeywordAssociation, itemkeywords, lazy = False, properties=dict(
|
||||
keyword = relation(Keyword, keywords, lazy = False),
|
||||
user = relation(User, users, lazy = True)
|
||||
)
|
||||
))
|
||||
)
|
||||
# bonus step - well, we do want to load the users in one shot, so modify the mapper via an option.
|
||||
# this returns a new mapper with the option switched on.
|
||||
m2 = mapper.options(eagerload('user'))
|
||||
|
||||
# select by keyword again
|
||||
articles = m.select(sql.and_(keywords.c.keyword_id==articles.c.article_id, keywords.c.keyword_name == 'jacks_stories'))
|
||||
|
||||
# user is available
|
||||
for a in articles:
|
||||
for k in a.keywords:
|
||||
if k.keyword.name == 'jacks_stories':
|
||||
print k.user.user_name
|
||||
|
||||
</&>
|
||||
|
||||
</&>
|
||||
|
||||
</&>
|
||||
Reference in New Issue
Block a user