Changeset 14
- Timestamp:
- 02/01/07 20:56:24 (6 years ago)
- Location:
- supermodel/trunk/supermodel
- Files:
-
- 3 modified
-
entity.py (modified) (7 diffs)
-
options.py (modified) (1 diff)
-
relationships.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
supermodel/trunk/supermodel/entity.py
r9 r14 40 40 desc.setup_options() 41 41 42 # create table & assign mapper42 # create table & assign (empty) mapper 43 43 desc.setup() 44 44 … … 71 71 # setattr(self.module, entity.__name__, entity) 72 72 self.metadata = getattr(self.module, 'metadata', supermodel.metadata) 73 self.initialized = False74 73 self.autoload = None 75 74 self.auto_primarykey = True … … 101 100 and assign a mapper. Will be called when an instance of the 102 101 entity is created or a mapper is needed to access one or many 103 instances of the entity. 104 """ 105 106 if not self.primary_keys and self.auto_primarykey: 107 self.create_auto_primary_key() 108 109 if not self.entity.mapper: 110 self.setup_mapper() 111 102 instances of the entity. This *doesn't* initialize relations. 103 """ 104 105 self.setup_mapper() 106 107 # This marks all relations of the entity (or, at least those which 108 # have been added so far by statements) as being uninitialized 112 109 EntityDescriptor.uninitialized_rels.update( 113 110 self.relationships.values()) … … 115 112 def setup_mapper(self): 116 113 """ 117 Initializes and assign a mapper to the given entity,114 Initializes and assign an (empty!) mapper to the given entity, 118 115 which needs a table defined, so it calls setup_table. 119 116 """ … … 152 149 return 153 150 151 if not self.autoload: 152 if not self.primary_keys and self.auto_primarykey: 153 self.create_auto_primary_key() 154 154 155 # create list of columns and constraints 155 156 args = [field.column for field in self.fields.values()] \ … … 198 199 table.append_constraint(constraint) 199 200 200 def get_inverse_relation(self, rel ):201 def get_inverse_relation(self, rel, reverse=False): 201 202 """Return the inverse relation of rel, if any, None otherwise.""" 202 203 … … 214 215 % (rel.name, rel.entity.__name__) 215 216 ) 217 # When a matching inverse is found, we check that it has only 218 # one relation matching as its own inverse. We don't need the result 219 # of the method though. But we do need to be careful not to start an 220 # infinite recursive loop. 221 if matching_rel and not reverse: 222 rel.entity._descriptor.get_inverse_relation(matching_rel, True) 223 216 224 return matching_rel 225 217 226 218 227 @classmethod -
supermodel/trunk/supermodel/options.py
r4 r14 25 25 tablename: Specify a custom tablename 26 26 shortnames: Usually tablenames include the full 27 module-path to the entity, but separated28 by underscores ("_"), eg.:29 "project1_model_ MyEntity", for an entity named27 module-path to the entity, but lower-cased and 28 separated by underscores ("_"), eg.: 29 "project1_model_myentity", for an entity named 30 30 "MyEntity" in the module "project1.model". 31 If shortnames is true, the tablename will just 32 be the entity's classname, ie. "MyEntity". 31 If shortnames is True, the tablename will just 32 be the entity's classname lower-cased, 33 ie. "myentity". 33 34 auto_primarykey: If given as string, it will represent the 34 35 auto-primary-key's column name -
supermodel/trunk/supermodel/relationships.py
r9 r14 21 21 self._target = None 22 22 23 self.initialized = False24 self.secondary = None25 23 self._inverse = None 26 self.foreign_key = None27 28 24 self.foreign_key = kwargs.pop('foreign_key', None) 29 25 if self.foreign_key and not isinstance(self.foreign_key, list): 30 26 self.foreign_key = [self.foreign_key] 31 27 28 #CHECKME: is it of any use to store it somewhere? 32 29 self.property = None # sqlalchemy property 33 30 … … 236 233 237 234 class HasAndBelongsToMany(Relationship): 238 239 235 def __init__(self, entity, name, *args, **kwargs): 240 self.tablename = kwargs.pop('tablename', None) 236 self.user_tablename = kwargs.pop('tablename', None) 237 self.secondary = None 241 238 super(HasAndBelongsToMany, self).__init__(entity, name, *args, **kwargs) 242 239 … … 294 291 name=desc.tablename + '_fk', 295 292 use_alter=True)) 296 297 # In the table name code below, we use the name of the relation 298 # for the first entity (instead of the name of its primary key), 299 # so that we can have two many-to-many relations between the same 300 # objects without having a table name collision. On the other hand, 301 # we use the name of the primary key for the second entity 302 # (instead of the inverse relation's name) so that a many-to-many 303 # relation can be defined without inverse. 304 if not self.tablename: 305 e2_pk_name = '_'.join([key.column.name for key in 306 e2_desc.primary_keys]) 307 tablename = "%s_%s__%s_%s" % (e1_desc.tablename, self.name, 308 e2_desc.tablename, e2_pk_name) 293 294 if self.user_tablename: 295 tablename = self.user_tablename 309 296 else: 310 tablename = self.tablename 297 # We use the name of the relation for the first entity 298 # (instead of the name of its primary key), so that we can 299 # have two many-to-many relations between the same objects 300 # without having a table name collision. 301 source_part = "%s_%s" % (e1_desc.tablename, self.name) 302 303 # And we use the name of the primary key for the second entity 304 # when there is no inverse, so that a many-to-many relation 305 # can be defined without an inverse. 306 if self.inverse: 307 e2_name = self.inverse.name 308 else: 309 e2_name = '_'.join([key.column.name for key in 310 e2_desc.primary_keys]) 311 target_part = "%s_%s" % (e2_desc.tablename, e2_name) 312 313 # we need to keep the table name consistent (independant of 314 # whether this relation or its inverse is setup first) 315 if self.inverse and e1_desc.tablename < e2_desc.tablename: 316 tablename = "%s__%s" % (target_part, source_part) 317 else: 318 tablename = "%s__%s" % (source_part, target_part) 311 319 312 320 args = columns + constraints … … 320 328 kwargs['secondaryjoin'] = and_(*self.secondaryjoin_clauses) 321 329 322 m = self.entity.mapper 323 #FIXME: using post_update systematically is *really* not good 324 m.add_property(self.name, 325 relation(self.target, secondary=self.secondary, 326 uselist=True, **kwargs)) 327 330 self.property = relation(self.target, secondary=self.secondary, 331 uselist=True, **kwargs) 332 self.entity.mapper.add_property(self.name, self.property) 333 334 def is_inverse(self, other): 335 return super(HasAndBelongsToMany, self).is_inverse(other) and \ 336 (self.user_tablename == other.user_tablename or 337 (not self.user_tablename and not other.user_tablename)) 328 338 329 339 belongs_to = Statement(BelongsTo)
