sqlobject-cvs Mailing List for SQLObject (Page 187)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(9) |
Apr
(74) |
May
(29) |
Jun
(16) |
Jul
(28) |
Aug
(10) |
Sep
(57) |
Oct
(9) |
Nov
(29) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(7) |
Feb
(14) |
Mar
(6) |
Apr
(3) |
May
(12) |
Jun
(34) |
Jul
(9) |
Aug
(29) |
Sep
(22) |
Oct
(2) |
Nov
(15) |
Dec
(52) |
2005 |
Jan
(47) |
Feb
(78) |
Mar
(14) |
Apr
(35) |
May
(33) |
Jun
(16) |
Jul
(26) |
Aug
(63) |
Sep
(40) |
Oct
(96) |
Nov
(96) |
Dec
(123) |
2006 |
Jan
(159) |
Feb
(144) |
Mar
(64) |
Apr
(31) |
May
(88) |
Jun
(48) |
Jul
(16) |
Aug
(64) |
Sep
(87) |
Oct
(92) |
Nov
(56) |
Dec
(76) |
2007 |
Jan
(94) |
Feb
(103) |
Mar
(126) |
Apr
(123) |
May
(85) |
Jun
(11) |
Jul
(130) |
Aug
(47) |
Sep
(65) |
Oct
(70) |
Nov
(12) |
Dec
(11) |
2008 |
Jan
(30) |
Feb
(55) |
Mar
(88) |
Apr
(20) |
May
(50) |
Jun
|
Jul
(38) |
Aug
(1) |
Sep
(9) |
Oct
(5) |
Nov
(6) |
Dec
(39) |
2009 |
Jan
(8) |
Feb
(16) |
Mar
(3) |
Apr
(33) |
May
(44) |
Jun
(1) |
Jul
(10) |
Aug
(33) |
Sep
(74) |
Oct
(22) |
Nov
|
Dec
(15) |
2010 |
Jan
(28) |
Feb
(22) |
Mar
(46) |
Apr
(29) |
May
(1) |
Jun
(1) |
Jul
(27) |
Aug
(8) |
Sep
(5) |
Oct
(33) |
Nov
(24) |
Dec
(41) |
2011 |
Jan
(4) |
Feb
(12) |
Mar
(35) |
Apr
(29) |
May
(19) |
Jun
(16) |
Jul
(32) |
Aug
(25) |
Sep
(5) |
Oct
(11) |
Nov
(21) |
Dec
(12) |
2012 |
Jan
(3) |
Feb
(4) |
Mar
(20) |
Apr
(4) |
May
(25) |
Jun
(13) |
Jul
|
Aug
|
Sep
(2) |
Oct
(25) |
Nov
(9) |
Dec
(1) |
2013 |
Jan
(6) |
Feb
(8) |
Mar
|
Apr
(10) |
May
(31) |
Jun
(7) |
Jul
(18) |
Aug
(33) |
Sep
(4) |
Oct
(16) |
Nov
|
Dec
(27) |
2014 |
Jan
(2) |
Feb
|
Mar
|
Apr
(11) |
May
(39) |
Jun
(8) |
Jul
(11) |
Aug
(4) |
Sep
|
Oct
(27) |
Nov
|
Dec
(71) |
2015 |
Jan
(17) |
Feb
(47) |
Mar
(33) |
Apr
|
May
|
Jun
(9) |
Jul
(7) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(8) |
2016 |
Jan
(4) |
Feb
(4) |
Mar
|
Apr
|
May
(12) |
Jun
(7) |
Jul
(9) |
Aug
(31) |
Sep
(8) |
Oct
(3) |
Nov
(15) |
Dec
(1) |
2017 |
Jan
(13) |
Feb
(7) |
Mar
(14) |
Apr
(8) |
May
(10) |
Jun
(4) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
(8) |
Nov
(4) |
Dec
(5) |
2018 |
Jan
(2) |
Feb
(8) |
Mar
|
Apr
(4) |
May
|
Jun
(6) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2019 |
Jan
(1) |
Feb
(16) |
Mar
(1) |
Apr
(3) |
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
(3) |
2020 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(1) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(2) |
Nov
|
Dec
(2) |
2021 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2022 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(6) |
Oct
(1) |
Nov
(1) |
Dec
(4) |
2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(3) |
Sep
(2) |
Oct
(2) |
Nov
(4) |
Dec
|
2024 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(9) |
2025 |
Jan
|
Feb
(4) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ian...@us...> - 2003-07-05 04:39:10
|
Update of /cvsroot/sqlobject/SOWeb/docs In directory sc8-pr-cvs1:/tmp/cvs-serv22271/docs Modified Files: News.html News.txt SQLObject.html SQLObject.txt build default.css Log Message: Update for 0.4 Index: News.html =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/News.html,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** News.html 8 Apr 2003 04:05:04 -0000 1.2 --- News.html 5 Jul 2003 04:39:07 -0000 1.3 *************** *** 14,33 **** <p class="topic-title"><a name="contents">Contents:</a></p> <ul class="simple"> ! <li><a class="reference" href="#sqlobject-0-3" id="id3" name="id3">SQLObject 0.3</a><ul> ! <li><a class="reference" href="#features" id="id4" name="id4">Features</a></li> ! <li><a class="reference" href="#bugs" id="id5" name="id5">Bugs</a></li> </ul> </li> ! <li><a class="reference" href="#sqlobject-0-2-1" id="id6" name="id6">SQLObject 0.2.1</a><ul> ! <li><a class="reference" href="#id1" id="id7" name="id7">Bugs</a></li> ! <li><a class="reference" href="#id2" id="id8" name="id8">Features</a></li> </ul> </li> </ul> </div> ! <a class="target" id="start" name="start"></a><div class="section" id="sqlobject-0-3"> ! <h1><a name="sqlobject-0-3">SQLObject 0.3</a></h1> <div class="section" id="features"> <h2><a name="features">Features</a></h2> <ul class="simple"> <li>Table creation (SQL schema generation) via new class method --- 14,170 ---- <p class="topic-title"><a name="contents">Contents:</a></p> <ul class="simple"> ! <li><a class="reference" href="#sqlobject-0-4" id="id5" name="id5">SQLObject 0.4</a><ul> ! <li><a class="reference" href="#features" id="id6" name="id6">Features</a><ul> ! <li><a class="reference" href="#col-and-join" id="id7" name="id7">Col and Join</a></li> </ul> </li> ! <li><a class="reference" href="#bugs" id="id8" name="id8">Bugs</a></li> ! <li><a class="reference" href="#internal" id="id9" name="id9">Internal</a></li> ! </ul> ! </li> ! <li><a class="reference" href="#sqlobject-0-3" id="id10" name="id10">SQLObject 0.3</a><ul> ! <li><a class="reference" href="#id1" id="id11" name="id11">Features</a></li> ! <li><a class="reference" href="#id2" id="id12" name="id12">Bugs</a></li> ! </ul> ! </li> ! <li><a class="reference" href="#sqlobject-0-2-1" id="id13" name="id13">SQLObject 0.2.1</a><ul> ! <li><a class="reference" href="#id3" id="id14" name="id14">Bugs</a></li> ! <li><a class="reference" href="#id4" id="id15" name="id15">Features</a></li> </ul> </li> </ul> </div> ! <a class="target" id="start" name="start"></a><div class="section" id="sqlobject-0-4"> ! <h1><a name="sqlobject-0-4">SQLObject 0.4</a></h1> <div class="section" id="features"> <h2><a name="features">Features</a></h2> + <ul> + <li><p class="first">You can specify columns in a new, preferred manner:</p> + <pre class="literal-block"> + class SomeObject(SQLObject): + someColumn = Col() + </pre> + <p>Equivalent to:</p> + <pre class="literal-block"> + class SomeObject(SQLObject): + _columns = [Col('someColumn')] + </pre> + <p>Ditto joins.</p> + </li> + <li><p class="first">Cache objects have a clear method, which empties all objects. + However, weak references to objects <em>are</em> maintained, so the + integrity of the cache can be ensured.</p> + </li> + <li><p class="first">SQLObject subclasses can be further subclassed, adding or removing + column definitions (as well as changing settings like connection, + style, etc). Each class still refers to a single concrete table in + the database -- the class hierarchy is not represented in the + database.</p> + </li> + <li><p class="first">Each SQLObject subclass can have an associated style, as given in + the <cite>_style</cite> attribute. This object is used to map between Python + and database names (e.g., the column name for a Python attribute). + Some samples are available in the <cite>Style</cite> module.</p> + </li> + <li><p class="first">Postgres support for <cite>_fromDatabase</cite> (reading a table definition from + the database, and creating a class from that).</p> + </li> + <li><p class="first">Postgres id columns more permissive, you don't have to create a + specially named sequence (or implicitly create that sequence through + <tt class="literal"><span class="pre">SERIAL</span></tt>). lastoid is used instead.</p> + </li> + <li><p class="first">MySQL uses <tt class="literal"><span class="pre">localhost</span></tt> as the default host, and the empty string + as the default password.</p> + </li> + <li><p class="first">Added functions for use with queries: <cite>ISNULL</cite>, <cite>ISNOTNULL</cite>. <tt class="literal"><span class="pre">==</span></tt> + and <tt class="literal"><span class="pre">!=</span></tt> can be used with None, and is translated into <cite>ISNULL</cite>, + <cite>ISNOTNULL</cite>.</p> + </li> + <li><p class="first">Classes can be part of a specific registry. Since classes are + referred to by name in several places, the names have to be unique. + This can be problematic, so you can add a class variable <cite>_registry</cite>, + the value of which should be a string. Classes references are + assumed to be inside that registry, and class names need only be + unique among classes in that registry.</p> + </li> + <li><p class="first"><tt class="literal"><span class="pre">SomeClass.select()</span></tt> selects all, instead of using + <tt class="literal"><span class="pre">SomeClass.select('all')</span></tt>. You can also use None instead of + <tt class="literal"><span class="pre">'all'</span></tt>.</p> + </li> + <li><p class="first">Trying to fetch non-existent objects raises <cite>SQLObjectNotFound</cite>, + which is a subclass of the builtin exception <cite>LookupError</cite>. + This may not be raised if <cite>_cacheValues</cite> is False and you use + the ID to fetch an object (but alternateID fetches will raise + the exception in either case).</p> + </li> + <li><p class="first">Can order by descending order, with the <cite>reversed</cite> option to + the <cite>select</cite> method, or by prefixing the column with a <tt class="literal"><span class="pre">"-"</span></tt>.</p> + </li> + <li><p class="first">Ordering with joins works better -- you can order with multiple + columns, as well as descending ordering.</p> + </li> + </ul> + <div class="section" id="col-and-join"> + <h3><a name="col-and-join">Col and Join</a></h3> + <ul class="simple"> + <li><cite>Join</cite> constructors have an argument <cite>orderBy</cite>, which is the name + of a Python attribute to sort results by. If not given, the + appropriate class's <cite>_defaultOrder</cite> will be used. None implies + no sorting (and <tt class="literal"><span class="pre">orderBy=None</span></tt> will override <cite>_defaultOrder</cite>).</li> + <li><cite>ForeignKey</cite> class (subclass of <cite>Col</cite>), for somewhat easier/clearer + declaration of foreign keys.</li> + <li><cite>Col</cite> (and subclasses) can take a <cite>sqlType</cite> argument, which is used + in table definitions. E.g., <tt class="literal"><span class="pre">Col(sqlType="BOOLEAN")</span></tt> can be used + to create a <tt class="literal"><span class="pre">BOOLEAN</span></tt> column, even though no <cite>BooleanCol</cite> exists.</li> + <li><cite>alternateID</cite> (a specifier for columns) implies <tt class="literal"><span class="pre">NOT</span> <span class="pre">NULL</span></tt>. Also + implies <tt class="literal"><span class="pre">UNIQUE</span></tt>.</li> + <li><cite>unique</cite> (a specifier for columns) added.</li> + <li><cite>DecimalCol</cite> and <cite>CurrencyCol</cite> added.</li> + <li><cite>EnumCol</cite> uses constraints on Postgres (if you use <cite>createTable</cite>).</li> + </ul> + </div> + </div> + <div class="section" id="bugs"> + <h2><a name="bugs">Bugs</a></h2> + <ul class="simple"> + <li><cite>DateTimeCol</cite> uses <tt class="literal"><span class="pre">TIMESTAMP</span></tt> for Postgres. Note that the + Python type name is used for column names, not necessarily the + SQL standard name.</li> + <li>Foreign key column names are slightly more permissive. They still + need to end in <tt class="literal"><span class="pre">id</span></tt>, but it's case insensitive.</li> + <li>_defaultOrder should be the python attribute's name, not the database + name.</li> + <li>SomeClass.q.colName uses proper Python attributes for colName, and + proper database names when executed in the database.</li> + <li>SQLite select results back to being proper iterator.</li> + <li>SomeClass.q.colName now does proper translation to database names, + using dbName, etc., instead of being entirely algorithm-driven.</li> + <li>Raise <cite>TypeError</cite> if you pass an unknown argument to the <cite>new</cite> + method.</li> + <li>You can override the _get_* or _set_* version of a property without + overriding the other.</li> + <li>Python 2.3 compatible.</li> + <li>Trying to use <tt class="literal"><span class="pre">Col('id')</span></tt> or <tt class="literal"><span class="pre">id</span> <span class="pre">=</span> <span class="pre">Col()</span></tt> will raise an + exception, instead of just acting funky.</li> + <li><tt class="literal"><span class="pre">ForeignKey</span></tt> columns return None if the associated column is + NULL in the database (used to just act weird).</li> + <li>Instantiating an object with an id of None will give an error, + instead of just acting weird.</li> + </ul> + </div> + <div class="section" id="internal"> + <h2><a name="internal">Internal</a></h2> + <ul class="simple"> + <li><cite>Col</cite> class separated into <cite>Col</cite> and <cite>SOCol</cite> (and same for all other + <cite>*Col</cite> classes). <cite>Col</cite> defines a column, <cite>SOCol</cite> is that definition + bound to a particular SQLObject class.</li> + <li>Instance variable <tt class="literal"><span class="pre">_SO_columns</span></tt> holds the <cite>SOCol</cite> instances.</li> + </ul> + </div> + </div> + <div class="section" id="sqlobject-0-3"> + <h1><a name="sqlobject-0-3">SQLObject 0.3</a></h1> + <div class="section" id="id1"> + <h2><a name="id1">Features</a></h2> <ul class="simple"> <li>Table creation (SQL schema generation) via new class method *************** *** 56,61 **** </ul> </div> ! <div class="section" id="bugs"> ! <h2><a name="bugs">Bugs</a></h2> <ul class="simple"> <li>LIMIT/OFFSET (select result slicing) works in Postgres and SQLite.</li> --- 193,198 ---- </ul> </div> ! <div class="section" id="id2"> ! <h2><a name="id2">Bugs</a></h2> <ul class="simple"> <li>LIMIT/OFFSET (select result slicing) works in Postgres and SQLite.</li> *************** *** 68,79 **** <div class="section" id="sqlobject-0-2-1"> <h1><a name="sqlobject-0-2-1">SQLObject 0.2.1</a></h1> ! <div class="section" id="id1"> ! <h2><a name="id1">Bugs</a></h2> <ul class="simple"> <li>Fixed caching of new objects</li> </ul> </div> ! <div class="section" id="id2"> ! <h2><a name="id2">Features</a></h2> <ul class="simple"> <li><a class="reference" href="http://sqlite.org/">SQLite</a> support</li> --- 205,216 ---- <div class="section" id="sqlobject-0-2-1"> <h1><a name="sqlobject-0-2-1">SQLObject 0.2.1</a></h1> ! <div class="section" id="id3"> ! <h2><a name="id3">Bugs</a></h2> <ul class="simple"> <li>Fixed caching of new objects</li> </ul> </div> ! <div class="section" id="id4"> ! <h2><a name="id4">Features</a></h2> <ul class="simple"> <li><a class="reference" href="http://sqlite.org/">SQLite</a> support</li> Index: News.txt =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/News.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** News.txt 8 Apr 2003 04:05:04 -0000 1.2 --- News.txt 5 Jul 2003 04:39:07 -0000 1.3 *************** *** 8,11 **** --- 8,152 ---- .. _start: + SQLObject 0.4 + ============= + + Features + -------- + + * You can specify columns in a new, preferred manner:: + + class SomeObject(SQLObject): + someColumn = Col() + + Equivalent to:: + + class SomeObject(SQLObject): + _columns = [Col('someColumn')] + + Ditto joins. + + * Cache objects have a clear method, which empties all objects. + However, weak references to objects *are* maintained, so the + integrity of the cache can be ensured. + + * SQLObject subclasses can be further subclassed, adding or removing + column definitions (as well as changing settings like connection, + style, etc). Each class still refers to a single concrete table in + the database -- the class hierarchy is not represented in the + database. + + * Each SQLObject subclass can have an associated style, as given in + the `_style` attribute. This object is used to map between Python + and database names (e.g., the column name for a Python attribute). + Some samples are available in the `Style` module. + + * Postgres support for `_fromDatabase` (reading a table definition from + the database, and creating a class from that). + + * Postgres id columns more permissive, you don't have to create a + specially named sequence (or implicitly create that sequence through + ``SERIAL``). lastoid is used instead. + + * MySQL uses ``localhost`` as the default host, and the empty string + as the default password. + + * Added functions for use with queries: `ISNULL`, `ISNOTNULL`. ``==`` + and ``!=`` can be used with None, and is translated into `ISNULL`, + `ISNOTNULL`. + + * Classes can be part of a specific registry. Since classes are + referred to by name in several places, the names have to be unique. + This can be problematic, so you can add a class variable `_registry`, + the value of which should be a string. Classes references are + assumed to be inside that registry, and class names need only be + unique among classes in that registry. + + * ``SomeClass.select()`` selects all, instead of using + ``SomeClass.select('all')``. You can also use None instead of + ``'all'``. + + * Trying to fetch non-existent objects raises `SQLObjectNotFound`, + which is a subclass of the builtin exception `LookupError`. + This may not be raised if `_cacheValues` is False and you use + the ID to fetch an object (but alternateID fetches will raise + the exception in either case). + + * Can order by descending order, with the `reversed` option to + the `select` method, or by prefixing the column with a ``"-"``. + + * Ordering with joins works better -- you can order with multiple + columns, as well as descending ordering. + + Col and Join + ~~~~~~~~~~~~ + + * `Join` constructors have an argument `orderBy`, which is the name + of a Python attribute to sort results by. If not given, the + appropriate class's `_defaultOrder` will be used. None implies + no sorting (and ``orderBy=None`` will override `_defaultOrder`). + + * `ForeignKey` class (subclass of `Col`), for somewhat easier/clearer + declaration of foreign keys. + + * `Col` (and subclasses) can take a `sqlType` argument, which is used + in table definitions. E.g., ``Col(sqlType="BOOLEAN")`` can be used + to create a ``BOOLEAN`` column, even though no `BooleanCol` exists. + + * `alternateID` (a specifier for columns) implies ``NOT NULL``. Also + implies ``UNIQUE``. + + * `unique` (a specifier for columns) added. + + * `DecimalCol` and `CurrencyCol` added. + + * `EnumCol` uses constraints on Postgres (if you use `createTable`). + + Bugs + ---- + + * `DateTimeCol` uses ``TIMESTAMP`` for Postgres. Note that the + Python type name is used for column names, not necessarily the + SQL standard name. + + * Foreign key column names are slightly more permissive. They still + need to end in ``id``, but it's case insensitive. + + * _defaultOrder should be the python attribute's name, not the database + name. + + * SomeClass.q.colName uses proper Python attributes for colName, and + proper database names when executed in the database. + + * SQLite select results back to being proper iterator. + + * SomeClass.q.colName now does proper translation to database names, + using dbName, etc., instead of being entirely algorithm-driven. + + * Raise `TypeError` if you pass an unknown argument to the `new` + method. + + * You can override the _get_* or _set_* version of a property without + overriding the other. + + * Python 2.3 compatible. + + * Trying to use ``Col('id')`` or ``id = Col()`` will raise an + exception, instead of just acting funky. + + * ``ForeignKey`` columns return None if the associated column is + NULL in the database (used to just act weird). + + * Instantiating an object with an id of None will give an error, + instead of just acting weird. + + Internal + -------- + + * `Col` class separated into `Col` and `SOCol` (and same for all other + `*Col` classes). `Col` defines a column, `SOCol` is that definition + bound to a particular SQLObject class. + + * Instance variable ``_SO_columns`` holds the `SOCol` instances. + SQLObject 0.3 ============= Index: SQLObject.html =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/SQLObject.html,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** SQLObject.html 8 Apr 2003 04:05:04 -0000 1.3 --- SQLObject.html 5 Jul 2003 04:39:07 -0000 1.4 *************** *** 5,66 **** <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="generator" content="Docutils 0.2.8: http://docutils.sourceforge.net/" /> ! <title>SQLObject 0.3</title> <link rel="stylesheet" href="default.css" type="text/css" /> </head> <body> ! <div class="document" id="sqlobject-0-3"> ! <h1 class="title">SQLObject 0.3</h1> <div class="contents topic" id="contents"> <p class="topic-title"><a name="contents">Contents:</a></p> [...1877 lines suppressed...] ! * <cite>CurrencyCol</cite></p> ! <p>From <cite>SQLObject.Join</cite>: ! * <cite>MultipleJoin</cite> ! * <cite>RelatedJoin</cite></p> ! <p>From <cite>SQLObject.Style</cite>: ! * <cite>Style</cite> ! * <cite>MixedCaseUnderscoreStyle</cite> ! * <cite>DefaultStyle</cite> ! * <cite>MixedCaseStyle</cite></p> ! <p>From <cite>SQLObject.SQLBuilder</cite>:</p> <ul class="simple"> <li><cite>AND</cite></li> *************** *** 882,885 **** --- 1130,1134 ---- <li><cite>IN</cite></li> <li><cite>LIKE</cite></li> + <li><cite>DESC</cite></li> <li><cite>CONTAINSSTRING</cite></li> <li><cite>const</cite></li> Index: SQLObject.txt =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/SQLObject.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** SQLObject.txt 8 Apr 2003 04:05:04 -0000 1.3 --- SQLObject.txt 5 Jul 2003 04:39:07 -0000 1.4 *************** *** 1,4 **** ``````````````` ! SQLObject 0.3 ``````````````` --- 1,4 ---- ``````````````` ! SQLObject 0.4 ``````````````` *************** [...1617 lines suppressed...] ! * `MultipleJoin` ! * `RelatedJoin` ! ! From `SQLObject.Style`: ! * `Style` ! * `MixedCaseUnderscoreStyle` ! * `DefaultStyle` ! * `MixedCaseStyle` ! ! From `SQLObject.SQLBuilder`: * `AND` *************** *** 907,910 **** --- 1017,1021 ---- * `IN` * `LIKE` + * `DESC` * `CONTAINSSTRING` * `const` Index: build =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/build,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** build 13 Mar 2003 20:45:39 -0000 1.3 --- build 5 Jul 2003 04:39:07 -0000 1.4 *************** *** 4,7 **** --- 4,8 ---- cp $SOURCEDIR/*.txt $SOURCEDIR/*.css . + cp $SOURCEDIR/../examples/snippets/*.html ../examples/snippets/ cd .. buildhtml.py Index: default.css =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/docs/default.css,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** default.css 8 Apr 2003 04:05:04 -0000 1.3 --- default.css 5 Jul 2003 04:39:07 -0000 1.4 *************** *** 108,121 **** font-family: Helvetica, Arial, sans-serif; border: thin solid black; - background-color: #cccccc; -moz-border-radius: 8px; padding: 4px; } h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: medium solid black; -moz-border-radius: 20px; } --- 108,137 ---- font-family: Helvetica, Arial, sans-serif; border: thin solid black; -moz-border-radius: 8px; padding: 4px; } + h1 { + background-color: #444499; + border: medium solid black; + color: #ffffff; + } + + h2 { + background-color: #666666; + color: #ffffff; + border: medium solid black; + } + + h3, h4, h5, h6 { + background-color: #cccccc; + color: #000000; + } + h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: thick solid black; -moz-border-radius: 20px; } *************** *** 236,237 **** --- 252,274 ---- ul.auto-toc { list-style-type: none } + + // Highlighting: + + .function {color: #000077; font-weight: bold} + .keyword {color: #004444;} + .comment {color: #770000; font-style: italic} + .normal {color: #000000;} + .string {color: #006600;} + .symbol {color: #000000;} + + .htmltag {color: #000077;} + .htmlsymbol {color: #000000;} + .htmlnormal {color: #000000;} + .htmlcomment {color: #770000; font-style: italic} + .htmlstring {color: #006600;} + .htmlattr {color: #000000;} + + .stmlfunction {color: #000077; font-weight: bold} + .stmlattr {color: #000000;} + .stmlstring {color: #006600;} + .stmlexpr {color: #004444;} \ No newline at end of file |
From: <ian...@us...> - 2003-07-05 04:39:10
|
Update of /cvsroot/sqlobject/SOWeb In directory sc8-pr-cvs1:/tmp/cvs-serv22271 Modified Files: default.css index.html index.txt Log Message: Update for 0.4 Index: default.css =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/default.css,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** default.css 27 Feb 2003 09:06:11 -0000 1.1 --- default.css 5 Jul 2003 04:39:06 -0000 1.2 *************** *** 108,121 **** font-family: Helvetica, Arial, sans-serif; border: thin solid black; - background-color: #cccccc; -moz-border-radius: 8px; padding: 4px; } h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: medium solid black; -moz-border-radius: 20px; } --- 108,137 ---- font-family: Helvetica, Arial, sans-serif; border: thin solid black; -moz-border-radius: 8px; padding: 4px; } + h1 { + background-color: #444499; + border: medium solid black; + color: #ffffff; + } + + h2 { + background-color: #666666; + color: #ffffff; + border: medium solid black; + } + + h3, h4, h5, h6 { + background-color: #cccccc; + color: #000000; + } + h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: thick solid black; -moz-border-radius: 20px; } *************** *** 236,237 **** --- 252,274 ---- ul.auto-toc { list-style-type: none } + + // Highlighting: + + .function {color: #000077; font-weight: bold} + .keyword {color: #004444;} + .comment {color: #770000; font-style: italic} + .normal {color: #000000;} + .string {color: #006600;} + .symbol {color: #000000;} + + .htmltag {color: #000077;} + .htmlsymbol {color: #000000;} + .htmlnormal {color: #000000;} + .htmlcomment {color: #770000; font-style: italic} + .htmlstring {color: #006600;} + .htmlattr {color: #000000;} + + .stmlfunction {color: #000077; font-weight: bold} + .stmlattr {color: #000000;} + .stmlstring {color: #006600;} + .stmlexpr {color: #004444;} \ No newline at end of file Index: index.html =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/index.html,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** index.html 8 Apr 2003 04:05:04 -0000 1.4 --- index.html 5 Jul 2003 04:39:06 -0000 1.5 *************** *** 51,59 **** class Person(SQLObject): ! _columns = [Col('firstName'), ! Col('middleInitial', default=None), ! Col('lastName')] </pre> ! <p>Here's the (MySQL) CREATE statement for that class:</p> <pre class="literal-block"> CREATE TABLE person ( --- 51,59 ---- class Person(SQLObject): ! firstName = StringCol(length=100) ! middleInitial = StringCol(length=1, default=None) ! lastName = StringCol(length=100) </pre> ! <p>Here's the (MySQL) <tt class="literal"><span class="pre">CREATE</span></tt> statement for that class:</p> <pre class="literal-block"> CREATE TABLE person ( *************** *** 61,69 **** first_name VARCHAR(100) NOT NULL, middle_initial CHAR(1), ! last_name VARCHAR(150) NOT NULL ); </pre> ! <p>Postgres works too with a slightly different CREATE statement and ! connection object, but it's otherwise identical.</p> <p>Here's how you'd use the object:</p> <pre class="literal-block"> --- 61,71 ---- first_name VARCHAR(100) NOT NULL, middle_initial CHAR(1), ! last_name VARCHAR(100) NOT NULL ); </pre> ! <p>SQLObject supports most database schemas that you already have, and ! can also issue the <tt class="literal"><span class="pre">CREATE</span></tt> statement for you. Postgres and SQLite are ! also supported, and SQLObject provides an abstraction layer that helps ! make your application much more portable between these databases.</p> <p>Here's how you'd use the object:</p> <pre class="literal-block"> *************** *** 85,90 **** <div class="section" id="community"> <h1><a class="toc-backref" href="#id10" name="community">Community</a></h1> ! <p>Well, it's just starting, but I'd recommend <a class="reference" href="http://lists.sourceforge.net/lists/listinfo/sqlobject-discuss">joining the mailing ! list</a> or visiting the <a class="reference" href="http://sourceforge.net/mailarchive/forum.php?forum=sqlobject-discuss">sqlobject-discuss archives</a>.</p> <p>If you are tracking changes, keeping up with CVS is helpful. To access CVS:</p> --- 87,91 ---- <div class="section" id="community"> <h1><a class="toc-backref" href="#id10" name="community">Community</a></h1> ! <p><a class="reference" href="http://lists.sourceforge.net/lists/listinfo/sqlobject-discuss">Join the mailing list</a> or visit the <a class="reference" href="http://sourceforge.net/mailarchive/forum.php?forum=sqlobject-discuss">sqlobject-discuss archives</a>.</p> <p>If you are tracking changes, keeping up with CVS is helpful. To access CVS:</p> *************** *** 102,116 **** patches. For simple bug fixes it's just as easy for me to get a line number and the fixed line -- submitting patches is more overhead than ! it's worth for small changes.</p> </div> <div class="section" id="download"> <h1><a class="toc-backref" href="#id12" name="download">Download</a></h1> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3.tar.gz?download">SQLObject-0.3.tar.gz</a></p> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3-1.noarch.rpm?download">SQLObject-0.3-1.noarch.rpm</a></p> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3.win32.exe?download">SQLObject-0.3.win32.exe</a></p> </div> <div class="section" id="documentation"> <h1><a class="toc-backref" href="#id13" name="documentation">Documentation</a></h1> ! <p><a class="reference" href="docs/News.html">New in 0.3</a></p> <p><a class="reference" href="docs/SQLObject.html">SQLObject documentation</a></p> <p><a class="reference" href="docs/SQLBuilder.html">SQLBuilder documentation</a></p> --- 103,118 ---- patches. For simple bug fixes it's just as easy for me to get a line number and the fixed line -- submitting patches is more overhead than ! it's worth for small changes. But again, bug reports should go to the ! bug tracker, so that I don't lose anything.</p> </div> <div class="section" id="download"> <h1><a class="toc-backref" href="#id12" name="download">Download</a></h1> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4.tar.gz?download">SQLObject-0.4.tar.gz</a></p> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4-1.noarch.rpm?download">SQLObject-0.4-1.noarch.rpm</a></p> ! <p><a class="reference" href="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4.win32.exe?download">SQLObject-0.4.win32.exe</a></p> </div> <div class="section" id="documentation"> <h1><a class="toc-backref" href="#id13" name="documentation">Documentation</a></h1> ! <p><a class="reference" href="docs/News.html">New in 0.4</a></p> <p><a class="reference" href="docs/SQLObject.html">SQLObject documentation</a></p> <p><a class="reference" href="docs/SQLBuilder.html">SQLBuilder documentation</a></p> Index: index.txt =================================================================== RCS file: /cvsroot/sqlobject/SOWeb/index.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** index.txt 8 Apr 2003 04:05:04 -0000 1.3 --- index.txt 5 Jul 2003 04:39:06 -0000 1.4 *************** *** 38,46 **** class Person(SQLObject): ! _columns = [Col('firstName'), ! Col('middleInitial', default=None), ! Col('lastName')] ! Here's the (MySQL) CREATE statement for that class:: CREATE TABLE person ( --- 38,46 ---- class Person(SQLObject): ! firstName = StringCol(length=100) ! middleInitial = StringCol(length=1, default=None) ! lastName = StringCol(length=100) ! Here's the (MySQL) ``CREATE`` statement for that class:: CREATE TABLE person ( *************** *** 48,56 **** first_name VARCHAR(100) NOT NULL, middle_initial CHAR(1), ! last_name VARCHAR(150) NOT NULL ); ! Postgres works too with a slightly different CREATE statement and ! connection object, but it's otherwise identical. Here's how you'd use the object:: --- 48,58 ---- first_name VARCHAR(100) NOT NULL, middle_initial CHAR(1), ! last_name VARCHAR(100) NOT NULL ); ! SQLObject supports most database schemas that you already have, and ! can also issue the ``CREATE`` statement for you. Postgres and SQLite are ! also supported, and SQLObject provides an abstraction layer that helps ! make your application much more portable between these databases. Here's how you'd use the object:: *************** *** 73,78 **** ========= ! Well, it's just starting, but I'd recommend `joining the mailing ! list`__ or visiting the `sqlobject-discuss archives`_. .. __: http://lists.sourceforge.net/lists/listinfo/sqlobject-discuss --- 75,79 ---- ========= ! `Join the mailing list`__ or visit the `sqlobject-discuss archives`_. .. __: http://lists.sourceforge.net/lists/listinfo/sqlobject-discuss *************** *** 100,104 **** patches. For simple bug fixes it's just as easy for me to get a line number and the fixed line -- submitting patches is more overhead than ! it's worth for small changes. .. _SourceForge bug tracker: http://sourceforge.net/tracker/?atid=540672&group_id=74338&func=browse --- 101,106 ---- patches. For simple bug fixes it's just as easy for me to get a line number and the fixed line -- submitting patches is more overhead than ! it's worth for small changes. But again, bug reports should go to the ! bug tracker, so that I don't lose anything. .. _SourceForge bug tracker: http://sourceforge.net/tracker/?atid=540672&group_id=74338&func=browse *************** *** 107,126 **** ======== ! SQLObject-0.3.tar.gz__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3.tar.gz?download ! SQLObject-0.3-1.noarch.rpm__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3-1.noarch.rpm?download ! SQLObject-0.3.win32.exe__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3.win32.exe?download Documentation ============= ! `New in 0.3`__ __ docs/News.html --- 109,128 ---- ======== ! SQLObject-0.4.tar.gz__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4.tar.gz?download ! SQLObject-0.4-1.noarch.rpm__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4-1.noarch.rpm?download ! SQLObject-0.4.win32.exe__ ! __ http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4.win32.exe?download Documentation ============= ! `New in 0.4`__ __ docs/News.html |
From: <ian...@us...> - 2003-07-05 03:55:25
|
Update of /cvsroot/sqlobject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv18828 Modified Files: setup.py Log Message: Version 0.4 Index: setup.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/setup.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** setup.py 1 Jul 2003 00:13:04 -0000 1.10 --- setup.py 5 Jul 2003 03:55:22 -0000 1.11 *************** *** 11,15 **** setup(name="SQLObject", ! version="0.4rc1", description="Object-Relational Manager, aka database wrapper", long_description="""\ --- 11,15 ---- setup(name="SQLObject", ! version="0.4", description="Object-Relational Manager, aka database wrapper", long_description="""\ |
From: <ian...@us...> - 2003-07-05 03:49:55
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv18381 Modified Files: SQLBuilder.py Log Message: Accept Unicode SQLBuilder literals Index: SQLBuilder.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLBuilder.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** SQLBuilder.py 26 Jun 2003 08:33:56 -0000 1.6 --- SQLBuilder.py 5 Jul 2003 03:49:52 -0000 1.7 *************** *** 109,113 **** if isinstance(obj, SQLExpression): return obj.sqlRepr() ! elif t is type(""): for orig, repl in sqlStringReplace: obj = obj.replace(orig, repl) --- 109,113 ---- if isinstance(obj, SQLExpression): return obj.sqlRepr() ! elif t is type("") or t is type(u""): for orig, repl in sqlStringReplace: obj = obj.replace(orig, repl) |
From: <ian...@us...> - 2003-07-01 00:13:11
|
Update of /cvsroot/sqlobject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv6733 Modified Files: setup.py README.txt Log Message: 0.3->0.4 version changes Index: setup.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/setup.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** setup.py 28 Jun 2003 22:19:16 -0000 1.9 --- setup.py 1 Jul 2003 00:13:04 -0000 1.10 *************** *** 11,15 **** setup(name="SQLObject", ! version="0.3", description="Object-Relational Manager, aka database wrapper", long_description="""\ --- 11,15 ---- setup(name="SQLObject", ! version="0.4rc1", description="Object-Relational Manager, aka database wrapper", long_description="""\ *************** *** 32,36 **** license="LGPL", packages=["SQLObject"], ! download_url="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.3.tar.gz?download") # Send announce to: --- 32,36 ---- license="LGPL", packages=["SQLObject"], ! download_url="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.4.tar.gz?download") # Send announce to: Index: README.txt =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/README.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** README.txt 8 Apr 2003 03:08:00 -0000 1.3 --- README.txt 1 Jul 2003 00:13:04 -0000 1.4 *************** *** 1,4 **** ============= ! SQLObject 0.3 ============= --- 1,4 ---- ============= ! SQLObject 0.4 ============= |
From: <ian...@us...> - 2003-06-30 22:43:09
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv27689/SQLObject Modified Files: DBConnection.py Log Message: Fix a couple SQLite bugs (from Matt Goodall <ma...@po...>) Index: DBConnection.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/DBConnection.py,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -d -r1.36 -r1.37 *** DBConnection.py 28 Jun 2003 22:20:20 -0000 1.36 --- DBConnection.py 30 Jun 2003 22:43:06 -0000 1.37 *************** *** 149,153 **** (", ".join(select.tables), self.whereClauseForSelect(select, limit=0, order=0)) ! val = self.queryOne(q)[0] if self.debug: print "COUNT results:", val --- 149,153 ---- (", ".join(select.tables), self.whereClauseForSelect(select, limit=0, order=0)) ! val = int(self.queryOne(q)[0]) if self.debug: print "COUNT results:", val *************** *** 586,590 **** return "%s LIMIT %i" % (query, end) if not end: ! return "%s OFFSET %i" % (query, start) return "%s LIMIT %i OFFSET %i" % (query, end-start, start) --- 586,590 ---- return "%s LIMIT %i" % (query, end) if not end: ! return "%s LIMIT 0 OFFSET %i" % (query, start) return "%s LIMIT %i OFFSET %i" % (query, end-start, start) |
From: <ian...@us...> - 2003-06-28 22:36:23
|
Update of /cvsroot/sqlobject/SQLObject/docs In directory sc8-pr-cvs1:/tmp/cvs-serv3421 Modified Files: SQLObject.txt Log Message: Added internal references Index: SQLObject.txt =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/docs/SQLObject.txt,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** SQLObject.txt 28 Jun 2003 22:19:08 -0000 1.13 --- SQLObject.txt 28 Jun 2003 22:36:20 -0000 1.14 *************** *** 149,154 **** We'll develop a simple addressbook-like database. We could create the ! tables ourselves (which I'll show later @@: link), but for now we'll ! let SQLObject do that work. First, the class: .. raw:: html --- 149,154 ---- We'll develop a simple addressbook-like database. We could create the ! tables ourselves, and just have SQLObject access those tables, but for ! now we'll let SQLObject do that work. First, the class: .. raw:: html *************** *** 169,174 **** different (especially the ``id`` column). You'll notice the names were changed from mixedCase to underscore_separated -- this is done by ! the style object (@@: link). There are a variety of ways to handle ! other names that are not as SQLObject expects (@@: link). The tables don't yet exist. We'll let SQLObject create them: --- 169,176 ---- different (especially the ``id`` column). You'll notice the names were changed from mixedCase to underscore_separated -- this is done by ! the `style object`_. There are a variety of ways to handle ! other names that are not as SQLObject expects (see `Irregular Naming`_). ! ! .. _`style object`: `Changing the Naming Style`_ The tables don't yet exist. We'll let SQLObject create them: *************** *** 178,183 **** We can change the type of the various columns by using something other ! than `StringCol`, or using different arguments. More about this @@: ! link. If you don't want to do table creation (you already have tables, or --- 180,185 ---- We can change the type of the various columns by using something other ! than `StringCol`, or using different arguments. More about this in ! `Subclasses of Col`_. If you don't want to do table creation (you already have tables, or *************** *** 190,195 **** definition, it is implied. For MySQL databases it should be defined as ``INT PRIMARY KEY AUTO_INCREMENT``, in Postgres ``SERIAL PRIMARY ! KEY``, and in SQLite as ``INTEGER PRIMARY KEY``. You can override the ! name (@@: link), but some integer primary key must exist. Using the Class --- 192,199 ---- definition, it is implied. For MySQL databases it should be defined as ``INT PRIMARY KEY AUTO_INCREMENT``, in Postgres ``SERIAL PRIMARY ! KEY``, and in SQLite as ``INTEGER PRIMARY KEY``. You can `override the ! name`__, but some integer primary key must exist. ! ! __ idName_ Using the Class *************** *** 227,231 **** multiple threads accessing the same data (though of course across processes there can be no sharing of an instance). This changes if ! you're using transactions (@@: link). To get an idea of what's happening behind the surface, I'll give the --- 231,235 ---- multiple threads accessing the same data (though of course across processes there can be no sharing of an instance). This changes if ! you're using transactions_. To get an idea of what's happening behind the surface, I'll give the *************** *** 352,360 **** you're selecting is always assumed to be included, of course. You can use the keyword arguments `orderBy` and `groupBy` to create ``ORDER BY`` and ``GROUP BY`` in the select statements: `orderBy` takes a string, which should be the *database* name of the column, or a column in the form ``Person.q.firstName``; `groupBy` is similar. ! Both accept lists or tuples of arguments. You can use the special class variable `_defaultOrder` to give a --- 356,367 ---- you're selecting is always assumed to be included, of course. + .. _orderBy: + You can use the keyword arguments `orderBy` and `groupBy` to create ``ORDER BY`` and ``GROUP BY`` in the select statements: `orderBy` takes a string, which should be the *database* name of the column, or a column in the form ``Person.q.firstName``; `groupBy` is similar. ! Both accept lists or tuples of arguments. You can use ``"-colname"`` ! to specify descending order, or call ``MyClass.select().reversed()``. You can use the special class variable `_defaultOrder` to give a *************** *** 542,546 **** `ForeignKey`: A key to another table/class. Use like ``user = ! ForeignKey('User')``. (@@: test) `EnumCol`: One of several string values -- give the possible strings as a --- 549,553 ---- `ForeignKey`: A key to another table/class. Use like ``user = ! ForeignKey('User')``. `EnumCol`: One of several string values -- give the possible strings as a *************** *** 569,578 **** --- 576,588 ---- class). You can also pass a connection object in at instance creation time, as described in transactions_. + `_table`: The database name of the table for this class. If you don't give a name, then the standard ``MixedCase`` to ``mixed_case`` translation is performed. + `_joins`: A list of `Join` objects. This is covered below. + `_cacheValues`: If set to ``False`` then values for attributes from the database *************** *** 582,591 **** then this is probably the way to do so. You should also use it with transactions_ (it is not implied). `_idName`: The name of the primary key column (default ``id``). `_style`: A style object -- this object allows you to use other algorithms for translating between Python attribute and class names, and the ! database's column and table names. (@@: link) Relationships Between Classes/Tables --- 592,608 ---- then this is probably the way to do so. You should also use it with transactions_ (it is not implied). + + .. _idName: + `_idName`: The name of the primary key column (default ``id``). + `_style`: A style object -- this object allows you to use other algorithms for translating between Python attribute and class names, and the ! database's column and table names. See `Changing the Naming ! Style`_ for more. ! ! .. Relationships_: Relationships Between Classes/Tables *************** *** 611,619 **** points to this table, then you'd use ``joinColumn="ProductNo"``. `orderBy`: ! Like the `orderBy` argument to `select()` (@@: link), you can specify the order that the joined objects should be returned in. `_defaultOrder` will be used if not specified; ``None`` forces unordered results. `joinMethodName`: ! When adding joins dynamically (using the class method `addJoin` @@: link), you can give the name of the accessor for the join. It can also be created automatically, and is normally implied (i.e., ``addresses = --- 628,636 ---- points to this table, then you'd use ``joinColumn="ProductNo"``. `orderBy`: ! Like the `orderBy`_ argument to `select()`, you can specify the order that the joined objects should be returned in. `_defaultOrder` will be used if not specified; ``None`` forces unordered results. `joinMethodName`: ! When adding joins dynamically (using the class method `addJoin`_), you can give the name of the accessor for the join. It can also be created automatically, and is normally implied (i.e., ``addresses = *************** *** 634,641 **** The name of the intermediate table which references both classes. `addRemoveName`: ! In the user/role example (@@: link), the methods `addRole(role)` and `removeRole(role)` are created. The ``Role`` portion of these method names can be changed by giving a string value here. An example schema that requires the use of `joinColumn`, `otherColumn`, and `intermediateTable`:: --- 651,660 ---- The name of the intermediate table which references both classes. `addRemoveName`: ! In the `user/role example`__, the methods `addRole(role)` and `removeRole(role)` are created. The ``Role`` portion of these method names can be changed by giving a string value here. + __ `Many-to-Many Relationships`_ + An example schema that requires the use of `joinColumn`, `otherColumn`, and `intermediateTable`:: *************** *** 726,730 **** This is a reference to another table. You typically need to only give the name of the foreign class that is referenced. ! `ForeignKey` implies an ``INT`` column. (@@: link) Creating and Dropping Tables --- 745,749 ---- This is a reference to another table. You typically need to only give the name of the foreign class that is referenced. ! `ForeignKey` implies an ``INT`` column. Creating and Dropping Tables *************** *** 785,792 **** ``MyClass.delColumn("username")``). ! You can also add Joins (@@: link), like ``MyClass.addJoin(MultipleJoin("MyOtherClass"))``, and remove joins with `delJoin`. `delJoin` does not take strings, you have to get the join object out of the `_joins` attribute. Legacy Database Schemas --- 804,815 ---- ``MyClass.delColumn("username")``). ! .. _addJoin: ! ! You can also add Joins__, like ``MyClass.addJoin(MultipleJoin("MyOtherClass"))``, and remove joins with `delJoin`. `delJoin` does not take strings, you have to get the join object out of the `_joins` attribute. + + __ Relationships_: Legacy Database Schemas |
From: <ian...@us...> - 2003-06-28 22:21:23
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv1718/SQLObject Modified Files: Col.py Log Message: Fix CurrencyCol Index: Col.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Col.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** Col.py 31 May 2003 02:00:27 -0000 1.23 --- Col.py 28 Jun 2003 22:21:21 -0000 1.24 *************** *** 347,350 **** --- 347,353 ---- SODecimalCol.__init__(self, **kw) + class CurrencyCol(DecimalCol): + baseClass = SOCurrencyCol + def popKey(kw, name, default=None): if not kw.has_key(name): |
From: <ian...@us...> - 2003-06-28 22:20:57
|
Update of /cvsroot/sqlobject/SQLObject/tests In directory sc8-pr-cvs1:/tmp/cvs-serv1615 Modified Files: test.py Log Message: Tweak new-style naming Index: test.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/tests/test.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** test.py 26 Jun 2003 08:33:56 -0000 1.17 --- test.py 28 Jun 2003 22:20:55 -0000 1.18 *************** *** 9,14 **** class TestSO1(SQLObject): _columns = [ - StringCol('name', length=10), StringCol('passwd', length=10), ] --- 9,15 ---- class TestSO1(SQLObject): + name = StringCol(length=10) + _columns = [ StringCol('passwd', length=10), ] |
From: <ian...@us...> - 2003-06-28 22:20:41
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv1550 Modified Files: Style.py Log Message: Added MixedCaseStyle, tweaked styles Index: Style.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Style.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Style.py 12 May 2003 01:58:21 -0000 1.3 --- Style.py 28 Jun 2003 22:20:37 -0000 1.4 *************** *** 1,5 **** import re ! __all__ = ["Style", "MixedCaseUnderscoreStyle", "DefaultStyle"] class Style(object): --- 1,6 ---- import re ! __all__ = ["Style", "MixedCaseUnderscoreStyle", "DefaultStyle", ! "MixedCaseStyle"] class Style(object): *************** *** 16,20 **** pythonClassToDBTable=None, dbTableToPythonClass=None, ! idForTable=None): if pythonAttrToDBColumn: self.pythonAttrToDBColumn = lambda a, s=self: pythonAttrToDBColumn(s, a) --- 17,22 ---- pythonClassToDBTable=None, dbTableToPythonClass=None, ! idForTable=None, ! longID=False): if pythonAttrToDBColumn: self.pythonAttrToDBColumn = lambda a, s=self: pythonAttrToDBColumn(s, a) *************** *** 27,30 **** --- 29,33 ---- if idForTable: self.idForTable = lambda a, s=self: idForTable(s, a) + self.longID = longID def pythonAttrToDBColumn(self, attr): *************** *** 41,48 **** def idForTable(self, table): ! return 'id' def pythonClassToAttr(self, className): ! return className[0].lower() + className[1:] def instanceAttrToIDAttr(self, attr): --- 44,54 ---- def idForTable(self, table): ! if self.longID: ! return self.tableReference(table) ! else: ! return 'id' def pythonClassToAttr(self, className): ! return lowerword(className) def instanceAttrToIDAttr(self, attr): *************** *** 80,89 **** DefaultStyle = MixedCaseUnderscoreStyle ! def longID(self, table): """ ! Use SomeStyle(idForTable=longID) to use this. This will ! make table IDs use the full table, like person_id. """ ! return defaultStyle = DefaultStyle() --- 86,107 ---- DefaultStyle = MixedCaseUnderscoreStyle ! class MixedCaseStyle(Style): ! """ ! This style leaves columns as mixed-case, and uses long ! ID names (like ProductID instead of simply id). """ ! ! def pythonAttrToDBColumn(self, attr): ! return capword(attr) ! ! def dbColumnToPythonAttr(self, col): ! return lowerword(col) ! ! def dbTableToPythonClass(self, table): ! return capword(table) ! ! def tableReference(self, table): ! return table + "ID" defaultStyle = DefaultStyle() *************** *** 118,121 **** --- 136,145 ---- else: return '_%s' % m + + def capword(s): + return s[0].upper() + s[1:] + + def lowerword(s): + return s[0].lower() + s[1:] _underToMixedRE = re.compile('_.') |
From: <ian...@us...> - 2003-06-28 22:20:25
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv1501 Modified Files: DBConnection.py Join.py Log Message: More descending sorting support Index: DBConnection.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/DBConnection.py,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** DBConnection.py 26 Jun 2003 08:33:56 -0000 1.35 --- DBConnection.py 28 Jun 2003 22:20:20 -0000 1.36 *************** *** 13,16 **** --- 13,17 ---- import os import anydbm + from Join import sorter try: *************** *** 832,839 **** self._maxNext = -1 results = self.allResults() ! def cmper(a, b, orderBy=select.ops['orderBy']): ! return cmp(getattr(a, orderBy), ! getattr(b, orderBy)) ! results.sort(cmper) self._results = results if select.ops.get('start'): --- 833,837 ---- self._maxNext = -1 results = self.allResults() ! results.sort(sorter(select.ops['orderBy'])) self._results = results if select.ops.get('start'): Index: Join.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Join.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Join.py 26 Jun 2003 08:33:56 -0000 1.4 --- Join.py 28 Jun 2003 22:20:20 -0000 1.5 *************** *** 52,85 **** self.orderBy = defaultSortClass._defaultOrder if self.orderBy is not None: ! def sorter(a, b, attr=self.orderBy): ! if attr.startswith('-'): ! return -sorter(a, b, attr=attr[1:]) ! return cmp(getattr(a, attr), ! getattr(b, attr)) ! results.sort(self._sorter(self.orderBy)) return results ! def _sorter(self, orderBy): ! if isinstance(orderBy, tuple) or isinstance(orderBy, list): ! if len(orderBy) == 1: ! orderBy = orderBy[0] ! else: ! fhead = self._sorter(orderBy[0]) ! frest = self._sorter(orderBy[1:]) ! return lambda a, b, fhead=fhead, frest=frest: fhead(a, b) or frest(a, b) ! if isinstance(orderBy, SQLBuilder.DESC) \ ! and isinstance(orderBy.expr, SQLBuilder.SQLObjectField): ! orderBy = '-' + orderBy.expr.original ! elif isinstance(orderBy, SQLBuilder.SQLObjectField): ! orderBy = orderBy.original ! # @@: but we don't handle more complex expressions for orderings ! if orderBy.startswith('-'): ! orderBy = orderBy[1:] ! def sorter(a, b, attr=orderBy): ! return cmp(getattr(b, attr), getattr(a, attr)) else: ! def sorter(a, b, attr=orderBy): ! return cmp(getattr(a, attr), getattr(b, attr)) ! return sorter # This is a one-to-many --- 52,80 ---- self.orderBy = defaultSortClass._defaultOrder if self.orderBy is not None: ! results.sort(sorter(self.orderBy)) return results ! def sorter(orderBy): ! if isinstance(orderBy, tuple) or isinstance(orderBy, list): ! if len(orderBy) == 1: ! orderBy = orderBy[0] else: ! fhead = sorter(orderBy[0]) ! frest = sorter(orderBy[1:]) ! return lambda a, b, fhead=fhead, frest=frest: fhead(a, b) or frest(a, b) ! if isinstance(orderBy, SQLBuilder.DESC) \ ! and isinstance(orderBy.expr, SQLBuilder.SQLObjectField): ! orderBy = '-' + orderBy.expr.original ! elif isinstance(orderBy, SQLBuilder.SQLObjectField): ! orderBy = orderBy.original ! # @@: but we don't handle more complex expressions for orderings ! if orderBy.startswith('-'): ! orderBy = orderBy[1:] ! def cmper(a, b, attr=orderBy): ! return cmp(getattr(b, attr), getattr(a, attr)) ! else: ! def cmper(a, b, attr=orderBy): ! return cmp(getattr(a, attr), getattr(b, attr)) ! return cmper # This is a one-to-many |
From: <ian...@us...> - 2003-06-28 22:19:29
|
Update of /cvsroot/sqlobject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv1374 Modified Files: setup.py Log Message: Filter warnings Index: setup.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/setup.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** setup.py 8 Apr 2003 09:04:55 -0000 1.8 --- setup.py 28 Jun 2003 22:19:16 -0000 1.9 *************** *** 1,3 **** --- 1,5 ---- from distutils.core import setup + import warnings + warnings.filterwarnings("ignore", "Unknown distribution option") import sys |
From: <ian...@us...> - 2003-06-28 22:19:10
|
Update of /cvsroot/sqlobject/SQLObject/docs In directory sc8-pr-cvs1:/tmp/cvs-serv1329 Modified Files: SQLObject.txt Log Message: Rewrite for 0.4 Index: SQLObject.txt =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/docs/SQLObject.txt,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** SQLObject.txt 29 Apr 2003 08:23:17 -0000 1.12 --- SQLObject.txt 28 Jun 2003 22:19:08 -0000 1.13 *************** *** 1,4 **** ``````````````` ! SQLObject 0.3 ``````````````` --- 1,4 ---- ``````````````` ! SQLObject 0.4 ``````````````` *************** [...1572 lines suppressed...] ! * `MultipleJoin` ! * `RelatedJoin` ! ! From `SQLObject.Style`: ! * `Style` ! * `MixedCaseUnderscoreStyle` ! * `DefaultStyle` ! * `MixedCaseStyle` ! ! From `SQLObject.SQLBuilder`: * `AND` *************** *** 908,911 **** --- 994,998 ---- * `IN` * `LIKE` + * `DESC` * `CONTAINSSTRING` * `const` |
From: <ian...@us...> - 2003-06-28 22:18:52
|
Update of /cvsroot/sqlobject/SQLObject/docs In directory sc8-pr-cvs1:/tmp/cvs-serv1312 Modified Files: default.css Log Message: Made header levels more distinct Index: default.css =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/docs/default.css,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** default.css 26 Feb 2003 23:59:42 -0000 1.1.1.1 --- default.css 28 Jun 2003 22:18:49 -0000 1.2 *************** *** 108,121 **** font-family: Helvetica, Arial, sans-serif; border: thin solid black; - background-color: #cccccc; -moz-border-radius: 8px; padding: 4px; } h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: medium solid black; -moz-border-radius: 20px; } --- 108,137 ---- font-family: Helvetica, Arial, sans-serif; border: thin solid black; -moz-border-radius: 8px; padding: 4px; } + h1 { + background-color: #444499; + border: medium solid black; + color: #ffffff; + } + + h2 { + background-color: #666666; + color: #ffffff; + border: medium solid black; + } + + h3, h4, h5, h6 { + background-color: #cccccc; + color: #000000; + } + h1.title { text-align: center; background-color: #444499; color: #eeeeee; ! border: thick solid black; -moz-border-radius: 20px; } *************** *** 236,237 **** --- 252,274 ---- ul.auto-toc { list-style-type: none } + + // Highlighting: + + .function {color: #000077; font-weight: bold} + .keyword {color: #004444;} + .comment {color: #770000; font-style: italic} + .normal {color: #000000;} + .string {color: #006600;} + .symbol {color: #000000;} + + .htmltag {color: #000077;} + .htmlsymbol {color: #000000;} + .htmlnormal {color: #000000;} + .htmlcomment {color: #770000; font-style: italic} + .htmlstring {color: #006600;} + .htmlattr {color: #000000;} + + .stmlfunction {color: #000077; font-weight: bold} + .stmlattr {color: #000000;} + .stmlstring {color: #006600;} + .stmlexpr {color: #004444;} \ No newline at end of file |
From: <ian...@us...> - 2003-06-28 22:18:21
|
Update of /cvsroot/sqlobject/SQLObject/docs In directory sc8-pr-cvs1:/tmp/cvs-serv1283 Added Files: build Log Message: Added builder to go with new example structure --- NEW FILE: build --- #!/bin/sh pushd ../examples > /dev/null ./examplestripper.py popd > /dev/null buildhtml.py --no-toc-backlinks |
Update of /cvsroot/sqlobject/SQLObject/examples In directory sc8-pr-cvs1:/tmp/cvs-serv1222 Added Files: codebits.py config.py examplestripper.py personaddress.py setup.py simpleperson.py styles.py userrole.py Log Message: Added examples, example stripper --- NEW FILE: codebits.py --- # This isn't a full example... ## Snippet "person_magicmethod" class Person(SQLObject): # ... def imageFilename(self): return 'images/person-%s.jpg' % self.id def _get_image(self): if not os.path.exists(self.imageFilename()): return None f = open(self.imageFilename()) v = f.read() f.close() return v def _set_image(self, value): # assume we get a string for the image f = open(self.imageFilename(), 'w') f.write(value) f.close() def _del_image(self, value): # I usually wouldn't include a method like this, but for # instructional purposes... os.unlink(self.imageFilename()) _doc_image = 'The headshot for the person' ## end snippet ## Snippet "person_magicoverride" class Person(SQLObject): lastName = StringCol() firstName = StringCol() def _set_lastName(self, value): self.notifyLastNameChange(value) self._SO_set_lastName(value) ## end snippet ## Snippet "phonenumber_magicoverride" import re class PhoneNumber(SQLObject): phoneNumber = StringCol(length=30) _garbageCharactersRE = re.compile(r'[\-\.\(\) ]') _phoneNumberRE = re.compile(r'^[0-9]+$') def _set_phoneNumber(self, value): value = self._garbageCharactersRE.sub('', value) if not len(value) >= 10: raise ValueError, 'Phone numbers must be at least 10 digits long' if not self._phoneNumberRE.match(value): raise ValueError, 'Phone numbers can contain only digits' self._SO_set_phoneNumber(value) def _get_phoneNumber(self): value = self._SO_get_phoneNumber() number = '(%s) %s-%s' % (value[0:3], value[3:6], value[6:10]) if len(value) > 10: number += ' ext.%s' % value[10:] return number ## end snippet ## Snippet "transactions1" conn = DBConnection.PostgresConnection('yada') trans = conn.transaction() p = Person(1, trans) p.firstName = 'Bob' trans.commit() p.firstName = 'Billy' trans.rollback() ## end snippet ## Snippet "transactions2" class Person(SQLObject): _cacheValue = False # ... ## end snippet --- NEW FILE: config.py --- from SQLObject import * """ This contains basic configuration for all the examples. Since they all require a connection, you can configure that just in this file. """ ## Use one of these to define your connection: """ conn = MySQLConnection(user='test', db='testdb') conn = PostgresConnection('user=test dbname=testdb') conn = SQLiteConnect('database.db') conn = DBMConnection('database/') """ conn = DBMConnection('database/') conn = MySQLConnection(user='test', db='test') --- NEW FILE: examplestripper.py --- #!/usr/bin/env python """ This script strips bits of examples from a larger script, formats them as HTML, and writes them out. You mark snippets of code like: ## Snippet "snippetname" code... ## End Snippet Then a file snippets/snippetname.html is created. """ import re, os, sys import warnings _snippetRE = re.compile(r'^##\s+Snippet\s+"(.*?)"', re.I) _endSnippetRE = re.compile(r'^##\s+End\s+Snippet', re.I) def stripSnippets(lines): results = {} name = None for line in lines: match = _snippetRE.search(line) if match: if name is not None: warnings.warn('You started snippet %s when snippet %s was not ended' % (match.group(1), name)) name = match.group(1) continue match = _endSnippetRE.search(line) if match: name = None if name is None: continue results.setdefault(name, []).append(line) return results _bodyRE = re.compile(r'<body[^>]*>', re.I) _endBodyRE = re.compile(r'</body>', re.I) _preRE = re.compile(r'<pre>\n<tt>\n', re.I) _endPreRE = re.compile(r'\n</pre>', re.I) def snipFile(filename): f = open(filename) d = stripSnippets(f) f.close() dirname = os.path.join(os.path.dirname(filename), 'snippets') if not os.path.exists(dirname): os.mkdir(dirname) for key, value in d.items(): fn = os.path.join(dirname, '%s' % key) f = open(fn + ".py", 'w') f.write(''.join(value)) f.close() os.system('source-highlight -spython -fxhtml -cdefault.css %s > /dev/null 2>&1' % (fn + ".py")) f = open(fn + ".py.html") c = f.read() f.close() os.unlink(fn + ".py.html") c = c[_bodyRE.search(c).end():] c = c[:_endBodyRE.search(c).start()] c = _preRE.sub('<pre class="literal-block"><tt>', c) c = _endPreRE.sub('</pre>', c) f = open(fn + ".html", 'w') f.write(c) f.close() def snipAll(dir): if dir == sys.argv[0]: return if dir.endswith('snippets'): return if os.path.isdir(dir): for fn in os.listdir(dir): fn = os.path.join(dir, fn) snipAll(fn) elif dir.endswith('.py'): snipFile(dir) if __name__ == '__main__': args = sys.argv[1:] if not args: args = ['.'] for arg in args: snipAll(arg) --- NEW FILE: personaddress.py --- from SQLObject import * from config import conn __connection__ = conn ## Snippet "address-person" class Person(SQLObject): firstName = StringCol() middleInitial = StringCol(length=1, default=None) lastName = StringCol() addresses = MultipleJoin('Address') ## end snippet ## Snippet "address-address" class Address(SQLObject): street = StringCol() city = StringCol() state = StringCol(length=2) zip = StringCol(length=9) person = ForeignKey('Person') ## end snippet def reset(): Person.dropTable(ifExists=True) Person.createTable() Address.dropTable(ifExists=True) Address.createTable() reset() ## Snippet "address-use1" p = Person.new(firstName='John', lastName='Doe') print p.addresses #>> [] a1 = Address.new(street='123', city='Smallsville', state='IL', zip='50484', person=p) print [a.street for a in p.addresses] #>> ['123'] ## end snippet # We'll add some more data to make the results more interesting: add1 = Person.new(firstName='Jane', lastName='Doe') add2 = Person.new(firstName='Tom', lastName='Brown') Address.new(street='5839', city='Eckersville', state='IL', zip='50482', person=add1) Address.new(street='4', city='Whinging', state='AZ', zip='49378', person=add2) ## Snippet "person-select1" peeps = Person.select(Person.q.firstName=="John") print list(peeps) #>> [<Person 1 lastName='Doe' middleInitial=None firstName='John'>] # SELECT person.id FROM person WHERE person.first_name = 'John'; ## end snippet ## Snippet "person-select2" peeps = Person.select( AND(Address.q.personID == Person.q.id, Address.q.zip.startswith('504'))) print list(peeps) # SELECT person.id FROM person, phone_number # WHERE (phone_number.id = person.id AND # phone_number.phone_number LIKE '612%'); ## end snippet ## Snippet "person-select3" peeps = Person.select("""address.id = person.id AND address.zip LIKE '504%'""", clauseTables=['address']) ## end snippet list(peeps) --- NEW FILE: setup.py --- import sys from config import conn import SQLObject main = sys.modules['__main__'] if '-v' in sys.argv: conn.debug = 1 def reset(): classes = [] for name in dir(main): value = getattr(main, name) if isinstance(value, type) \ and issubclass(value, SQLObject.SQLObject)\ and value is not SQLObject.SQLObject: value.dropTable(ifExists=True) value.createTable() --- NEW FILE: simpleperson.py --- from SQLObject import * ## Use one of these to define your connection: """ ## Snippet "connections" conn = MySQLConnection(user='test', db='testdb') conn = PostgresConnection('user=test dbname=testdb') conn = SQLiteConnect('database.db') conn = DBMConnection('database/') ## End snippet """ conn = DBMConnection('database/') conn = MySQLConnection(user='test', db='test') ## Snippet "simpleaddress-person1" class Person(SQLObject): _connection = conn firstName = StringCol() middleInitial = StringCol(length=1, default=None) lastName = StringCol() ## end snippet ## We create a table like this: (for MySQL) """ ## Snippet "simpleaddress-schema-person1" CREATE TABLE person ( id INT PRIMARY KEY AUTO_INCREMENT, first_name TEXT, middle_initial CHAR(1), last_name TEXT ); ## end snippet """ def reset(): Person.dropTable(ifExists=True) Person.createTable() ## Get rid of any tables we have left over... Person.dropTable(ifExists=True) ## Now we create new tables... ## Snippet "simpleaddress-person1-create" Person.createTable() ## End snippet ## Snippet "simpleaddress-person1-use" p = Person.new(firstName="John", lastName="Doe") print p #>> <Person 1 firstName='John' middleInitial=None lastName='Doe'> print p.firstName #>> 'John' p.middleInitial = 'Q' print p.middleInitial #>> 'Q' p2 = Person(1) print p2 #>> <Person 1 firstName='John' middleInitial='Q' lastName='Doe'> print p is p2 #>> True ## End snippet reset() print '-'*60 conn.debug = 1 ## Snippet "simpleaddress-person1-use-debug" p = Person.new(firstName="John", lastName="Doe") #>> QueryIns: # INSERT INTO person (last_name, middle_initial, first_name) # VALUES ('Doe', NULL, 'John') # #-- Not quite optimized, we don't remember the values we used to #-- create the object, so they get re-fetched from the database: #>> QueryOne: # SELECT last_name, middle_initial, first_name # FROM person # WHERE id = 1 print p #>> <Person 1 firstName='John' middleInitial=None lastName='Doe'> print p.firstName #-- Now we've saved cached the column values, so we don't fetch #-- it again. #>> 'John' p.middleInitial = 'Q' #>> Query : # UPDATE person # SET middle_initial = 'Q' # WHERE id = 1 print p.middleInitial #>> 'Q' p2 = Person(1) #-- Again, no database access, since we're just grabbing the same #-- instance we already had. print p2 #>> <Person 1 firstName='John' middleInitial='Q' lastName='Doe'> print p is p2 #>> True ## End snippet ## Snippet "simpleaddress-person1-use-set" p.set(firstName='Bob', lastName='Dole') ## end snippet --- NEW FILE: styles.py --- from SQLObject import * from config import conn __connection__ = conn ## Snippet "style1" class Person(SQLObject): _style = MixedCaseStyle(longID=True) firstName = StringCol() lastName = StringCol() ## end snippet """ ## Snippet "default-style" __connection__.style = MixedCaseStyle(longID=True) ## end snippet """ ## Snippet "style-table" class User(SQLObject): _table = "user_table" _idName = "userid" username = StringCol(length=20, dbName='name') ## end snippet --- NEW FILE: userrole.py --- from SQLObject import * import setup __connection__ = setup.conn True, False = 1==1, 0==1 ## Snippet "userrole-classes" class User(SQLObject): # user is a reserved word in some databases, so we won't # use that for the table name: _table = "user_table" username = StringCol(alternateID=True, length=20) # We'd probably define more attributes, but we'll leave # that excersize to the reader... roles = RelatedJoin('Role') class Role(SQLObject): name = StringCol(alternateID=True, length=20) users = RelatedJoin('User') ## end snippet #def reset(): # User.dropTable(ifExists=True) # User.createTable() # Role.dropTable(ifExists=True) # Role.createTable() setup.reset() ## Snippet "userrole-use" bob = User.new(username='bob') tim = User.new(username='tim') jay = User.new(username='jay') admin = Role.new(name='admin') editor = Role.new(name='editor') bob.addRole(admin) bob.addRole(editor) tim.addRole(editor) print bob.roles #>> [<Role 1 name='admin'>, <Role 2 name='editor'>] print tim.roles #>> [<Role 2 name='editor'>] print jay.roles #>> [] print admin.users #>> [<User 1 username='bob'>] print editor.users #>> [<User 1 username='bob'>, <User 2 username='tim'>] ## end snippet ## Snippet "userrole-use-alternate" print User.byUsername('bob') #>> <User 1 username='bob'> print Role.byName('admin') #>> <Role 1 name='admin'> ## End snippet |
From: <ian...@us...> - 2003-06-26 08:34:40
|
Update of /cvsroot/sqlobject/SQLObject/docs In directory sc8-pr-cvs1:/tmp/cvs-serv4218/docs Modified Files: News.txt Log Message: updated Index: News.txt =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/docs/News.txt,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** News.txt 30 May 2003 02:20:22 -0000 1.7 --- News.txt 26 Jun 2003 08:34:38 -0000 1.8 *************** *** 72,75 **** --- 72,81 ---- the exception in either case). + * Can order by descending order, with the `reversed` option to + the `select` method, or by prefixing the column with a ``"-"``. + + * Ordering with joins works better -- you can order with multiple + columns, as well as descending ordering. + Col and Join ~~~~~~~~~~~~ *************** *** 130,133 **** --- 136,142 ---- * ``ForeignKey`` columns return None if the associated column is NULL in the database (used to just act weird). + + * Instantiating an object with an id of None will give an error, + instead of just acting weird. Internal |
From: <ian...@us...> - 2003-06-26 08:33:59
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv4120/SQLObject Modified Files: DBConnection.py Join.py SQLBuilder.py SQLObject.py Log Message: * Made descending ordering work * Made ordering with joins more robust Index: DBConnection.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/DBConnection.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** DBConnection.py 24 May 2003 21:17:17 -0000 1.34 --- DBConnection.py 26 Jun 2003 08:33:56 -0000 1.35 *************** *** 174,194 **** ops = select.ops ! def clauseList(lst): if type(lst) not in (type([]), type(())): lst = [lst] ! return [clauseQuote(i) for i in lst] def clauseQuote(s): if type(s) is type(""): assert SQLBuilder.sqlIdentifier(s), "Strings in clauses are expected to be column identifiers. I got: %r" % s if select.sourceClass._SO_columnDict.has_key(s): s = select.sourceClass._SO_columnDict[s].dbName ! return s else: ! return SQLBuilder.sqlRepr(s) if order and ops.get('groupBy'): ! q = "%s GROUP BY %s" % (q, ", ".join(clauseList(ops['groupBy']))) if order and ops.get('dbOrderBy'): ! q = "%s ORDER BY %s" % (q, ", ".join(clauseList(ops['dbOrderBy']))) start = ops.get('start', 0) --- 174,206 ---- ops = select.ops ! def clauseList(lst, desc=False): if type(lst) not in (type([]), type(())): lst = [lst] ! lst = [clauseQuote(i) for i in lst] ! if desc: ! lst = [SQLBuilder.DESC(i) for i in lst] ! return ', '.join([SQLBuilder.sqlRepr(i) for i in lst]) ! def clauseQuote(s): if type(s) is type(""): + if s.startswith('-'): + desc = True + s = s[1:] + else: + desc = False assert SQLBuilder.sqlIdentifier(s), "Strings in clauses are expected to be column identifiers. I got: %r" % s if select.sourceClass._SO_columnDict.has_key(s): s = select.sourceClass._SO_columnDict[s].dbName ! if desc: ! return SQLBuilder.DESC(SQLBuilder.SQLConstant(s)) ! else: ! return SQLBuilder.SQLConstant(s) else: ! return s if order and ops.get('groupBy'): ! q = "%s GROUP BY %s" % (q, clauseList(ops['groupBy'])) if order and ops.get('dbOrderBy'): ! q = "%s ORDER BY %s" % (q, clauseList(ops['dbOrderBy'], ops.get('reversed', False))) start = ops.get('start', 0) Index: Join.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Join.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Join.py 4 Jun 2003 05:19:05 -0000 1.3 --- Join.py 26 Jun 2003 08:33:56 -0000 1.4 *************** *** 1,3 **** ! from SQLBuilder import NoDefault import Style import SQLObject --- 1,4 ---- ! import SQLBuilder ! NoDefault = SQLBuilder.NoDefault import Style import SQLObject *************** *** 52,59 **** if self.orderBy is not None: def sorter(a, b, attr=self.orderBy): return cmp(getattr(a, attr), getattr(b, attr)) ! results.sort(sorter) return results # This is a one-to-many --- 53,85 ---- if self.orderBy is not None: def sorter(a, b, attr=self.orderBy): + if attr.startswith('-'): + return -sorter(a, b, attr=attr[1:]) return cmp(getattr(a, attr), getattr(b, attr)) ! results.sort(self._sorter(self.orderBy)) return results + + def _sorter(self, orderBy): + if isinstance(orderBy, tuple) or isinstance(orderBy, list): + if len(orderBy) == 1: + orderBy = orderBy[0] + else: + fhead = self._sorter(orderBy[0]) + frest = self._sorter(orderBy[1:]) + return lambda a, b, fhead=fhead, frest=frest: fhead(a, b) or frest(a, b) + if isinstance(orderBy, SQLBuilder.DESC) \ + and isinstance(orderBy.expr, SQLBuilder.SQLObjectField): + orderBy = '-' + orderBy.expr.original + elif isinstance(orderBy, SQLBuilder.SQLObjectField): + orderBy = orderBy.original + # @@: but we don't handle more complex expressions for orderings + if orderBy.startswith('-'): + orderBy = orderBy[1:] + def sorter(a, b, attr=orderBy): + return cmp(getattr(b, attr), getattr(a, attr)) + else: + def sorter(a, b, attr=orderBy): + return cmp(getattr(a, attr), getattr(b, attr)) + return sorter # This is a one-to-many Index: SQLBuilder.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLBuilder.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** SQLBuilder.py 5 May 2003 17:35:19 -0000 1.5 --- SQLBuilder.py 26 Jun 2003 08:33:56 -0000 1.6 *************** *** 358,365 **** def __getattr__(self, attr): if attr == 'id': ! return Table.__getattr__(self, self.soClass._idName) else: ! return Table.__getattr__( ! self, self.soClass._SO_columnDict[attr].dbName) class Field(SQLExpression): --- 358,366 ---- def __getattr__(self, attr): if attr == 'id': ! return SQLObjectField(self.tableName, self.soClass._idName, attr) else: ! return SQLObjectField(self.tableName, ! self.soClass._SO_columnDict[attr].dbName, ! attr) class Field(SQLExpression): *************** *** 374,377 **** --- 375,383 ---- return executor.field(self.tableName, self.fieldName) + class SQLObjectField(Field): + def __init__(self, tableName, fieldName, original): + self.original = original + Field.__init__(self, tableName, fieldName) + class ConstantSpace: def __getattr__(self, attr): *************** *** 517,520 **** --- 523,536 ---- ## SQL Builtins ######################################## + + class DESC(SQLExpression): + + def __init__(self, expr): + self.expr = expr + + def sqlRepr(self): + if isinstance(self.expr, DESC): + return sqlRepr(self.expr.expr) + return '%s DESC' % sqlRepr(self.expr) def AND(*ops): Index: SQLObject.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLObject.py,v retrieving revision 1.45 retrieving revision 1.46 diff -C2 -d -r1.45 -r1.46 *** SQLObject.py 4 Jun 2003 05:20:05 -0000 1.45 --- SQLObject.py 26 Jun 2003 08:33:56 -0000 1.46 *************** *** 846,853 **** def select(cls, clause=None, clauseTables=None, orderBy=NoDefault, groupBy=None, limit=None, ! lazyColumns=False): return SelectResults(cls, clause, clauseTables=clauseTables, orderBy=orderBy, groupBy=groupBy, ! limit=limit, lazyColumns=lazyColumns) select = classmethod(select) --- 846,854 ---- def select(cls, clause=None, clauseTables=None, orderBy=NoDefault, groupBy=None, limit=None, ! lazyColumns=False, reversed=False): return SelectResults(cls, clause, clauseTables=clauseTables, orderBy=orderBy, groupBy=groupBy, ! limit=limit, lazyColumns=lazyColumns, ! reversed=reversed) select = classmethod(select) *************** *** 979,984 **** orderBy = self.ops['orderBy'] if orderBy is not None: if sourceClass._SO_columnDict.has_key(orderBy): ! self.ops['dbOrderBy'] = sourceClass._SO_columnDict[orderBy].dbName def clone(self, **newOps): --- 980,994 ---- orderBy = self.ops['orderBy'] if orderBy is not None: + if isinstance(orderBy, str) and orderBy.startswith('-'): + orderBy = orderBy[1:] + desc = True + else: + desc = False if sourceClass._SO_columnDict.has_key(orderBy): ! self.ops['dbOrderBy'] = sourceClass._SO_columnDict[orderBy].dbName ! else: ! self.ops['dbOrderBy'] = orderBy ! if desc: ! self.ops['dbOrderBy'] = '-' + self.ops['dbOrderBy'] def clone(self, **newOps): *************** *** 1002,1005 **** --- 1012,1018 ---- def lazyColumns(self, value): return self.clone(lazyColumns=value) + + def reversed(self): + self.clone(reversed=not self.ops.get('reversed', False)) def __getitem__(self, value): |
From: <ian...@us...> - 2003-06-26 08:33:59
|
Update of /cvsroot/sqlobject/SQLObject/tests In directory sc8-pr-cvs1:/tmp/cvs-serv4120/tests Modified Files: test.py Log Message: * Made descending ordering work * Made ordering with joins more robust Index: test.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/tests/test.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** test.py 31 May 2003 01:59:45 -0000 1.16 --- test.py 26 Jun 2003 08:33:56 -0000 1.17 *************** *** 89,93 **** self.assertEqual(tc3.other2, tc4d) self.assertEqual(tc3.other2ID, tc4d.id) ! --- 89,96 ---- self.assertEqual(tc3.other2, tc4d) self.assertEqual(tc3.other2ID, tc4d.id) ! tcc = TestSO3.new(name='b', other=tc4a) ! self.assertEqual(tcc.other, tc4a) ! tcc2 = TestSO3.new(name='c', other=tc4a.id) ! self.assertEqual(tcc2.other, tc4a) *************** *** 176,179 **** --- 179,188 ---- range(0, 90)) + def test5(self): + self.counterEqual(Counter.select('all', orderBy='number', reversed=True), range(99, -1, -1)) + + def test6(self): + self.counterEqual(Counter.select('all', orderBy='-number'), range(99, -1, -1)) + ######################################## *************** *** 257,261 **** Phone.delColumn(col, changeSchema=True) Person.delJoin(join) - ######################################## --- 266,269 ---- *************** *** 368,373 **** _columns = [StringCol('zip', length=5), ForeignKey('PersonJoiner2')] ! # KeyCol('personJoiner2ID', foreignKey='PersonJoiner2')] class JoinTest2(SQLObjectTest): --- 376,382 ---- _columns = [StringCol('zip', length=5), + StringCol('plus4', length=4, default=None), ForeignKey('PersonJoiner2')] ! _defaultOrder = ['-zip', 'plus4'] class JoinTest2(SQLObjectTest): *************** *** 396,400 **** z = AddressJoiner2(id) self.assertEqual(z.zip, 'xxxxx') ! --- 405,413 ---- z = AddressJoiner2(id) self.assertEqual(z.zip, 'xxxxx') ! ! def testDefaultOrder(self): ! p1 = PersonJoiner2.byName('bob') ! self.assertEqual([i.zip for i in p1.addressJoiner2s], ! ['33333', '22222', '11111']) |
From: <ian...@us...> - 2003-06-04 05:20:08
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv11660/SQLObject Modified Files: SQLObject.py Log Message: Made SomeSQLObject(None) bomb instead of just acting weird. Index: SQLObject.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLObject.py,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** SQLObject.py 31 May 2003 02:00:39 -0000 1.44 --- SQLObject.py 4 Jun 2003 05:20:05 -0000 1.45 *************** *** 323,326 **** --- 323,329 ---- + class CreateNewSQLObject: + pass + # SQLObject is the superclass for all SQLObject classes, of # course. All the deeper magic is done in MetaSQLObject, and *************** *** 370,377 **** def __new__(cls, id, connection=None, selectResults=None): # When id is None, that means we are trying # to create a new object. This is done by the # `new()` method. ! if id is None: # Create an actual new object: inst = object.__new__(cls) --- 373,382 ---- def __new__(cls, id, connection=None, selectResults=None): + assert id is not None, 'None is not a possible id for %s' % cls.__name + # When id is None, that means we are trying # to create a new object. This is done by the # `new()` method. ! if id is CreateNewSQLObject: # Create an actual new object: inst = object.__new__(cls) *************** *** 743,750 **** # a new object. if kw.has_key('connection'): ! inst = cls(None, connection=kw['connection']) del kw['connection'] else: ! inst = cls(None) # First we do a little fix-up on the keywords we were --- 748,755 ---- # a new object. if kw.has_key('connection'): ! inst = cls(CreateNewSQLObject, connection=kw['connection']) del kw['connection'] else: ! inst = cls(CreateNewSQLObject) # First we do a little fix-up on the keywords we were |
From: <ian...@us...> - 2003-06-04 05:19:08
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv11549/SQLObject Modified Files: Join.py Log Message: Trim null values from joins Index: Join.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Join.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Join.py 30 May 2003 02:22:51 -0000 1.2 --- Join.py 4 Jun 2003 05:19:05 -0000 1.3 *************** *** 82,86 **** self.joinColumn, inst.id) ! return self._applyOrderBy([self.otherClass(id) for (id,) in ids], self.otherClass) class MultipleJoin(Join): --- 82,86 ---- self.joinColumn, inst.id) ! return self._applyOrderBy([self.otherClass(id) for (id,) in ids if id is not None], self.otherClass) class MultipleJoin(Join): *************** *** 118,122 **** self.joinColumn, inst.id) ! return self._applyOrderBy([self.otherClass(id) for (id,) in ids], self.otherClass) def remove(self, inst, other): --- 118,122 ---- self.joinColumn, inst.id) ! return self._applyOrderBy([self.otherClass(id) for (id,) in ids if id is not None], self.otherClass) def remove(self, inst, other): |
From: <ian...@us...> - 2003-05-31 02:00:42
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv14543 Modified Files: SQLObject.py Log Message: More foreignKey fixes Index: SQLObject.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLObject.py,v retrieving revision 1.43 retrieving revision 1.44 diff -C2 -d -r1.43 -r1.44 *** SQLObject.py 30 May 2003 03:24:53 -0000 1.43 --- SQLObject.py 31 May 2003 02:00:39 -0000 1.44 *************** *** 85,90 **** cls = findClass(needClass, registry=registryName) for obj, attr in q: ! if callable(getattr(obj, attr, None)): ! getattr(obj, attr)(cls) else: setattr(obj, attr, cls) --- 85,93 ---- cls = findClass(needClass, registry=registryName) for obj, attr in q: ! curr = getattr(obj, attr, None) ! if curr is cls: ! pass ! elif callable(curr): ! curr(cls) else: setattr(obj, attr, cls) *************** *** 469,473 **** # self._SO_class_className is a reference # to the class in question. ! getter = eval('lambda self: self._SO_foreignKey(self.%s and self._SO_class_%s)' % (instanceName(name), column.foreignKey)) else: # Same non-caching version as above. --- 472,476 ---- # self._SO_class_className is a reference # to the class in question. ! getter = eval('lambda self: self._SO_foreignKey(self.%s, self._SO_class_%s)' % (instanceName(name), column.foreignKey)) else: # Same non-caching version as above. |
From: <ian...@us...> - 2003-05-31 02:00:30
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv14448 Modified Files: Col.py Log Message: Made *ID keys names more permissive -- if you don't add the ID, it gets added for you. Index: Col.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/Col.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** Col.py 26 May 2003 21:48:54 -0000 1.22 --- Col.py 31 May 2003 02:00:27 -0000 1.23 *************** *** 89,94 **** self.foreignKey = foreignKey if self.foreignKey: ! assert self.name.upper().endswith('ID'), "All foreign key columns must end with 'ID' (%s)" % repr(self.name) ! self.foreignName = self.name[:-2] else: self.foreignName = None --- 89,98 ---- self.foreignKey = foreignKey if self.foreignKey: ! #assert self.name.upper().endswith('ID'), "All foreign key columns must end with 'ID' (%s)" % repr(self.name) ! if not self.name.upper().endswith('ID'): ! self.foreignName = self.name ! self.name = self.name + "ID" ! else: ! self.foreignName = self.name[:-2] else: self.foreignName = None |
From: <ian...@us...> - 2003-05-31 01:59:48
|
Update of /cvsroot/sqlobject/SQLObject/tests In directory sc8-pr-cvs1:/tmp/cvs-serv14231/tests Modified Files: test.py Log Message: Proper test of foreign keys Index: test.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/tests/test.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** test.py 24 May 2003 20:48:51 -0000 1.15 --- test.py 31 May 2003 01:59:45 -0000 1.16 *************** *** 55,58 **** --- 55,98 ---- MyClass = TestSO2 + class TestSO3(SQLObject): + name = StringCol(length=10) + other = ForeignKey('TestSO4', default=None) + other2 = KeyCol(foreignKey='TestSO4', default=None) + + class TestSO4(SQLObject): + me = StringCol(length=10) + + class TestCase34(SQLObjectTest): + + classes = [TestSO3, TestSO4] + + def testForeignKey(self): + tc3 = TestSO3.new(name='a') + self.assertEqual(tc3.other, None) + self.assertEqual(tc3.other2, None) + self.assertEqual(tc3.otherID, None) + self.assertEqual(tc3.other2ID, None) + tc4a = TestSO4.new(me='1') + tc3.other = tc4a + self.assertEqual(tc3.other, tc4a) + self.assertEqual(tc3.otherID, tc4a.id) + tc4b = TestSO4.new(me='2') + tc3.other = tc4b.id + self.assertEqual(tc3.other, tc4b) + self.assertEqual(tc3.otherID, tc4b.id) + tc4c = TestSO4.new(me='3') + tc3.other2 = tc4c + self.assertEqual(tc3.other2, tc4c) + self.assertEqual(tc3.other2ID, tc4c.id) + tc4d = TestSO4.new(me='4') + tc3.other2 = tc4d.id + self.assertEqual(tc3.other2, tc4d) + self.assertEqual(tc3.other2ID, tc4d.id) + + + + + + ######################################## ## Delete during select |
From: <ian...@us...> - 2003-05-30 03:49:03
|
Update of /cvsroot/sqlobject/SQLObject/SQLObject In directory sc8-pr-cvs1:/tmp/cvs-serv2322/SQLObject Modified Files: SQLObject.py Log Message: Continued fix for foreignKey Index: SQLObject.py =================================================================== RCS file: /cvsroot/sqlobject/SQLObject/SQLObject/SQLObject.py,v retrieving revision 1.42 retrieving revision 1.43 diff -C2 -d -r1.42 -r1.43 *** SQLObject.py 30 May 2003 02:22:51 -0000 1.42 --- SQLObject.py 30 May 2003 03:24:53 -0000 1.43 *************** *** 469,476 **** # self._SO_class_className is a reference # to the class in question. ! getter = eval('lambda self: self._SO_foreignKey(self.%s and self._SO_class_%s)' % (column.foreignKey, instanceName(name))) else: # Same non-caching version as above. ! getter = eval('lambda self: self._SO_class_%s(self._SO_getValue(%s))' % (column.foreignKey, repr(name))) setattr(cls, rawGetterName(name)[:-2], getter) --- 469,476 ---- # self._SO_class_className is a reference # to the class in question. ! getter = eval('lambda self: self._SO_foreignKey(self.%s and self._SO_class_%s)' % (instanceName(name), column.foreignKey)) else: # Same non-caching version as above. ! getter = eval('lambda self: self._SO_foreignKey(self._SO_getValue(%s), self._SO_class_%s)' % (repr(name), column.foreignKey)) setattr(cls, rawGetterName(name)[:-2], getter) |