Changeset 405

Show
Ignore:
Timestamp:
10/01/08 12:00:47 (5 years ago)
Author:
ged
Message:

Added a new "target_column" argument on ManyToOne relationships (ticket #26).
This is harder than I initially thought: it breaks if the target is declared
after the class holding the ManyToOne.

Location:
elixir/trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/CHANGES

    r404 r405  
    2020  ManyToMany table in a custom schema and not necessarily the same schema as 
    2121  the table of the "source" entity (patch from Diez B. Roggisch). 
     22- Added a new "target_column" argument on ManyToOne relationships (ticket #26). 
     23  TODOC 
    2224 
    2325Changes: 
  • elixir/trunk/elixir/relationships.py

    r401 r405  
    543543        self.primaryjoin_clauses = list() 
    544544 
     545        self.target_column = kwargs.pop('target_column', None) 
     546        if self.target_column is not None and \ 
     547           not isinstance(self.target_column, list): 
     548            self.target_column = [self.target_column] 
     549 
    545550        super(ManyToOne, self).__init__(*args, **kwargs) 
    546551 
     
    601606        # - the name of the target table 
    602607        target_desc = self.target._descriptor 
    603         #make sure the target has all its pk setup up 
     608        #make sure the target has all its pk set up 
     609#ca craint 
    604610        target_desc.create_pk_cols() 
    605611 
     
    625631            fk_colnames = list() 
    626632 
     633            if self.target_column is None: 
     634                target_columns = target_desc.primary_keys 
     635            else: 
     636                target_columns = [target_desc.get_column(col) 
     637                                  for col in self.target_column] 
     638 
     639            if not target_columns: 
     640                raise Exception("No primary key found in target table ('%s') " 
     641                                "for the '%s' relationship of the '%s' entity." 
     642                                % (self.target.tablename, self.name, 
     643                                   self.entity.__name__)) 
    627644            if self.colname and \ 
    628                len(self.colname) != len(target_desc.primary_keys): 
     645               len(self.colname) != len(target_columns): 
    629646                raise Exception( 
    630647                        "The number of column names provided in the colname " 
     
    635652                           self.target.__name__)) 
    636653 
    637             pks = target_desc.primary_keys 
    638             if not pks: 
    639                 raise Exception("No primary key found in target table ('%s') " 
    640                                 "for the '%s' relationship of the '%s' entity." 
    641                                 % (self.target.tablename, self.name, 
    642                                    self.entity.__name__)) 
    643  
    644             for key_num, pk_col in enumerate(pks): 
     654            for key_num, target_col in enumerate(target_columns): 
    645655                if self.field: 
    646656                    col = self.field[key_num].column 
     
    651661                        colname = options.FKCOL_NAMEFORMAT % \ 
    652662                                  {'relname': self.name, 
    653                                    'key': pk_col.key} 
     663                                   'key': target_col.key} 
    654664 
    655665                    # We can't add the column to the table directly as the 
    656666                    # table might not be created yet. 
    657                     col = Column(colname, pk_col.type, **self.column_kwargs) 
     667                    col = Column(colname, target_col.type, 
     668                                 **self.column_kwargs) 
    658669                    source_desc.add_column(col) 
    659670 
     
    680691                # point to 
    681692                fk_refcols.append("%s.%s" % \ 
    682                                   (target_desc.table_fullname, pk_col.key)) 
     693                                  (target_desc.table_fullname, target_col.key)) 
    683694 
    684695                # Build up the primary join. This is needed when you have 
    685696                # several belongs_to relationships between two objects 
    686                 self.primaryjoin_clauses.append(col == pk_col) 
     697                self.primaryjoin_clauses.append(col == target_col) 
    687698 
    688699            if 'name' not in self.constraint_kwargs: 
  • elixir/trunk/tests/test_m2o.py

    r380 r405  
    201201        assert a2 == b1.a_rel2 
    202202 
     203    def test_non_pk_target(self): 
     204        class A(Entity): 
     205            name = Field(String(60), unique=True) 
     206 
     207        class B(Entity): 
     208            name = Field(String(60)) 
     209            a = ManyToOne('A', target_column=['id', 'name']) 
     210# currently fails 
     211#            c = ManyToOne('C', target_column=['id', 'name']) 
     212 
     213#        class C(Entity): 
     214#            name = Field(String(60), unique=True) 
     215 
     216        setup_all(True) 
     217 
     218        b1 = B(name='b1', a=A(name='a1')) 
     219 
     220        session.commit() 
     221        session.clear() 
     222 
     223        b = B.query.one() 
     224 
     225        assert b.a.name == 'a1' 
     226 
    203227    def test_belongs_to_syntax(self): 
    204228        class Person(Entity):