So, I am working on my self learning on flask, in order to one my problem with enums, I am using marshal_with
, which one of user suggested me.. Now I have problem getting data for invalid ids..
I am using following to get response:
def json(self):
return {
'data': {
'employee_id': self.emp_no,
'employee_name': self.first_name + " " + self.last_name,
'gender': self.gender,
'birth_date': self.birth_date,
'hire_date': self.hire_date,
'created_at': self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
'last_updated_at': self.last_updated_at.strftime("%Y-%m-%d %H:%M:%S")
}
}
@classmethod
def find_by_employee_id(cls, employee_id):
return cls.query.filter_by(emp_no=employee_id).first()
at resources section of employees, I have implemented following logic to get results for end point:
class GetEmployee(Resource):
@marshal_with({
'data': fields.Nested({
'employee_id': fields.Integer,
'employee_name': fields.String,
'gender': fields.String,
'birth_date': fields.String,
'hire_date': fields.String,
'created_at': fields.Raw,
'last_updated_at': fields.Raw
})
})
def get(self, employee_id: int):
employee = Employees.find_by_employee_id(employee_id)
if not employee:
return {'message': 'Employee Not Found'}, 404
return employee.json(), 200
Now good thing is, I am getting response perfectly fine, if I am entering valid employee_id
within end point, but if I add invalid id like 4,5, I am getting response like this:
{
"data": {
"employee_id": 0,
"employee_name": null,
"gender": null,
"birth_date": null,
"hire_date": null,
"created_at": null,
"last_updated_at": null
}
}
what I am expecting is the response, which I have added within GetEmployee
class, i.e.
{'message': 'Employee Not Found'}
Where is the problem.
There is the possibility of throwing a 404 error when querying the database if no entry is found. It is also possible to define an error message that is output when abort
is called automatically following the error. The explanation can be found in the Flask-SQLAlchemy documentation in the "Queries for Views" section.
The following example shows you in a simplified manner how you can output either the error or the resource. Of course, it is also possible to call abort()
manually if necessary.
from flask import (
Flask,
render_template,
request
)
from flask_restful import (
Api,
Resource,
fields,
marshal_with,
)
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import column_property
import enum
class GenderChoices(enum.Enum):
M = 'M'
F = 'F'
def __str__(self):
return self.name
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY='your secret here',
SQLALCHEMY_DATABASE_URI='sqlite:///demo.db',
)
db = SQLAlchemy(app)
api = Api(app)
class Employee(db.Model):
__tablename__ = "employees"
id = db.Column(db.Integer, primary_key=True)
firstname = db.Column(db.String(80), unique=False, nullable=False)
lastname = db.Column(db.String(80), unique=False, nullable=False)
name = column_property(firstname + ' ' + lastname)
gender = db.Column(db.Enum(
GenderChoices,
values_callable=lambda x: [str(member.value) for member in GenderChoices]
))
# ...
def to_dict(self):
return {
'employee_id': self.id,
'employee_name': self.name,
'gender': self.gender
# ...
}
with app.app_context():
db.drop_all()
db.create_all()
employee = Employee(
firstname='User',
lastname='One',
gender=GenderChoices.M,
)
db.session.add(employee)
db.session.commit()
class EmployeeRsrc(Resource):
@marshal_with({
'data': fields.Nested({
'employee_id': fields.Integer,
'employee_name': fields.String,
'gender': fields.String
# ...
})
})
def get(self, employee_id):
employee = db.get_or_404(
Employee, employee_id,
description='Employee Not Found'
)
return {
'data': employee.to_dict()
}
api.add_resource(EmployeeRsrc, '/employees/<employee_id>')
If you want to output any error message including a status code, you can use abort(code, *args, **kwargs)
. Execution ends immediately and an exception is thrown, which is caught by the error handler, which sends a response.
from flask_restful import abort
class MyRsrc(Resource):
def post(self):
# ...
abort(422, message='Email invalid')