I need help with Enum field type as it is not accepted by Swagger and I am getting error message **TypeError: Object or Type eGameLevel is not JSON serializable**
. Below is the complete set of code for table. Complete set of code with DB table and sqlalchemy settings is provided. I already tried it with Marshmallow-Enum Flask package and it didn’t worked. Looking for kind help with some explanation about the solution so I can learn it well. :-)
I am using MySQL with the Flask. In Postgres its pretty easy to manage all the choice fields. All I need is a working example or a link to repository where MySQL choice fields are showing up in swagger drop down.
My Model:
import enum from app import db from typing import List class eGameLevel(enum.Enum): BEGINNER = 'Beginner' ADVANCED = 'Advanced' class Game(Base): __tablename__ = 'game_stage' id = db.Column(db.Integer(), primary_key=True) game_level= db.Column(db.Enum(eGameLevel), default=eGameLevel.BEGINNER, nullable=False) user_id = db.Column(db.Integer(), db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False) user = db.relationship('User', backref='game__level_submissions', lazy=True) def __init__(self, game_level, user_id): self.game_level = game_level self.user_id = user_id def __repr__(self): return 'Game(game_level%s, ' 'user_id%s'%(self.game_level, self.user_id) def json(self): return {'game_level':self.game_level, 'user_id':self.user_id} @classmethod def by_game_id(cls, _id): return cls.query.filter_by(id=_id) @classmethod def find_by_game_level(cls, game_level): return cls.query.filter_by(game_level=game_level) @classmethod def by_user_id(cls, _user_id): return cls.query.filter_by(user_id=_user_id) @classmethod def find_all(cls) -> List["Game"]: return cls.query.all() def save_to_db(self) -> None: db.session.add(self) db.session.commit() def delete_from_db(self) -> None: db.session.delete(self) db.session.commit()
My Schema
from app import ma from app.models import Gode class GameSchema(ma.SQLAlchemyAutoSchema): game = ma.Nested('GameSchema', many=True) class Meta: model = Game load_instance = True include_fk= True
My Resources:
from flask_restx import Resource, fields, Namespace from app.models import Game from app import db from app.schemas import GameSchema GAME_REQUEST_NOT_FOUND = "Game request not found." GAME_REQUEST_ALREADY_EXSISTS = "Game request '{}' Already exists." game_ns = Namespace('Game', description='Available Game Requests') games_ns = Namespace('Game Requests', description='All Games Requests') game_schema = GameSchema() games_list_schema = GameSchema(many=True) gamerequest = game_ns.model('Game', { 'game_level': fields.String('Game Level: Must be one of: BEGINNER, ADVANCED.'), 'user_id': fields.Integer, }) class GameRequestsListAPI(Resource): @games_ns.doc('Get all Game requests.') def get(self): return games_list_schema.dump(Game.find_all()), 200 @games_ns.expect(gamerequest) @games_ns.doc("Create a Game request.") def post(self): game_json = request.get_json() game_data = game_schema.load(game_json) game_data.save_to_db() return game_schema.dump(game_data), 201
Advertisement
Answer
Instead of trying to manage Enum fields for MySQL schema I suggest to use another table with backref to your eGameLevel. You can get rid of this whole fuss and also in future if you needed to add another option in your choice field you won’t have to hardcode it.
Simply create a main table as Game and sub table as eGameLevel (with only one string field). You will be able to access choices from your Game table.
Whenever I get stuck I go to basics as mentioned in here.