Flask gets the user role based on token and returns an error

Database Design:

db = SQLAlchemy()

roles_users = db.Table(
    "roles_users",
    db.Column("user_id",db.Integer(),db.ForeignKey("users.id")),
    db.Column("role_id",db.Integer(),db.ForeignKey("roles.id"))
)

class Role(db.Model,RoleMixin):
    """"""
    __tablename__ = "roles"
 
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    description = db.Column(db.String(255))
 
    def __init__(self):
        self.name = name
   

    def __repr__(self):
         return "%r" % self.name
  

class User(db.Model, UserMixin):   
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), unique=True)
    email = db.Column(db.String(64), unique=True)
    password = db.Column(db.Text,nullable=False)
    last_login_at = db.Column(db.DateTime, default=datetime.utcnow)
    current_login_at = db.Column(db.DateTime)
    last_login_ip = db.Column(db.String(100))
    current_login_ip = db.Column(db.String(100))
    login_count = db.Column(db.Integer)
    active = db.Column(db.Boolean())
    status = db.Column(db.String(64))
    confirmed_at = db.Column(db.DateTime, default=datetime.now())
    roles = db.relationship("Role",secondary="roles_users",backref=db.backref("users",lazy="dynamic"))

    def __init__(self, name=None, email=None):
        self.name = name
        self.email = email
        self.roles = roles 
   
    def to_json(self):       
        
        json_data = {
            "id": self.id,
            "name": self.name,
            "roles":self.roles,
            "email": self.email,
            "status": self.status,
            "active": self.active, 
            "confirmed_at": self.confirmed_at, 
            "current_login_at": self.current_login_at, 
            "current_login_ip": self.current_login_ip,
            "last_login_at": self.last_login_at, 
            "last_login_ip": self.last_login_ip, 
            "login_count": self.login_count,  
            "status": self.status
        }

        return json_data


    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config["SECRET_KEY"])
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None -sharp valid token, but expired
        except BadSignature:
            return None -sharp invalid token
        user = User.query.get(data["id"])        
        return user
        
 
 :
@user.route("/info", methods=["GET", "POST"])
-sharp @login_required 
def userinfo():
   
    token=request.args.get("token")       
        
    if not token:
        return jsonify({"status":201,"state":0,"msg":""})   
        
    else:
        data = User.verify_auth_token(token)        
        return jsonify({"status":200,"state":1,"msg":"","data": data.to_json()})
        

error: TypeError: Object of type Role is not JSON serializable
Why? Has anyone met?

Jul.06,2022

because User.roles is relationship , not a field.
I guess you don't want to return User.roles . If so, just remove 'roles':self.roles, from User.to_json () .
if you still want to return User.roles , you can do this:

class Role(db.Model,RoleMixin):
    ...
    def to_json(self):
        json_data = {
            'id': self.id,
            'name': self.name,
            'description': self.description
        }
        return json_data


class User(db.Model, UserMixin):
    ...
    def to_json(self):
        json_data = {
            ...
            roles = [role.to_json() for role in self.roles]
        }

returns:

{
    'id': 1,
    ...
    'roles': [
        {'id': 1, name: 'admin', description: 'admin'},
        {'id': 1, name: 'user', description: 'user'}
        ...
     ]
}

of course, you can also define it as 'roles': [' admin', 'user'] . That's the way of thinking.

Menu