On Tuesday 19 August 2008 09:12:43 Diez B. Roggisch wrote:
> Gaetan de Menten schrieb:
> > On Thu, Aug 14, 2008 at 5:12 PM, Diez B. Roggisch <[EMAIL PROTECTED]> wrote:
> >> I'm mapping an existing schema with elixir. One thing strikes me as odd
> >> is that local_side/remote_side on ManyToMany-relationships can only be
> >> specified (or are respected) when auto-mapping.
> >>
> >> I don't want to auto-map, my desire is to create full mappings so that I
> >> can from then on work with my elixir/sa-model.
> >>
> >> What's the rationale behind not respecting the parameters as
> >> column-names?
> >
> > What exactly do you want to achieve? Do you want to have custom names
> > in your ManyToMany table? If this is the case, isn't the column_format
> > argument enough for you?
>
> I didn't realize it. It might work as well - but certainly it's a bit
> more complicted :)
>
> > And, FWIW, there is no rationale. This is just the way it is because
> > nobody really needed custom names beyond what column_format allows you
> > do to yet. What you suggest is probably a more elegant solution to the
> > column_format argument.
> >
> > I was a bit uneasy to implement it because in the case where several
> > columns are needed on one (or both) side(s), the column names would
> > need to be given in the same order the primary key columns are
> > declared on the targeted entities. Now that I think of it, I don't
> > think it's an unreasonable requirement if it is clearly stated in the
> > documentation. A patch in that direction would be very likely to be
> > accepted ;-).
>
> I will see if I can do that :)
You find the patch attached. I created a test-case, which works flawlessly.
I also introduced a new keyword to ManyToMany - schema. This completes my
earlier patches as it allows to specify a schema in case of both entities
being part of different schemas and thus elixir can't decide which one to
use.
Diez
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"SQLElixir" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sqlelixir?hl=en
-~----------~----~----~----~------~----~------~--~---
Index: tests/test_m2m.py
===================================================================
--- tests/test_m2m.py (revision 396)
+++ tests/test_m2m.py (working copy)
@@ -9,6 +9,7 @@
class TestManyToMany(object):
def setup(self):
metadata.bind = 'sqlite:///'
+ metadata.bind.echo = True
def teardown(self):
cleanup_all(True)
@@ -169,3 +170,26 @@
assert b1 in a2.bs
assert not a3.bs
+ def test_local_and_remote_sidess(self):
+ class A(Entity):
+ key1 = Field(Integer, primary_key=True, autoincrement=False)
+ key2 = Field(String(40), primary_key=True)
+
+ bs_ = ManyToMany('B', local_side=['foo', 'bar'], remote_side="baz")
+
+ class B(Entity):
+ name = Field(String(60))
+ as_ = ManyToMany('A', remote_side=['foo', 'bar'], local_side="baz")
+
+ setup_all(True)
+
+ b1 = B(name='b1', as_=[A(key1=10, key2='a1')])
+
+ session.commit()
+ session.clear()
+
+ a = A.query.one()
+ b = B.query.one()
+
+ assert a in b.as_
+ assert b in a.bs_
Index: elixir/relationships.py
===================================================================
--- elixir/relationships.py (revision 396)
+++ elixir/relationships.py (working copy)
@@ -233,17 +233,20 @@
| | and when the table is autoloaded/reflected from the |
| | database. |
+--------------------+--------------------------------------------------------+
+| ``schema`` | Specify a custom schema for the intermediate table. |
+| | This can be used both when the tables needs to |
+| | be created and when the table is autoloaded/reflected |
+| | from the database. |
++--------------------+--------------------------------------------------------+
| ``remote_side`` | A column name or list of column names specifying |
| | which column(s) in the intermediary table are used |
| | for the "remote" part of a self-referential |
-| | relationship. This argument has an effect only when |
-| | your entities are autoloaded. |
+| | relationship. |
+--------------------+--------------------------------------------------------+
| ``local_side`` | A column name or list of column names specifying |
| | which column(s) in the intermediary table are used |
| | for the "local" part of a self-referential |
-| | relationship. This argument has an effect only when |
-| | your entities are autoloaded. |
+| | relationship. |
+--------------------+--------------------------------------------------------+
| ``order_by`` | Specify which field(s) should be used to sort the |
| | results given by accessing the relation field. You can |
@@ -748,6 +751,8 @@
self.column_format = kwargs.pop('column_format', options.M2MCOL_NAMEFORMAT)
self.secondary_table = kwargs.pop('table', None)
+ self.schema = kwargs.pop('schema', None)
+
self.primaryjoin_clauses = list()
self.secondaryjoin_clauses = list()
@@ -775,8 +780,13 @@
e1_schema = e1_desc.table_options.get('schema', None)
e2_schema = e2_desc.table_options.get('schema', None)
+
+ if self.schema is not None:
+ e1_schema = e2_schema = self.schema
+
assert e1_schema == e2_schema, \
- "Schema %r for entity %s differs from schema %r of entity %s" \
+ "Schema %r for entity %s differs from schema %r of entity %s." \
+ " Consider using the schema-parameter. "\
% (e1_schema, self.entity.__name__,
e2_schema, self.target.__name__)
@@ -827,13 +837,19 @@
constraints = list()
joins = (self.primaryjoin_clauses, self.secondaryjoin_clauses)
+ all_alternative_names = self.local_side, self.remote_side
+
for num, desc, fk_name, rel in (
(0, e1_desc, source_fk_name, self),
(1, e2_desc, target_fk_name, self.inverse)):
fk_colnames = list()
fk_refcols = list()
- for pk_col in desc.primary_keys:
+ alternative_names = all_alternative_names[num]
+ if isinstance(alternative_names, basestring):
+ alternative_names = [alternative_names]
+
+ for colnum, pk_col in enumerate(desc.primary_keys):
colname = self.column_format % \
{'tablename': desc.tablename,
'key': pk_col.key,
@@ -845,6 +861,9 @@
if self.entity is self.target:
colname += str(num + 1)
+ if alternative_names:
+ colname = alternative_names[colnum]
+
col = Column(colname, pk_col.type, primary_key=True)
columns.append(col)