Flask SQLAlchemy: How to find the primary key value before adding a new object to the session?

I'm using b64encode to create a unique reference string from the primary key in each row in the table. This is my model in Flask SQLAlchemy:

class Groups(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    ref_id = db.Column(db.String(20), index = True)

    def __init__(self):
        self.ref_id = id_encode(self.id)

However, the self.id passed into the id_encode() function has a "None" value instead of the primary key's value. From what I can see, it's only possible to get the new primary key value after committing the session, or by using the flush() method.

Here's the definition for id_encode():

def id_encode(num):
        bts = base64.b64encode(bytes(str(num), 'utf-8'))
        print(num)
        return bts.decode()

If there any way to get this to work, or what's a better (but simple) way to do unique reference ID generation? I just don't want the average user to be able to navigate to other groups by entering a numeric ID.

1 answer

  • answered 2020-07-05 09:24 mmi-coding

    What you can do is replace the « __init __ » with a class function.

    so instead of :

    class Groups(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    ref_id = db.Column(db.String(20), index = True)
    
    def __init__(self):
        self.ref_id = id_encode(self.id)
    

    You should try :

    class Groups(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    ref_id = db.Column(db.String(20), index = True)
    
    def generate_id(self):
        self.ref_id = base64.b64encode(bytes(str(self.id), 'utf-8'))
    

    Then when you create a new group object, just remember to use the function before committing.

    group = Groups(id=xxx, arg2=xxx, arg3=xxx etc) 
    # omit "id" if you set it to autoincrement
    group.generate_id()
    db.session.commit()