On Mar 12, 2012, at 2:06 PM, Paddy Mullen wrote:

> I am trying to create a column that stores sha1sums of content, and
> allows easy programatic access of that content.  I would like my table
> definition to look like this
> 
> class Picture(Base):
>    content = sa.Column('content_sha1sum', DataColumn(se))
> 
> I would like to be able to create instances of pictures like this
> 
> p = Picture()
> p.content(binary_image_string)
> 
> I only want to save the sha1sum to the database, DataColumn takes care
> of computing the sha1sum, and actually saving the content to s3 or the
> filesystem.  I also want DataColumn to be a deferred column, I can do
> that with deferred
> 
> All good so far.
> 
> What I can't do, or can't do cleanly is figure out how to access the
> sha1sum behind content
> 
> p = s.query(Picture).all().first()
> 
> p.content_sha1sum
> p.content_direct_url
> 
> Where direct_url is a function of the sha1sum.  The problem with a
> custom column is, I can't make sha1sum loading eager and the call to
> s3/filesystem lazy, this means that every re-hydration of a Picture
> requires a read from the filesystem.
> 
> There are a couple of ways that I could go.  First would be to store
> the sha1sum directly as a regular String column, and create properties
> of names "content" and "content_direct_url".  Another method would be
> to use a mixin, but that is a bit ugly.
> 
> What I really want is a way to add all 3 properties with a single
> line.  I'm willing to modify DeclarativeMeta .

So really the problem here is not the mechanics of things, you just want a very 
particular way of declaring it in your model.

I'm a strong proponent of mixins, but I suppose here the "ugly" part is that 
the mixin doesn't really grant a nice way of defining what the name of the 
column/attribute would be, and you just want a single attribute that becomes 
several.

So if you really want totally "magic" kinds of configuration, that is, you set 
up just one attribute on the class that magically creates two others, the 
straight path to this, without having to hack into metaclasses, is to use 
events.   The blog post at 
http://techspot.zzzeek.org/2011/05/17/magic-a-new-orm/ illustrates a technique 
for doing this.   Using the "mapper_configured" event you receive an event 
whenever a mapper is finished initializing itself.  At that point you can scan 
through the class and/or mapping and apply any additional things you want to 
apply.    

Another path is to override __mapper_cls__, which is a way of receiving a hook 
as soon as declarative sets up the mapping for the class.   An example of using 
this method is in the distro in examples/declarative_reflection/.   You'd use 
similar techniques, and at that stage you can also augment what gets sent to 
mapper() and add columns directly on the Table.   The advantage to 
__mapper_cls__ is that you get to set up the class early, while the advantage 
to the mapper_configured event is that the approach remains discrete and 
separate from everything else going on, and also has access to the full 
configuration of other mappers.



-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" 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/sqlalchemy?hl=en.

Reply via email to