Re: [sqlalchemy] Declarative Field Type 'Alias'
On 08/05/2011 10:46 PM, Mark Erbaugh wrote: This is more of a Python issue than a SA issue, but I had trouble getting this to work. I did, but the code seems a little awkard to mesigh. In addition to the requirements already, I also wanted toe default value to be a class level 'constant'. The problem, as I see it, is that since the class definition isn't complete, it's namespace isn't avaialble. Since the default value 'constant' is a class data member, it would make sense if the function were a @classmethod, but I couldn't get python to accept: class Table(Base): ... DEFAULT = 2 @classmethod def CustomColumn(cls): return Column(Integer, default=DEFAULT) that should be cls.DEFAULT ... field1 = CustomColumn() Python complained 'classmethod object is not callable' on the last line above. You can only call a class method on a class. In this case that would be Table.CustomColumn(). However since the Table class is not available at this point you can't do that. You can do this sort of thing with metaclasses, but I would not recommend going down that paht. What I finally ended up with that works is: class Table(Base): ... DEFAULT = 2 def CustomColumn(default=DEFAULT): return Column(Integer, default=default) ... field1 = CustomColumn() That looks like a pretty good solution. Wichert. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
[sqlalchemy] Declarative Field Type 'Alias'
In my application, some tables have several fields that need to have the same type and default value, i.e.: field1 = Column(Integer, default=2) field2 = Column(Integer, default=2) ... Is there some way to refactor the Common(Integer, default=2), short of creating a custom column type? I could see the possibility that in a future version of the application, I would want to globally change the column type or default value for all these fields at once. So far, I've come up with creating a function that returns the column. def common_field(): return Column(Integer, default=2) field1 = common_field() field2 = common_field() Is there a better way? Mark -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] Declarative Field Type 'Alias'
On Aug 5, 2011, at 1:36 PM, Mark Erbaugh wrote: In my application, some tables have several fields that need to have the same type and default value, i.e.: field1 = Column(Integer, default=2) field2 = Column(Integer, default=2) ... Is there some way to refactor the Common(Integer, default=2), short of creating a custom column type? I could see the possibility that in a future version of the application, I would want to globally change the column type or default value for all these fields at once. So far, I've come up with creating a function that returns the column. def common_field(): return Column(Integer, default=2) field1 = common_field() field2 = common_field() Is there a better way? What's the issue with using a function to generate a Column of a certain pre-determined configuration (what are functions in a procedural language for if not this) ? FTR I use functions to generate prefab Column objects all the time and they are also intrinsic to the example application I've created for the SQLAlchemy book project (which is on a somewhat indefinite schedule at the moment, unless someone wants to help write) . If the issue is that these tables need to have a certain series of completely fixed columns, i.e. same names and everything, here are a series of approaches for that depending on what you're doing. 1. Regular declarative ? Use declarative mixins. class MyMixin(object): updated_at = Column(DateTime, onupdate=datetime.utcnow) 2. if I am using Table metadata directly (i.e. with declarative, __table__ = Table()), I'd typically use a function around Table: def standard_table(*args, **kw): return Table(*(args + [_standard_table_cols()]), **kw) 3. For all tables, use events: @event.listens_for(Table, after_parent_attach) def _table_standard_cols(table, metadata): table.append_column(Column(DateTime, onupdate=datetime.utcnow)) 4. Certain classes of tables...there's probably a nice way to combine the table events with a subset of table classes. (tries...success !) from sqlalchemy import * from sqlalchemy import event from sqlalchemy.schema import CreateTable import datetime class TableWithUTC(Table): pass @event.listens_for(TableWithUTC, after_parent_attach) def _add_col(table, metadata): table.append_column(Column('updated_at', DateTime, onupdate=datetime.datetime.utcnow)) m = MetaData() t1 = Table('t1', m, Column('x', Integer)) t2 = TableWithUTC('t2', m, Column('x', Integer)) t3 = TableWithUTC('t3', m, Column('x', Integer)) t4 = Table('t4', m, Column('x', Integer)) assert t2.c.updated_at is not None assert 'updated_at' not in t4.c for name in 't1', 't2', 't3', 't4': print CreateTable(m.tables[name]) -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] Declarative Field Type 'Alias'
On Aug 5, 2011, at 3:51 PM, Michael Bayer wrote: On Aug 5, 2011, at 1:36 PM, Mark Erbaugh wrote: In my application, some tables have several fields that need to have the same type and default value, i.e.: field1 = Column(Integer, default=2) field2 = Column(Integer, default=2) ... Is there some way to refactor the Common(Integer, default=2), short of creating a custom column type? I could see the possibility that in a future version of the application, I would want to globally change the column type or default value for all these fields at once. So far, I've come up with creating a function that returns the column. def common_field(): return Column(Integer, default=2) field1 = common_field() field2 = common_field() Is there a better way? What's the issue with using a function to generate a Column of a certain pre-determined configuration (what are functions in a procedural language for if not this) ? No issue at all. I just wanted to make sure I was doing it 'the right way'. I just noticed that in several places, SA will let you pass in a class or an instance of a class and figures out what to do with it. I thought that something like that might be working here. Actually, there is a small issue with using a function: Where should the function live? Obviously for some schema, this field type is used in multiple tables and belongs in a global namespace, but for others (as in my application), the field type is unique to an individual table. It would be nice if the function could live in the class's namespace. This is more of a Python issue than a SA issue, but I had trouble getting this to work. I did, but the code seems a little awkard to me sigh. In addition to the requirements already, I also wanted toe default value to be a class level 'constant'. The problem, as I see it, is that since the class definition isn't complete, it's namespace isn't avaialble. Since the default value 'constant' is a class data member, it would make sense if the function were a @classmethod, but I couldn't get python to accept: class Table(Base): ... DEFAULT = 2 @classmethod def CustomColumn(cls): return Column(Integer, default=DEFAULT) ... field1 = CustomColumn() Python complained 'classmethod object is not callable' on the last line above. Next I tried changing that line to: field1 = Table.CustomColumn() Now Python complained 'Table' is not defined If I leave the @classmethod decroator off, I couldn't figure out how to reference the class level data DEFAULT. Python complained on the return Column(... line ' global name DEFAULT is not defined. What I finally ended up with that works is: class Table(Base): ... DEFAULT = 2 def CustomColumn(default=DEFAULT): return Column(Integer, default=default) ... field1 = CustomColumn() Mark -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.