From: Mike Bayer Date: Sat, 27 Mar 2010 19:20:03 +0000 (-0400) Subject: - 0.6beta3 version X-Git-Tag: rel_0_6beta3~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3cd2c4661f1522353be983a309dc947c2a2a28bb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 0.6beta3 version - remove redundant orderinglist docs, use just module docs - add warning for primary keys/unique colummns, [ticket:1669] --- diff --git a/doc/build/reference/ext/orderinglist.rst b/doc/build/reference/ext/orderinglist.rst index c5308689b3..a3581df59f 100644 --- a/doc/build/reference/ext/orderinglist.rst +++ b/doc/build/reference/ext/orderinglist.rst @@ -1,88 +1,9 @@ orderinglist ============ -.. module: sqlalchemy.ext.orderinglist - -:author: Jason Kirtland - -``orderinglist`` is a helper for mutable ordered relationships. It will intercept -list operations performed on a relationship collection and automatically -synchronize changes in list position with an attribute on the related objects. -(See :ref:`advdatamapping_entitycollections` for more information on the general pattern.) - -Example: Two tables that store slides in a presentation. Each slide -has a number of bullet points, displayed in order by the 'position' -column on the bullets table. These bullets can be inserted and re-ordered -by your end users, and you need to update the 'position' column of all -affected rows when changes are made. - -.. sourcecode:: python+sql - - slides_table = Table('Slides', metadata, - Column('id', Integer, primary_key=True), - Column('name', String)) - - bullets_table = Table('Bullets', metadata, - Column('id', Integer, primary_key=True), - Column('slide_id', Integer, ForeignKey('Slides.id')), - Column('position', Integer), - Column('text', String)) - - class Slide(object): - pass - class Bullet(object): - pass - - mapper(Slide, slides_table, properties={ - 'bullets': relationship(Bullet, order_by=[bullets_table.c.position]) - }) - mapper(Bullet, bullets_table) - -The standard relationship mapping will produce a list-like attribute on each Slide -containing all related Bullets, but coping with changes in ordering is totally -your responsibility. If you insert a Bullet into that list, there is no -magic- it won't have a position attribute unless you assign it it one, and -you'll need to manually renumber all the subsequent Bullets in the list to -accommodate the insert. - -An ``orderinglist`` can automate this and manage the 'position' attribute on all -related bullets for you. - -.. sourcecode:: python+sql - - mapper(Slide, slides_table, properties={ - 'bullets': relationship(Bullet, - collection_class=ordering_list('position'), - order_by=[bullets_table.c.position]) - }) - mapper(Bullet, bullets_table) - - s = Slide() - s.bullets.append(Bullet()) - s.bullets.append(Bullet()) - s.bullets[1].position - >>> 1 - s.bullets.insert(1, Bullet()) - s.bullets[2].position - >>> 2 - -Use the ``ordering_list`` function to set up the ``collection_class`` on relationships -(as in the mapper example above). This implementation depends on the list -starting in the proper order, so be SURE to put an order_by on your relationship. - -``ordering_list`` takes the name of the related object's ordering attribute as -an argument. By default, the zero-based integer index of the object's -position in the ``ordering_list`` is synchronized with the ordering attribute: -index 0 will get position 0, index 1 position 1, etc. To start numbering at 1 -or some other integer, provide ``count_from=1``. +.. automodule:: sqlalchemy.ext.orderinglist -Ordering values are not limited to incrementing integers. Almost any scheme -can implemented by supplying a custom ``ordering_func`` that maps a Python list -index to any value you require. See the [module -documentation](rel:docstrings_sqlalchemy.ext.orderinglist) for more -information, and also check out the unit tests for examples of stepped -numbering, alphabetical and Fibonacci numbering. +API Reference +------------- -.. automodule:: sqlalchemy.ext.orderinglist - :members: - :undoc-members: +.. autofunction:: ordering_list diff --git a/doc/build/static/docs.css b/doc/build/static/docs.css index f60eef3a60..ad6f999e65 100644 --- a/doc/build/static/docs.css +++ b/doc/build/static/docs.css @@ -149,7 +149,7 @@ li.toctree-l1 ul li li } -div.note { +div.note, div.warning { background-color:#EEFFEF; } @@ -160,6 +160,10 @@ div.admonition { font-size:.9em; } +div.warning .admonition-title { + color:#FF0000; +} + div.admonition .admonition-title { font-weight:bold; } diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index 13e8438012..376b13e64f 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -114,6 +114,6 @@ from sqlalchemy.engine import create_engine, engine_from_config __all__ = sorted(name for name, obj in locals().items() if not (name.startswith('_') or inspect.ismodule(obj))) -__version__ = '0.6beta2' +__version__ = '0.6beta3' del inspect, sys diff --git a/lib/sqlalchemy/ext/orderinglist.py b/lib/sqlalchemy/ext/orderinglist.py index db0bd2a4ec..0d2c3ae5d7 100644 --- a/lib/sqlalchemy/ext/orderinglist.py +++ b/lib/sqlalchemy/ext/orderinglist.py @@ -1,67 +1,92 @@ """A custom list that manages index/position information for its children. -``orderinglist`` is a custom list collection implementation for mapped -relationships that keeps an arbitrary "position" attribute on contained objects in -sync with each object's position in the Python list. - -The collection acts just like a normal Python ``list``, with the added -behavior that as you manipulate the list (via ``insert``, ``pop``, assignment, -deletion, what have you), each of the objects it contains is updated as needed -to reflect its position. This is very useful for managing ordered relationships -which have a user-defined, serialized order:: - - >>> from sqlalchemy import MetaData, Table, Column, Integer, String, ForeignKey - >>> from sqlalchemy.orm import mapper, relationship - >>> from sqlalchemy.ext.orderinglist import ordering_list - -A simple model of users their "top 10" things:: - - >>> metadata = MetaData() - >>> users = Table('users', metadata, - ... Column('id', Integer, primary_key=True)) - >>> blurbs = Table('user_top_ten_list', metadata, - ... Column('id', Integer, primary_key=True), - ... Column('user_id', Integer, ForeignKey('users.id')), - ... Column('position', Integer), - ... Column('blurb', String(80))) - >>> class User(object): - ... pass - ... - >>> class Blurb(object): - ... def __init__(self, blurb): - ... self.blurb = blurb - ... - >>> mapper(User, users, properties={ - ... 'topten': relationship(Blurb, collection_class=ordering_list('position'), - ... order_by=[blurbs.c.position])}) - - >>> mapper(Blurb, blurbs) - - -Acts just like a regular list:: - - >>> u = User() - >>> u.topten.append(Blurb('Number one!')) - >>> u.topten.append(Blurb('Number two!')) - -But the ``.position`` attibute is set automatically behind the scenes:: - - >>> assert [blurb.position for blurb in u.topten] == [0, 1] - -The objects will be renumbered automaticaly after any list-changing operation, -for example an ``insert()``:: - - >>> u.topten.insert(1, Blurb('I am the new Number Two.')) - >>> assert [blurb.position for blurb in u.topten] == [0, 1, 2] - >>> assert u.topten[1].blurb == 'I am the new Number Two.' - >>> assert u.topten[1].position == 1 - -Numbering and serialization are both highly configurable. See the docstrings -in this module and the main SQLAlchemy documentation for more information and -examples. - -The :class:`~sqlalchemy.ext.orderinglist.ordering_list` factory function is the -ORM-compatible constructor for `OrderingList` instances. +:author: Jason Kirtland + +``orderinglist`` is a helper for mutable ordered relationships. It will intercept +list operations performed on a relationship collection and automatically +synchronize changes in list position with an attribute on the related objects. +(See :ref:`advdatamapping_entitycollections` for more information on the general pattern.) + +Example: Two tables that store slides in a presentation. Each slide +has a number of bullet points, displayed in order by the 'position' +column on the bullets table. These bullets can be inserted and re-ordered +by your end users, and you need to update the 'position' column of all +affected rows when changes are made. + +.. sourcecode:: python+sql + + slides_table = Table('Slides', metadata, + Column('id', Integer, primary_key=True), + Column('name', String)) + + bullets_table = Table('Bullets', metadata, + Column('id', Integer, primary_key=True), + Column('slide_id', Integer, ForeignKey('Slides.id')), + Column('position', Integer), + Column('text', String)) + + class Slide(object): + pass + class Bullet(object): + pass + + mapper(Slide, slides_table, properties={ + 'bullets': relationship(Bullet, order_by=[bullets_table.c.position]) + }) + mapper(Bullet, bullets_table) + +The standard relationship mapping will produce a list-like attribute on each Slide +containing all related Bullets, but coping with changes in ordering is totally +your responsibility. If you insert a Bullet into that list, there is no +magic- it won't have a position attribute unless you assign it it one, and +you'll need to manually renumber all the subsequent Bullets in the list to +accommodate the insert. + +An ``orderinglist`` can automate this and manage the 'position' attribute on all +related bullets for you. + +.. sourcecode:: python+sql + + mapper(Slide, slides_table, properties={ + 'bullets': relationship(Bullet, + collection_class=ordering_list('position'), + order_by=[bullets_table.c.position]) + }) + mapper(Bullet, bullets_table) + + s = Slide() + s.bullets.append(Bullet()) + s.bullets.append(Bullet()) + s.bullets[1].position + >>> 1 + s.bullets.insert(1, Bullet()) + s.bullets[2].position + >>> 2 + +Use the ``ordering_list`` function to set up the ``collection_class`` on relationships +(as in the mapper example above). This implementation depends on the list +starting in the proper order, so be SURE to put an order_by on your relationship. + +.. warning:: ``ordering_list`` only provides limited functionality when a primary + key column or unique column is the target of the sort. Since changing the order of + entries often means that two rows must trade values, this is not possible when + the value is constrained by a primary key or unique constraint, since one of the rows + would temporarily have to point to a third available value so that the other row + could take its old value. ``ordering_list`` doesn't do any of this for you, + nor does SQLAlchemy itself. + +``ordering_list`` takes the name of the related object's ordering attribute as +an argument. By default, the zero-based integer index of the object's +position in the ``ordering_list`` is synchronized with the ordering attribute: +index 0 will get position 0, index 1 position 1, etc. To start numbering at 1 +or some other integer, provide ``count_from=1``. + +Ordering values are not limited to incrementing integers. Almost any scheme +can implemented by supplying a custom ``ordering_func`` that maps a Python list +index to any value you require. + + + """ from sqlalchemy.orm.collections import collection @@ -288,7 +313,3 @@ class OrderingList(list): func.__doc__ = getattr(list, func_name).__doc__ del func_name, func -if __name__ == '__main__': - import doctest - doctest.testmod(optionflags=doctest.ELLIPSIS) -