Hey all, I'm trying to add an API using Flask-Restless and have come across an issue that completely stumps me, and I'm not sure if it's starting in the initial Flask app or Flask-Restless. Short story, I'm getting 301 Moved Permanently on my Flask-Restless routes and have no idea where they come from. Longer Story: I'm using Flask 0.8, Flask-Restless 0.12.1, and SQLAlchemy 0.8.2. I'm using the pure SQLAlchemy method rather than Flask-Alchemy given other requirements we have. I attempted to create a standard setup for a basic class defined in SQLAlchemy. # Flask-Restless Setup manager = APIManager(app, session = sqlalchemy_scoped_session) manager.create_api(TheClass, collection_name="the_class", methods=["GET"]) The code above should set up a blueprint with routes. In fact, if I iterate over the rules, I can see the routes are created as expected. For example, "/api/the_class/<instid> (HEAD, OPTIONS, GET)" is one of the basic ones I try to access. Here is where it gets weird. I make a request for GET /wsgi_base/api/the_class/1 and get a "301 Moved Permanently" back, redirecting to "/wsgi_base/api/the_class/None". This ends up leading to an attribute error because u"None" is not an attribute... Does anyone know where this 301 may be coming from? I've searched and searched but haven't figured it out. Simple grepping for 301 in both flask and flask_restless come up with nothing. Some rough, unprofessional debugging techniques shows it tosses a routing_exception within app.py in Flask fairly early on somewhere..In fact, it seems to already have "301 Moved Permanently" as the _request_ctx_stack.top.request.routing_exception in the earliest code I see in a traceback - right in the start of the wsgi_app function. I'm not sure what code executes before that as it's the earliest code I have in traceback and seems to be the start of wsgi running the app. This only seems to happen for these flask_restless API requests as well...If I put in a bogus route, there is no 301 exception. If I put in any hard coded routes, it works fine as well. But what doesn't make sense is I can print the rules/endpoints after calling create_api() and everything looks ok there..
So weird... Would you gimme some code to reproduce this?
On 12/3/13, 8:55 AM, gioi wrote: > So weird... Would you gimme some code to reproduce this? > Sure. Here is some slightly adjusted code straight from Flask-Restless tutorial. Just adjusted it to work with pure SQLAlchemy. This was tested using Flask 0.8 and Flask-Restless 0.12. I'm still working on testing running newer versions of Flask, but it truly is a pain to jump through some of these hoops to do so. Hitting <ip>:5000/api/person/1 redirects to <ip>:5000/api/person/1/None --- from flask import Flask from sqlalchemy import Column, Date, DateTime, Float, Integer, Unicode from sqlalchemy import ForeignKey from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import backref, relationship from sqlalchemy.orm import scoped_session, sessionmaker from flask.ext.restless import APIManager app = Flask(__name__) engine = create_engine('sqlite:////tmp/testdb.sqlite', convert_unicode=True) Session = sessionmaker(autocommit=False, autoflush=False, bind=engine) mysession = scoped_session(Session) Base = declarative_base() Base.metadata.bind = engine class Computer(Base): __tablename__ = 'computer' id = Column(Integer, primary_key=True) name = Column(Unicode, unique=True) vendor = Column(Unicode) buy_date = Column(DateTime) owner_id = Column(Integer, ForeignKey('person.id')) class Person(Base): __tablename__ = 'person' id = Column(Integer, primary_key=True) name = Column(Unicode, unique=True) age = Column(Float) other = Column(Float) birth_date = Column(Date) computers = relationship('Computer', backref=backref('owner', lazy='dynamic')) Base.metadata.create_all() # Create the Flask-Restless API manager. manager = APIManager(app, session=mysession) # Create API endpoints, which will be available at /api/<tablename> by # default. Allowed HTTP methods can be specified as well. manager.create_api(Person, methods=['GET', 'POST', 'DELETE']) manager.create_api(Computer, methods=['GET']) # start the flask loop app.run(host='0.0.0.0')