librelist archives

« back to archive

Common field to several models (SQLAlchemy extension)

Common field to several models (SQLAlchemy extension)

From:
Carlos A. Carnero Delgado
Date:
2012-08-23 @ 19:00
Hi,

I'm building a really simple web services application that serializes
to/from JSON; so simple in fact that I'm only needing four models. I
was using SQLAlchemy directly, but I just began using the SQLAlchemy
extension which should ease things a little, or at least, cut down on
boilerplate code (already has).

There is a requirement that all the four models have a random UUID
string as their identifier, which should be generated on save. Since
this is a common feature, I was wondering if the following is correct

  application = ...
  application.config['SQLALCHEMY_DATABASE_URI'] = ...
  database = SQLAlchemy(application)

  database.Model.uuid = staticmethod(lambda: unicode(uuid4()))
  database.Model.id = database.Column(
      'ID', database.String(36), default=database.Model.uuid,
      primary_key=True
  )

I'm guessing then that every model that I subclass from database.Model
will have the id field. Is this a pythonic approach? Should I create
an explicit intermediate Model subclass instead?

TIA,
Carlos.

Re: [flask] Common field to several models (SQLAlchemy extension)

From:
Audrius Kažukauskas
Date:
2012-08-24 @ 14:55
On Thu, 2012-08-23 at 15:00:27 -0400, Carlos A. Carnero Delgado wrote:
> There is a requirement that all the four models have a random UUID
> string as their identifier, which should be generated on save. Since
> this is a common feature, I was wondering if the following is correct
> 
>   application = ...
>   application.config['SQLALCHEMY_DATABASE_URI'] = ...
>   database = SQLAlchemy(application)
> 
>   database.Model.uuid = staticmethod(lambda: unicode(uuid4()))
>   database.Model.id = database.Column(
>       'ID', database.String(36), default=database.Model.uuid,
>       primary_key=True
>   )
> 
> I'm guessing then that every model that I subclass from database.Model
> will have the id field. Is this a pythonic approach? Should I create
> an explicit intermediate Model subclass instead?

I would subclass database.Model or even use a mixin class together with
it instead of modifying database.Model directly:

  class HasUUID(object):
      id = database.Column('ID', database.String(36),
                           default=lambda: unicode(uuid4()),
                           primary_key=True)

  class MyModel(HasUUID, database.Model):
      ...

Oh, and if you are going to use PostgreSQL, consider using its native
UUID type (available as sqlalchemy.dialects.postgresql.UUID), this will
save you some space, especially if your DB is going to grow
significantly over time.

-- 
Audrius Kažukauskas
http://neutrino.lt/

Re: [flask] Common field to several models (SQLAlchemy extension)

From:
Carlos A. Carnero Delgado
Date:
2012-08-25 @ 14:15
Hi,

On Fri, Aug 24, 2012 at 10:55 AM, Audrius Kažukauskas
<audrius@neutrino.lt> wrote:
>   class HasUUID(object):
>       id = database.Column('ID', database.String(36),
>                            default=lambda: unicode(uuid4()),
>                            primary_key=True)
>
>   class MyModel(HasUUID, database.Model):
>       ...

that, not only worked but is really nice to read.

Thanks a lot, Audrius (and Lyndsy too).

Re: [flask] Common field to several models (SQLAlchemy extension)

From:
Lyndsy Simon
Date:
2012-08-24 @ 15:47
I agree - if you look at just your models, if you modify the base Model
class it isn't clear where the uuid is coming from.

Doing it as a mixin makes it clear you have some shared behavior that isn't
part of the default Model class. Explicit is better than implicit.

It also makes it much easier to later add a model that doesn't have a uuid
if need be.

Generally speaking, modifying base classes from a library is bad form.
On Aug 24, 2012 10:09 AM, "Audrius Kažukauskas" <audrius@neutrino.lt> wrote:

> On Thu, 2012-08-23 at 15:00:27 -0400, Carlos A. Carnero Delgado wrote:
> > There is a requirement that all the four models have a random UUID
> > string as their identifier, which should be generated on save. Since
> > this is a common feature, I was wondering if the following is correct
> >
> >   application = ...
> >   application.config['SQLALCHEMY_DATABASE_URI'] = ...
> >   database = SQLAlchemy(application)
> >
> >   database.Model.uuid = staticmethod(lambda: unicode(uuid4()))
> >   database.Model.id = database.Column(
> >       'ID', database.String(36), default=database.Model.uuid,
> >       primary_key=True
> >   )
> >
> > I'm guessing then that every model that I subclass from database.Model
> > will have the id field. Is this a pythonic approach? Should I create
> > an explicit intermediate Model subclass instead?
>
> I would subclass database.Model or even use a mixin class together with
> it instead of modifying database.Model directly:
>
>   class HasUUID(object):
>       id = database.Column('ID', database.String(36),
>                            default=lambda: unicode(uuid4()),
>                            primary_key=True)
>
>   class MyModel(HasUUID, database.Model):
>       ...
>
> Oh, and if you are going to use PostgreSQL, consider using its native
> UUID type (available as sqlalchemy.dialects.postgresql.UUID), this will
> save you some space, especially if your DB is going to grow
> significantly over time.
>
> --
> Audrius Kažukauskas
> http://neutrino.lt/
>