Changeset 350

Show
Ignore:
Timestamp:
07/02/08 15:17:29 (5 years ago)
Author:
ged
Message:
  • added add_mapper_property and add_table_column helper method in EntityBuilders
  • added full_tablename property on EntityDescriptor (includes schema name if
    any)
Location:
elixir/trunk/elixir
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/elixir/entity.py

    r349 r350  
    157157                    # key columns 
    158158                    parent_desc = self.parent._descriptor 
    159                     schema = parent_desc.table_options.get('schema', None) 
    160                     tablename = parent_desc.tablename 
    161                     if schema is not None: 
    162                         tablename = "%s.%s" % (schema, tablename) 
     159                    tablename = parent_desc.table_fullname 
    163160                    for pk_col in parent_desc.primary_keys: 
    164161                        colname = options.MULTIINHERITANCECOL_NAMEFORMAT % \ 
     
    534531        else: 
    535532            return None 
     533 
     534    def table_fullname(self): 
     535        ''' 
     536        Complete name of the table for the related entity. 
     537        Includes the schema name if there is one specified. 
     538        ''' 
     539        schema = self.table_options.get('schema', None) 
     540        if schema is not None: 
     541            return "%s.%s" % (schema, self.tablename) 
     542        else: 
     543            return self.tablename 
     544    table_fullname = property(table_fullname) 
    536545 
    537546    def columns(self): 
  • elixir/trunk/elixir/ext/associable.py

    r310 r350  
    99------------------------------ 
    1010 
    11 A frequent pattern in database schemas is the has_and_belongs_to_many, or a  
     11A frequent pattern in database schemas is the has_and_belongs_to_many, or a 
    1212many-to-many table. Quite often multiple tables will refer to a single one 
    1313creating quite a few many-to-many intermediate tables. 
    1414 
    1515Polymorphic associations lower the amount of many-to-many tables by setting up 
    16 a table that allows relations to any other table in the database, and relates  
    17 it to the associable table. In some implementations, this layout does not  
    18 enforce referential integrity with database foreign key constraints, this  
    19 implementation uses an additional many-to-many table with foreign key  
     16a table that allows relations to any other table in the database, and relates 
     17it to the associable table. In some implementations, this layout does not 
     18enforce referential integrity with database foreign key constraints, this 
     19implementation uses an additional many-to-many table with foreign key 
    2020constraints to avoid this problem. 
    2121 
     
    3838 
    3939.. sourcecode:: python 
    40      
     40 
    4141    class Tag(Entity): 
    4242        name = Field(Unicode) 
    43      
     43 
    4444    acts_as_taggable = associable(Tag) 
    45      
     45 
    4646    class Entry(Entity): 
    4747        title = Field(Unicode) 
    4848        acts_as_taggable('tags') 
    49      
     49 
    5050    class Article(Entity): 
    5151        title = Field(Unicode) 
     
    5656 
    5757.. sourcecode:: python 
    58      
     58 
    5959    class Address(Entity): 
    6060        street = Field(String(130)) 
    6161        city = Field(String(100)) 
    62      
     62 
    6363    is_addressable = associable(Address, 'addresses') 
    64      
     64 
    6565    class Person(Entity): 
    6666        name = Field(Unicode) 
    6767        orders = OneToMany('Order') 
    6868        is_addressable() 
    69      
     69 
    7070    class Order(Entity): 
    7171        order_num = Field(primary_key=True) 
     
    7373        person = ManyToOne('Person') 
    7474        is_addressable('address', uselist=False) 
    75      
     75 
    7676    home = Address(street='123 Elm St.', city='Spooksville') 
    7777    user = Person(name='Jane Doe') 
    7878    user.addresses.append(home) 
    79      
     79 
    8080    neworder = Order(item_count=4) 
    8181    neworder.address = home 
    8282    user.orders.append(neworder) 
    83      
     83 
    8484    # Queries using the added helpers 
    8585    Person.select_by_addresses(city='Cupertino') 
     
    131131 
    132132    class GenericAssoc(object): 
    133      
     133 
    134134        def __init__(self, tablename): 
    135135            self.type = tablename 
    136     
     136 
    137137    #TODO: inherit from entity builder 
    138138    class Associable(object): 
    139139        """An associable Elixir Statement object""" 
    140          
     140 
    141141        def __init__(self, entity, name=None, uselist=True, lazy=True): 
    142142            self.entity = entity 
    143143            self.lazy = lazy 
    144144            self.uselist = uselist 
    145              
     145 
    146146            if name is None: 
    147147                self.name = plural_name 
     
    150150 
    151151        def after_table(self): 
    152             col = sa.Column('%s_assoc_id' % interface_name, sa.Integer,  
     152            col = sa.Column('%s_assoc_id' % interface_name, sa.Integer, 
    153153                            sa.ForeignKey('%s.id' % able_name)) 
    154154            self.entity._descriptor.add_column(col) 
     
    162162                tablename =  "%s_to_%s" % (able_name, interface_name) 
    163163                association_to_table = sa.Table(tablename, metadata, 
    164                     sa.Column('assoc_id', sa.Integer,  
    165                               sa.ForeignKey(association_table.c.id,  
    166                                             ondelete="CASCADE"),  
     164                    sa.Column('assoc_id', sa.Integer, 
     165                              sa.ForeignKey(association_table.c.id, 
     166                                            ondelete="CASCADE"), 
    167167                              primary_key=True), 
    168168                    #FIXME: this assumes a single id col 
    169                     sa.Column('%s_id' % interface_name, sa.Integer,  
    170                               sa.ForeignKey(assoc_entity.table.c.id,  
    171                                             ondelete="RESTRICT"),  
     169                    sa.Column('%s_id' % interface_name, sa.Integer, 
     170                              sa.ForeignKey(assoc_entity.table.c.id, 
     171                                            ondelete="RESTRICT"), 
    172172                              primary_key=True), 
    173173                ) 
     
    186186                                       order_by=assoc_entity.mapper.order_by) 
    187187                }) 
    188          
     188 
    189189            entity = self.entity 
    190190            entity.mapper.add_property( 
    191                 attr_name,  
     191                attr_name, 
    192192                sa.orm.relation(GenericAssoc, lazy=self.lazy, 
    193193                                backref='_backref_%s' % entity.table.name) 
     
    197197                def get(self): 
    198198                    if getattr(self, attr_name) is None: 
    199                         setattr(self, attr_name,  
     199                        setattr(self, attr_name, 
    200200                                GenericAssoc(entity.table.name)) 
    201201                    return getattr(self, attr_name).targets 
     
    211211                def set(self, value): 
    212212                    if getattr(self, attr_name) is None: 
    213                         setattr(self, attr_name,  
     213                        setattr(self, attr_name, 
    214214                                GenericAssoc(entity.table.name)) 
    215215                    getattr(self, attr_name).targets = [value] 
    216216                setattr(entity, self.name, property(get, set)) 
    217217 
    218             # self.name is both set via mapper synonym and the python  
     218            # self.name is both set via mapper synonym and the python 
    219219            # property, but that's how synonym properties work. 
    220             # adding synonym property after "real" property otherwise it  
     220            # adding synonym property after "real" property otherwise it 
    221221            # breaks when using SQLAlchemy > 0.4.1 
    222222            entity.mapper.add_property(self.name, sa.orm.synonym(attr_name)) 
     
    227227                                .filter_by(**kwargs).all() 
    228228            setattr(entity, 'select_by_%s' % self.name, classmethod(select_by)) 
    229              
     229 
    230230            def select(cls, *args, **kwargs): 
    231231                return cls.query.join([attr_name, 'targets']) \ 
  • elixir/trunk/elixir/fields.py

    r347 r350  
    187187        self.column = Column(self.colname, self.type, 
    188188                             *self.args, **self.kwargs) 
    189         self.entity._descriptor.add_column(self.column) 
     189        self.add_table_column(self.column) 
    190190 
    191191    def create_properties(self): 
     
    196196            self.property = deferred(self.column, group=group) 
    197197        elif self.name != self.colname: 
    198             # if the property name is different from the column name, we need to 
    199             # add an explicit property (otherwise nothing is needed as it's done 
    200             # automatically by SA) 
     198            # if the property name is different from the column name, we need  
     199            # to add an explicit property (otherwise nothing is needed as it's 
     200            # done automatically by SA) 
    201201            self.property = self.column 
    202202 
    203203        if self.property: 
    204             self.entity._descriptor.add_property(self.name, self.property) 
     204            self.add_mapper_property(self.name, self.property) 
    205205 
    206206        if self.synonym: 
    207             self.entity._descriptor.add_property(self.synonym, 
    208                                                  synonym(self.name)) 
     207            self.add_mapper_property(self.synonym, synonym(self.name)) 
    209208 
    210209 
  • elixir/trunk/elixir/properties.py

    r348 r350  
    7777        pass 
    7878 
     79    # helper methods 
     80    def add_mapper_property(self, name, prop): 
     81        self.entity._descriptor.add_property(name, prop) 
     82 
     83    def add_table_column(self, column): 
     84        self.entity._descriptor.add_column(column) 
     85 
    7986 
    8087class CounterMeta(type): 
     
    146153            prop_value = self.prop 
    147154        prop_value = self.evaluate_property(prop_value) 
    148         self.entity._descriptor.add_property(self.name, prop_value) 
     155        self.add_mapper_property(self.name, prop_value) 
    149156 
    150157    def evaluate_property(self, prop): 
  • elixir/trunk/elixir/relationships.py

    r347 r350  
    414414        kwargs.update(self.get_prop_kwargs()) 
    415415        self.property = relation(self.target, **kwargs) 
    416         self.entity._descriptor.add_property(self.name, self.property) 
     416        self.add_mapper_property(self.name, self.property) 
    417417 
    418418    def target(self): 
     
    571571                # Build the list of column "paths" the foreign key will 
    572572                # point to 
    573                 target_path = "%s.%s" % (target_desc.tablename, pk_col.key) 
    574                 schema = target_desc.table_options.get('schema', None) 
    575                 if schema is not None: 
    576                     target_path = "%s.%s" % (schema, target_path) 
    577                 fk_refcols.append(target_path) 
     573                fk_refcols.append("%s.%s" % \ 
     574                                  (target_desc.table_fullname, pk_col.key)) 
    578575 
    579576                # Build up the primary join. This is needed when you have 
     
    757754 
    758755            joins = (self.primaryjoin_clauses, self.secondaryjoin_clauses) 
    759             for num, desc, fk_name, m2m in ( 
     756            for num, desc, fk_name, rel in ( 
    760757                    (0, e1_desc, source_fk_name, self), 
    761758                    (1, e2_desc, target_fk_name, self.inverse)): 
     
    784781                    # Build the list of column "paths" the foreign key will 
    785782                    # point to 
    786                     target_path = "%s.%s" % (desc.tablename, pk_col.key) 
    787                     schema = desc.table_options.get('schema', None) 
    788                     if schema is not None: 
    789                         target_path = "%s.%s" % (schema, target_path) 
     783                    target_path = "%s.%s" % (desc.table_fullname, pk_col.key) 
    790784                    fk_refcols.append(target_path) 
    791785 
     
    794788                        joins[num].append(col == pk_col) 
    795789 
    796                 onupdate = m2m and m2m.onupdate 
    797                 ondelete = m2m and m2m.ondelete 
     790                onupdate = rel and rel.onupdate 
     791                ondelete = rel and rel.ondelete 
    798792 
    799793                constraints.append(