1

I'm using flask-restless and getting a Bad Request (400) error on my first POST (from Postman). If I keep on making the same request, it keeps on erroring. But if I remove the field that flask-restless complains about, run the POST again, get a positive response, add that same field back in, and run it again, it works fine from then on.

URL: /api/appraisals

Request JSON:

{
    "suggested_price": 88,
    "listing": {"id": 1}
}

Error Response:

{
    "message": "Model does not have field 'listing'"
}

app.py:

from models.db import init_app
from controllers import api


app = Flask(__name__)
app.config.from_object('config')
init_app(app)

api.init_api(app)

from models.db.py:

 from flask.ext.sqlalchemy import SQLAlchemy

 def init_app(app):
      with app.app_context():
           db.init_app(app)
           db.create_all()

 db = SQLAlchemy()

from controllers.api.py:

 from flask.ext.restless import APIManager

 class ResourceManager(APIManager): ...

 def init_api(app):
      with app.app_context():
           manager = ResourceManager(app, flask_sqlalchemy_db=db)
           manager.add_resource(ListingResource())
           manager.add_resource(AppraisalResource())

from models.appraisal.py:

 from .db import db
 from .base import BaseModel


 class Appraisal(BaseModel):

      __tablename__ = "appraisal"

      # required fields
      suggested_price = db.Column(db.Integer, nullable=False)

      # optional fields
      currency = db.Column(db.Unicode, default=u"USD")

      # relationships
      listing_id = db.Column(db.Integer, db.ForeignKey('listing.id'))

from models.listing.py:

 from sqlalchemy.schema import UniqueConstraint

 from .db import db
 from .base import BaseModel

 class Listing(StatusfulModel, BaseModel):

     __tablename__ = "listing"

     # relationships
     appraisals = db.relationship(
         "Appraisal",
         backref=db.backref("listing", uselist=False),
         uselist=True)

from controllers.resource.appraisal.py:

 class AppraisalResource(Resource):

      model_class = Appraisal
      base_url = "appraisals"
      allowed_methods = ["POST", "GET"]

      def get_fields(self):
           super_fields = super(AppraisalResource, self).get_fields()

           return super_fields + [
                "listing",
                "listing.id"
           ]
Evan Hammer
  • 450
  • 4
  • 13

1 Answers1

2

I think the best way to explain how to solve this error is to tell you what was on my mind while thinking about that.

You going to get into those situation a lot with APIs, and it's importing to know how to think about the logics.

  1. You got error 400 - that mean you sent a JSON but not in the format Flask expecting.
  2. According to your question removing the listing field solved the problem - feels like we getting closer.
  3. I looked on what model you trying to make the change(/api/appraisals) - Appraisals
  4. Your model:

    class Appraisal(BaseModel):
        __tablename__ = "appraisal"
    
        suggested_price = db.Column(db.Integer, nullable=False)
        currency = db.Column(db.Unicode, default=u"USD")
        listing_id = db.Column(db.Integer, db.ForeignKey('listing.id'))
    
  5. After looking at this, you can see Flask expecting "listing_id" - and not "listing"

I hope i was clear, tell me if you need any help. Goodluck!

Or Duan
  • 13,142
  • 6
  • 60
  • 65
  • Giving you credit as this solved the problem. And thank you for that! But the erratic nature of the error is a problem with flask-restless. I send the same request twice: one time it fails, one time it works. Also, `listing` is a relationship on the Appraisal object. If you list out its RelationshipProperty's you can see it. – Evan Hammer Jun 21 '14 at 16:27