On Jul 28, 2014, at 5:54 PM, Luca Clementi <luca.cleme...@gmail.com> wrote:

> Hi,
> I am trying to use my ORM mapping definitions to create my database
> schema and I'm looking at the defaults values.
> 
> Apparently when I defined a column, if I use default_server='value' it
> will get into the DDL for my DB, but then my object instances will not
> have a default value when I instantiate them.
> 
> While if I use the default=value it will be used in my instances to
> set a default but it will not be used when creating the DDL for my DB.
> 
> So basically to define a default I have to use both:
> default=1024, default_server='1024'
> or
> default=None, default_server=text('NULL')
> 
> Is this correct or I am missing something?
> 
> Why for simple values (like number) default is not enough?

the "default" that you put on a Column() object isn't copied into your ORM 
object until it is flushed.  If the column instead specifies a server_default, 
the ORM object will also be able to see this value after the flush(), it just 
requires that the database either emit a SELECT for this value, or it can get 
it via RETURNING, but it will do this automatically.

In either case, post-flush you should see the value on your object, pre-flush 
you will not.      There should never be a need to have both "default" and 
"server_default".

A simple case we can see the "post-select":

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'

    id = Column(Integer, primary_key=True)
    data = Column(Integer, server_default="10")

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

sess = Session(e)

a1 = A()
sess.add(a1)
sess.flush()

assert a1.data == 10


then, to get the server_default via RETURNING, we can use a supporting DB like 
Postgresql and add "eager_defaults":

class A(Base):
    __tablename__ = 'a'
    __mapper_args__ = {'eager_defaults': True}
    id = Column(Integer, primary_key=True)
    data = Column(Integer, server_default="10")

# ...
e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)


we see in the SQL log:

INSERT INTO a DEFAULT VALUES RETURNING a.id, a.data


now as far as the feature of having the value present *before* a flush, that 
isn't available automatically right now.  you can, as i just told someone else 
earlier today (see previous email thread), use an init() event and iterate 
through the Table metadata to find these defaults and set them up.   But 
SQLAlchemy right now doesn't really want to be concerned with parsing what you 
put in server_default; if you say "server_default='3'", it's just the number 
three, but even to determine that it's a constant and not some SQL expression 
we can't evaluate, requires parsing and guessing, and we'd rather not get into 
that.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to