How to generate crud methods for flask_restful resource classes

22 Views Asked by At

I'm trying to create some routing for my server and have found that I am repeating myself a lot when defining the methods for the classes that bridge my React requests and Flask SQLAlchemy models. Here is an example of some of the resources and the repetitive functions:

class Users(Resource):

    def get(self):
        #this might work to exclude passwords
        users = [user.to_dict(rules=("-password",)) for user in User.query.all()]
        return make_response(jsonify(users), 200)
    
    def post(self):
        data = request.get_json()

        try:
            new_user = User(
                name = data['name'],
                password = data['password']
            )
        except:
            error = {"errors": ["validation errors"]}
            return make_response(jsonify(error), 400)
        
        db.session.add(new_user)
        db.session.commit()

        return make_response(new_user.to_dict(), 201)
    
api.add_resource(Users, '/users')

class UserByID(Resource):
        
    def get(self, id):
        user = User.query.filter_by(id=id).first().to_dict()
        if user:
            return make_response(jsonify(user), 200)
        error = {"error": "User not found"}
        return make_response(jsonify(error), 404)

    def patch(self, id):
        user = User.query.filter_by(id=id).first()
        for attr in request.json:
            setattr(user, attr, request.json[attr])

        db.session.add(user)
        db.session.commit()

        return make_response(user.to_dict(), 202)

api.add_resource(UserByID, '/users/<int:id>')

class Prompts(Resource):

    def get(self):
        prompts = [prompt.to_dict() for prompt in Prompt.query.all()]
        return make_response(jsonify(prompts), 200)
    
    def post(self):
        data = request.get_json()

        try:
            new_prompt = Prompt(
                title = data['title'],
                content = data['content'],
                user_id = data['user_id']
            )
        except:
            error = {"errors": ["validation errors"]}
            return make_response(jsonify(error), 400)
        
        db.session.add(new_prompt)
        db.session.commit()

        return make_response(new_prompt.to_dict(), 201)
    
api.add_resource(Prompts, '/prompts')

class PromptByID(Resource):

    def get(self, id):
        prompt = Prompt.query.filter_by(id=id).first()
        return make_response(jsonify(prompt), 200)

    def patch(self, id):
        prompt = Prompt.query.filter_by(id=id).first()
        for attr in request.json:
            setattr(prompt, attr, request.json[attr])

        db.session.add(prompt)
        db.session.commit()

        return make_response(prompt.to_dict(), 202)

api.add_resource(PromptByID, '/prompts/<int:id>')

I was thinking of approaching the problem this way but haven't been able to get very far. The method will probably have to be supplied the name of the Model like User or Prompt. I also saw something about creating class decorators, but I'm not sure that would work since I imagine I'd have to use one decorator to make several methods.

0

There are 0 best solutions below