Hướng dẫn init python not working

This is some really simple code I am using with sqlalchemy and I am missing something basic here about how classes work.

class Game[Base]:
    __tablename__ = "games"

    id = Column[Integer, primary_key=True]
    a_name = Column[String]

    def __init__[self, **kwargs]:
        for k, v in kwargs.iteritems[]:
             setattr[self, k, v]
        print 'hi'
        self.away_dictionary =  {'name': self.a_name}

    @hybrid_property
    def stuff[self]:
        return self.away_dictionary

The following query works:

session.query[Game].first[].a_name

but the following query returns an error:

session.query[Game].first[].stuff
'Game' object has no attribute 'away_dictionary'

I also have an even more basic problem, when I query the Game class it doesn't print out 'hi'. So could someone please explain why 'hi' isn't printed out everytime I use a Game instance? And the second question is how can I build and access the away_dictionary I want to have for each instance of this class?

asked Jun 23, 2013 at 0:22

appleLoverappleLover

13.8k8 gold badges32 silver badges50 bronze badges

6

You're not creating a Game instance in your queries above, you only pass the Game class object. Hence the init[] constructor is never called. If you need a Game instance for query, you need this: session.query[Game[]].first[].stuff.

answered Jun 23, 2013 at 0:42

4

Ah ha. I was just about to point out that it's bizarre that stuff isn't getting found, and I would expect away_dictionary not to be found instead... and you edited your post and changed the error message that you're quoting. It is indeed away_dictionary that isn't getting found, because it's normally created in your class's __init__[] method and __init__[] isn't getting called.

Normally, __init__[] would be called when you create an instance, but when you use the class in SQLAlchemy's queries, it's skipping the __init__[] method. I suspect this is something to do with how SQLAlchemy's declarative_mapper works, but I'm rusty enough on SQLAlchemy that I don't know off the top of my head how to fix it. If I find out, I'll edit this answer later and tell you.

But for now, you should probably not rely on your __init__[] method getting called in your SQLAlchemy model objects [that is, anything derived from Base]. See if you can structure your code in some other way.

answered Jun 23, 2013 at 1:41

rmunnrmunn

33k9 gold badges70 silver badges103 bronze badges

thanks for the comments. is it just me or is sqlalchemy kind of confusing?

anyway, as people have pointed out above the __init__ method apparently is not called when you do a query.

The SQLAlchemy ORM does not call __init__ when recreating objects from database rows. The ORM’s process is somewhat akin to the Python standard library’s pickle module, invoking the low level __new__ method and then quietly restoring attributes directly on the instance rather than calling __init__.

the solution to this is to add the following code:

from sqlalchemy.orm import reconstructor
@reconstructor
awesome_true_init[self]:
    self.away_dictionary = {'hi': 'i work!!'}

this function will act like a real __init__ and get called whenever you create the object!!

answered Jun 23, 2013 at 3:40

appleLoverappleLover

13.8k8 gold badges32 silver badges50 bronze badges

2

The reason session.query[Game].first[].a_nameworks, but session.query[Game].first[].stuff doesn't is a simple syntactic issue. a_name is a variable, an attribute of the class Game, so you refer to it just by typing a_name. stuff, on the other hand, is a method of that class, so you need a pair of parentheses after it, even if, as in this case, there isn't anything inside them. So try using session.query[Game].first[].stuff[].

"hi" isn't being printed because init is only called when you create an object using that constructor, which query isn't doing.

answered Jun 23, 2013 at 0:47

1

Not the answer you're looking for? Browse other questions tagged python class sqlalchemy or ask your own question.

Chủ Đề