0
votes

I have a very simple Flask RESTful API that I have built following the Packt book "Python API Development Fundamentals". I can successfully get data from the DB but I'm having trouble posting data.

I am using Flask, SQLAlchemy, and flask_restful, and a Microsoft Server Management Studio local database. I am currently getting an error ("name 'user_schema' is not defined.") in the user.py resource when trying to insert an entry into the Users table. A user is only an ID, Name, Age.

I have never use Marshmallow before and I'm not sure what I'm doing wrong.

I am trying to create a new user by entering this into the console using httpie:

http POST localhost:5000/users Name="Kyle" Age="22"

Error

[2021-03-31 10:44:40,944] ERROR in app: Exception on /users [POST]
Traceback (most recent call last):
  File "c:\users\e096752\documents\cole's projects\flask projects\testproj\venv\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\users\e096752\documents\cole's projects\flask projects\testproj\venv\lib\site-packages\flask\app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "c:\users\e096752\documents\cole's projects\flask projects\testproj\venv\lib\site-packages\flask_restful\__init__.py", line 468, in wrapper
    resp = resource(*args, **kwargs)
  File "c:\users\e096752\documents\cole's projects\flask projects\testproj\venv\lib\site-packages\flask\views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "c:\users\e096752\documents\cole's projects\flask projects\testproj\venv\lib\site-packages\flask_restful\__init__.py", line 583, in dispatch_request   
    resp = meth(*args, **kwargs)
  File "C:\Users\e096752\Documents\Cole's Projects\Flask Projects\testProj\resources\users.py", line 34, in post
    data, errors = user_schema.load(data=json_data)
NameError: name 'user_schema' is not defined
127.0.0.1 - - [31/Mar/2021 10:44:40] "POST /users HTTP/1.1" 500 -

users.py resource


from flask import request
from flask_restful import Resource
from http import HTTPStatus
from flask import jsonify
from sqlToJson import convert_sqlaLchamy_to_json
from models.Users import User, userList
from schemas.user import UserSchema

class User_List_Resource(Resource):

    user_schema = UserSchema()

    def get(self):
        
        users = User.query.all()

        data = jsonify(convert_sqlaLchamy_to_json(users))
        
        return data

    def post(self):

        #Non-marshmallow approach gives error: "Object of type User is not JSON serializable"
        # json_data = request.get_json()

        # user = User(Name=json_data['Name'],
        #                 Age=json_data['Age'])
        
        # return jsonify(user), HTTPStatus.CREATED

        #Marshmallow approach gives error: "line 36, name 'user_schema' is not defined."
        json_data = request.get_json()

        data, errors = user_schema.load(data=json_data)

        if errors:
            return {'message': 'Name already exists'}, HTTPStatus.BAD_REQUEST

        user = User(**data)
        user.save()
        return user_schema.dump(user).data, HTTPStatus.CREATED

Users.py model

from extensions import db
from flask_marshmallow import Marshmallow

userList = []

def get_last_id():
    if userList:
        lastUser = userList[-1]
    else:
        return 1
    return lastUser.id + 1

class User(db.Model):
    __tablename__ = 'Users'
    ID = db.Column(db.Integer, primary_key=True)
    Name = db.Column(db.String(50))
    Age = db.Column(db.Integer)

Users.py schema

from marshmallow import Schema, fields

class UserSchema(Schema):
    class Meta:
        ordered = True

    Name = fields.String(required=True)
    Age = fields.Integer(required=True)

app.py

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
from flask_restful import Resource, Api
from flask import jsonify
import json
from sqlToJson import convert_sqlaLchamy_to_json
import datetime
from flask_restful import Api

from config import Config
from extensions import db
from models.Case_Log import Case_Log
from resources.case_log import Case_Log_List_Resource
from models.Users import User
from resources.users import User_List_Resource
from resources.home import Home_Resource

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)

    register_extensions(app)
    register_resources(app)

    return app


def register_extensions(app):
    db.init_app(app)

def register_resources(app):
    api = Api(app)

    #Add all resources as routes
    api.add_resource(Home_Resource, '/')
    api.add_resource(Case_Log_List_Resource, '/case_logs')
    api.add_resource(User_List_Resource, '/users')

if __name__ == '__main__':
    app = create_app()
    app.run()

Here is my project structure if it helps:

file structure

And here is a pic of the database table if that helps at all:

table

1

1 Answers

0
votes

i suggest first

the schema, not load from user model so you must declare it as model in UserSchema

from marshmallow import Schema, fields
from models.users import User

class UserSchema(Schema):
    class Meta:
        model = User
        ordered = True

    Name = fields.String(required=True)
    Age = fields.Integer(required=True)