0

I'm using SQLAlchemy with the below User model to track users on my site. I'm trying to get the __init__ method to populate all of the fields in the class instance once it's passed a valid user id, but it doesn't work like it's supposed to.

Here's my code:

class User(db.Model):
    # Fields
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    email = db.Column(db.String(255), index=True)

    # Methods
    def __init__(self, id):
        # Populate the fields
        u = User.query.filter_by(id=id).first()

        # Fill in the name, email fields from the result
        self = u # <-- Not working as expected
    # ...

The problem is that the attributes are not getting populated.

u = User(1)
u.id, u.name, u.email # <-- Output: None

How can I auto-populate all the class attributes from the user id without having to set them one by one?

Note: I've removed the validation bits from the above code to avoid clutter Note2: I'm a beginner in SQLAlchemy, and just recently started using Python.

3
  • 2
    Normally in SQLAlchemy, the constructor is used to create a new object, for example to insert into the database, not to load one from the database. Do you have a particular need to do things differently? If you're just looking for a convenient place to define a lookup function, see @Oleh's answer. Commented Jun 22, 2014 at 15:36
  • 2
    Maybe I should go further and say that in Python in general, a constructor is used for creating a new instance, not for looking up an existing one. Why use a constructor for looking up when you can write functions that are not methods on an already existing instance? (Normal functions, classmethods, staticmethods) Commented Jun 22, 2014 at 15:52
  • @DanGetz thanks Dan! So I just need to remove it from the constructor, and move it to a "normal" function. That makes perfect sense Commented Jun 22, 2014 at 16:06

1 Answer 1

1

For this particular case you can use get which gets a row by its primary key:

u = User.get(1)
u.id, u.name, u.email

The problem with your code is that you're trying to use a bound method, even worse, the constructor (in which assigning to self does nothing at all) to get an existing, completely different instance.

I'll just show a reimplementation of the get method so you can reuse it for other cases.

class User(db.Model):
    # ...

    @classmethod
    def get_by_id(cls, id):
        return cls.query.filter_by(id=id).one()


u = User.get_by_id(1)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank Oleh. I'm still unclear on how the model gets updated from within the same class?
Nothing gets updated, thats the whole point. Read on classmethods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.