3

I have the following table using Flask-SQLAlchemy:

class Posts(db.Model):    
    id = db.Column(db.Integer, primary_key=True)
    hashID = db.Column(db.String(6))
    post = db.Column(db.String(500))

    def __init__(self, post):
        self.hashID = hashid.encode(self.id)
        self.post = post

I want to create a hash using the autoincrementd ID field. I saw from other questions db.session.flush() can be used however this will not work since I would preferably get the ID from the inside the init.

The code above using self.id will not work since self.id returns a NoneType. Is there a way to get the ID that will be generated from inside the init? Thanks.

Pav Sidhu
  • 6,724
  • 18
  • 55
  • 110
  • You could add `self` to the session then flush but that's not a good idea. Instead of autoincrement you could come up with an ID generation scheme that allows the app to generate the ID instead of the DB. – univerio Jun 19 '16 at 15:41
  • @univerio Autoincrement within the app seems to complicated for a possible easier solution. – Pav Sidhu Jun 19 '16 at 15:47
  • I think the problem could be that you are overriding the *\__init\__* method of `db.Model` class. See: http://stackoverflow.com/questions/3279833/ – wgwz Jun 19 '16 at 16:04
  • And here's the *super* stuff, used to not override class methods: http://stackoverflow.com/questions/222877/. – wgwz Jun 19 '16 at 16:11
  • @PSidhu You don't have to use an incrementing integer for your ID. You can just as easily generate a UUID for your ID, or a custom ID generation scheme. – univerio Jun 20 '16 at 16:20
  • What's the status of this? – wgwz Jun 25 '16 at 03:06

1 Answers1

0

The documentation states that the self.id attribute is not set until the INSERT statement for that entity was issued. That means: unless you don't issue the INSERT statement in your __init__ method you can't get the auto incremented value there.

I don't know the functionality of hashid.encode but if that function has no side effects and is fast you won't need to store that field in the database at all. Instead you could add it with a property:

class Posts(...):
    self.id = ...
    # other columns here

    @property
    def hashID(self):
        return hashid.encode(self.id)

Then you only have to make sure that you don't access the hashID property before the entity was inserted into the database.

Note: this approach does not create a column hashID. If you need the hashID to be a column in the database you can flush the object first and then set the hashID like in OP's initial code. For the flushing take a look here.

Community
  • 1
  • 1
Wombatz
  • 4,958
  • 1
  • 26
  • 35
  • It seems dont persistent into DB. – Ryan Chou Oct 14 '16 at 11:33
  • @RyanChou you are right, the `hashID` is not stored in the DB which is fine in this case as it is only redundant information. – Wombatz Oct 14 '16 at 13:38
  • Yeah. Your answer could satisfy some cases which just only needed read-only. if we want to persist the `hashID`. We would try other ways to generate the Hash value based on the auto-increment ID. – Ryan Chou Oct 14 '16 at 15:39