I am trying to use Flask restful as a Blueprint in a pattern that works for other blueprints. I keep getting a 404 error when i go to
/todos/1
My project setup is as follows:
Folder structure
├── app
│ ├── __init__.py
│ ├── mod_api
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── main
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ └── views.py
│ └── templates
│ ├── base.html
│ └── home.html
├── config.py
├── manage.py
└── requirements.txt
__init__.py
from flask import Flask
from flask_restful import Api
from flask_bootstrap import Bootstrap
from config import config
bootstrap = Bootstrap()
api = Api()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
api.init_app(app)
from .main import main as main_blueprint
from .mod_api import mod_api as api_blueprint
app.register_blueprint(main_blueprint)
app.register_blueprint(api_blueprint)
return app
mod_api/__init__.py
from flask import Blueprint
mod_api = Blueprint('mod_api', __name__)
from . import routes
api/routes.py
from flask_restful import Resource
from .. import api
class TodoItem(Resource):
def get(self, id):
return {'task': 'Say "Hello, World!"'}
api.add_resource(TodoItem, '/todos/<int:id>')
What am I doing wrong??
I had the same problem, the solution is:
api.init_app(api_blueprint)
Related
I am creating a Flask based Web application with GAE Python 2.7 Standard Environment. When I try to import Animal Model inside application/__init__py file and other files, App Engine SDK raises DuplicatePropertyError.
DuplicatePropertyError: Class AnimalKind already has property animal_set
.
├── README.md
├── requirements.txt
├── src
│ ├── app.yaml
│ ├── application
│ │ ├── __init__.py
│ │ ├── animal_bp
│ │ │ ├── __init__.py
│ │ │ └── views.py
│ │ ├── appengine_config.py
│ │ ├── main.py
│ │ ├── models
│ │ │ ├── __init__.py
│ │ │ ├── base_models.py
│ │ │ ├── common_models.py
│ │ │ └── kind_models.py
│ │ └── settings.py
│ ├── index.yaml
│ ├── lib
app.yaml
service: default
runtime: python27
api_version: 1
threadsafe: true
instance_class: F1
builtins:
- appstats: on
- remote_api: on
libraries:
- name: ssl
version: latest
inbound_services:
- warmup
# [START handlers]
handlers:
- url: /static
static_dir: static
- url: .*
script: run.application.app
# script: main.app
secure: always
# [END handlers]
run.py
# -*- coding: utf-8 -*-
import os
import sys
sys.path.insert(1, os.path.join(os.path.abspath('.'), 'lib'))
sys.path.insert(1, os.path.join(os.path.abspath('.'), 'application'))
import application
application/init.py
# -*- coding: utf-8 -*-
import os
from flask import Flask, g, request, session
from werkzeug.debug import DebuggedApplication
from animal_bp.views import animal_bp
from models.common_models import Animal
def create_app():
app = Flask(__name__)
app.config.from_object('application.settings.Local')
app.wsgi_app = DebuggedApplication(app.wsgi_app, evalex=True)
app.register_blueprint(animal_bp)
return app
app = create_app()
application/models/common_models.py
from google.appengine.ext import db
from models.kind_models import AnimalKind
class Animal(db.Model):
"""
Animal Model
"""
animal_kind_name = db.ReferenceProperty(AnimalKind)
application/models/kind_models.py
from google.appengine.ext import db
class AnimalKind(db.Model):
"""
Kind Model
"""
name = db.StringProperty(required=True)
application/animal_bp/views.py
from flask import Blueprint
from models.common_models import Animal
animal_bp = Blueprint('animal_bp', __name__)
#animal_bp.route('/')
def hello():
return 'Hello world1'
For example, if I delete "from models.common_models import Animal" in animal_bp/views.py. the error is not raised. Of course when I remove "from models.common_models import Animal" from application/init.py file, the error is not raised.
I don't have any duplicate property but maybe initialization process run twice due to my directory structure. Sorry for such a long question, but any help will be welcomed!!
from google.appengine.ext import db
from models.kind_models import AnimalKind
class Animal(db.Model):
"""
Animal Model
"""
animal_kind_name = db.ReferenceProperty(AnimalKind)
The error seems to be that you are creating a ReferenceProperty without giving it an explicit name.
from google.appengine.ext import db
from models.kind_models import AnimalKind
class Animal(db.Model):
"""
Animal Model
"""
animal_kind_name = db.ReferenceProperty(AnimalKind, name='testName')
I think this was not necessary in some old versions but after (1.7.6+) they have changed the way of initializing instances.
And FYI Python 2 support on Google Cloud already ended on January 1, 2020, and all developers are encouraged to upgrade to Python 3 as soon as they can.
Python2 Sunset
DuplicatePropertyError happens If you have multiple ReferenceProperty values that refer to the same model class. A solution for this is to explicitly set the collection_name argument in ReferenceProperty, like in:
class Animal(db.Model):
name = db.ReferenceProperty(AnimalKind, collection_name='test_reference')
Currently I have an API project, based on flask-restful, with documentation page created with OpenAPI (Swagger). I'm trying to create a login page, based on my structure jinja2 can not find the path to the template.
In the login script, I tried to pass the full path to the .html file, in the render_template() function, but did not find the file. Just like adding the parameter template_folder = path/to/file in app=Flask(__name__) and I did not succeed.
My Structure:
├── app
│ ├── __init__.py
│ ├── auth
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── login.py
│ ├── common
│ │ ├── __init__.py
│ │ ├── jwt.py
│ │ ├── request.py
│ │ └── utils.py
│ ├── models
│ │ ├── __init__.py
│ │ ├── core.py
│ │ └── db_app_2.py
│ ├── routes
│ │ ├── __init__.py
│ │ ├── resources.py
│ └── templates
│ ├── docs
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ └── pages
│ ├── base.html
│ ├── login.html
│ └── signup.html
├── app.db
├── config.py
├── main.py
├── migrations
├── requeriments
└── tests
login.py
# -*- coding: utf-8 -*-
from flask import Blueprint, render_template, redirect, url_for
from app.models.core import db
auth = Blueprint('auth', __name__)
#auth.route('/login')
def login():
return render_template('login.html')
#auth.route('/signup')
def signup():
return render_template('signup.html')
__init__.py(main project)
from flask import Blueprint, Flask
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_restful import Api
from config import config
from .models.core import db
from .routes.resources import TwoThings
def create_app(config_name):
app = Flask(__name__, template_folder="/templates/pages")
app.config.from_object(config[config_name])
'''Fixed path for routes the api'''
path_prefix = '/api/v1'
api_bp = Blueprint(path_prefix, __name__)
api = Api(api_bp)
from app.auth.login import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix=path_prefix)
api.add_resource(Reset, f'{path_prefix}/two_things')
app.register_blueprint(api_bp)
db.init_app(app)
Migrate(app, db)
return app
I need to create a login page, to be accessible by the browser and once logged in redirect to the documentation endpoint.
Try:
return render_template('pages/login.html')
In your login.py.
I'm building an API, using Flask and flask-restful and flask-swagger-ui. I have now modified the project structure and now I can no longer access the project's swagger.json file.
Based on the package documentation flask-swagger-ui, you would only need to change the parameter API_URL to the correct path. But even when entering relative path or full path, I can no longer access the file.
My Code:
from flask import Flask, jsonify
from flask_migrate import Migrate
from flask_restful import Api
from flask_swagger_ui import get_swaggerui_blueprint
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
api = Api(app, prefix="/api/v1")
'''swagger specific'''
SWAGGER_URL = '/api/v1/docs'
# API_URL = 'templates/swagger.json'
API_URL = 'app/templates/docs/swagger.json'
SWAGGERUI_BLUEPRINT = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': "My Rest App"
}
)
app.register_blueprint(SWAGGERUI_BLUEPRINT, url_prefix=SWAGGER_URL)
db.init_app(app)
Migrate(app, db)
return app
My Tree Structure:
├── API
│ ├── app
│ │ ├── __init__.py
│ │ ├── models
│ │ │ ├── __init__.py
│ │ │ ├── db.py
│ │ │ └── db2.py
│ │ ├── routes
│ │ │ ├── __init__.py
│ │ │ ├── resources.py
│ │ └── templates
│ │ └── docs
│ │ └── swagger.json
│ ├── app.db
│ ├── config.py
│ ├── main.py
│ ├── migrations
│ ├── requeriments
│ └── tests
└── README.md
I need help, to understand the problem of the path to the file and thus correct the problem.
I believe that its a restriction on flask's end, but it seems like you must place static files in a folder explicitly named static/ at the root of your flask app.
Try changing
API_URL = 'app/templates/docs/swagger.json'
to
API_URL = '/static/swagger.json'
Then create a static/ folder in API/app/, and move your json into it. Like so: API/app/static/swagger.json
If that doesn't work, make sure you have the static/ folder in the correct directory, try print(app.root_path) after defining your flask app variable in order to see what flask considered the root path to be.
We can't provide any custom file path for swagger.json.
But there is one catch which we can do if you require.
I was facing the same issue where I need to provide different prefix for swagger URL and swagger.json.
If we just want to serve swagger.json file from a different prefix instead of '/static/swagger.json':
Then make changes as below:
APP = Flask(__name__, static_url_path = '/my-prefix/static')
API_URL = '/my-prefix/static/swagger.json'
For me "root_path" solved the problem,
Lets say I have the following path:
"C:\script\mycode\src\swagger.json"
def resource_path(relative_path):
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
new_path = resource_path("swagger.json")
new_path = new_path.replace("swagger.json", "")
app = Flask(__name__, root_path=new_path, static_folder="")
print("app.root_path ===================>>",app.root_path)
#prints: "C:\script\mycode\src\"
app.register_blueprint(get_swaggerui_blueprint(
'/api/swagger',
"\\swagger.json", #put starting slash even the app.root_path ends with
#slash. and check in "app.root_path" if additional path
#need to be added with "\\swagger.json"
config=apiConfig),
url_prefix=apiPrefixV1+'swagger',
name='v1')
Note: For me resource path is used for pyinstaller build. For local test also works fine!
I'm trying to get Flask Blueprints running in Docker, but having issues with registering Blueprints correct.
I have the following structure:
├── docker-compose.yml
├── nginx
│ ├── Dockerfile
│ └── sites-enabled
│ └── flask_project
└── web
├── Dockerfile
├── __init__.py
├── app.py
├── modules
│ ├── __init__.py
│ └── page
│ ├── __init__.py
│ ├── forms.py
│ ├── models.py
│ ├── views.py
├── requirements.txt
├── static
│ ├── css
│ │ ├── bootstrap.min.css
│ │ └── main.css
│ ├── img
│ └── js
│ └── bootstrap.min.js
└── templates
├── _base.html
└── index.html
app.py contains:
from flask import Flask
from web.modules.page import simple_page
app = Flask(__name__)
app.register_blueprint(simple_page)
if __name__ == '__main__':
print app.url_map
app.run(debug=True)
views.py contains:
from flask import Blueprint
simple_page = Blueprint('simple_page', __name__,
template_folder='templates')
#simple_page.route('/')
def index():
return "Hello world"
__init__.py under page:
from web.modules.page.views import simple_page
The __init__.py files are empty.
The console gives an ImportError: No module named web.modules.page
Thanks for your time.
Look like is structure problem, you can reference from here: https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications
The following is my example, hope it can help for you:
├── app
│ ├── __init__.py
│ ├── main
│ │ ├── __init__.py
│ │ └── views.py
│ ├── models
│ │ └── __init__.py
│ ├── static
│ │ ├── css
│ │ ├── js
│ │ ├── img
│ │ └── file
│ ├── templates
│ │ └── index.html
└── master.py
app/__init__.py
from flask import Flask
from app.main import main
def create_app():
app = Flask(__name__)
app.register_blueprint(main)
return app
app/main/__init__.py
from flask import Blueprint
main = Blueprint('main', __name__)
from app.main import views
master.py
from app import create_app
if __name__ == '__main__':
app = create_app()
app.run(host='0.0.0.0', port=8000, threaded=True)
I've faced many hurdles in upgrading my Django 1.6.2 project to Django 1.8.4. The latest problem which has me stumped is this one. When I start my Django dev server and try to access my site, I'm getting the following error:
Exception Type: ImportError at /
Exception Value: No module named account.models
Traceback:
File "/Users/me/venv/myproj_dj_18/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
119. resolver_match = resolver.resolve(request.path_info)
File "/Users/me/venv/myproj_dj_18/lib/python2.7/site-packages/django/core/urlresolvers.py" in resolve
366. for pattern in self.url_patterns:
File "/Users/me/venv/myproj_dj_18/lib/python2.7/site-packages/django/core/urlresolvers.py" in url_patterns
402. patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "/Users/me/venv/myproj_dj_18/lib/python2.7/site-packages/django/core/urlresolvers.py" in urlconf_module
396. self._urlconf_module = import_module(self.urlconf_name)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py" in import_module
37. __import__(name)
File "/www/myproj/conf/urls.py" in <module>
8. from apps.admin.views import all_admins
File "/www/myproj/apps/admin/views.py" in <module>
27. from apps.account.models import Account
This is a portion of my project's folder structure:
myproj
├── apps
│ ├── __init__.py
│ ├── account
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── forms.py
│ │ ├── models.py
│ │ ├── templates
│ │ ├── tests
│ │ ├── urls.py
│ │ └── views.py
│ ├── admin
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── forms.py
│ │ ├── models.py
│ │ ├── templates
│ │ ├── tests
│ │ ├── urls.py
│ │ └── views.py
├── conf
│ ├── __init__.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── base.py
│ ├── urls.py
│ ├── wsgi.py
├── manage.py
Here is a portion of my url file:
# conf/urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.contrib.auth.decorators import user_passes_test
from django.contrib import admin
from apps.admin.views import all_admins
urlpatterns = patterns('',
url(r'^account/', include('apps.account.urls')),
url(r'^members/', include('apps.members.urls')),
url(r'^admin/all_admins/$',
user_passes_test(lambda u: u.is_staff)(all_admins),
{'template': 'all_admins.html'},
name='all-admins'),
url(r'^admin/review/queue/$',
'apps.admin.views.review_queue',
{'template': 'review_queue.html'},
name='review-queue'),
url(r'^admin/', include(admin.site.urls)),
url(r'', include('apps.home.urls')),
)
These are my installed apps:
# apps/conf/settings/base.py
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'apps.admin',
'apps.account',
'apps.home',
)
This is a portion of the model file:
# apps/account/models.py
from django.db import models
class Account(models.Model):
pass
I've subclassed the new AppConfig class per the docs:
# apps/account/apps.py
from django.apps import AppConfig
class AccountConfig(AppConfig):
name = 'apps.account'
# apps/account/__init__.py
default_app_config = 'apps.account.apps.AccountConfig'
# apps/admin/apps.py
from django.apps import AppConfig
class MyAdminConfig(AppConfig):
name = 'apps.admin'
label = 'my_admin'
verbose_name = 'Administration'
# apps/admin/__init__.py
default_app_config = 'apps.admin.apps.MyAdminConfig'
I've checked to ensure that all my paths are mutually consistent:
$ python
>>> from django.apps import apps as myproj_apps
>>> account = myproj_apps.get_app_config('account')
>>> account.name # => 'apps.account'
>>> list(account.get_models()) # => [apps.account.models.Account]
I can also do this with no errors:
$ python
>>> from apps.account.models import Account
>>> Account.objects.get(pk=1)
I tried changing all paths described above from "apps.account.models" to "myproj.apps.account.models" but that didn't help. I've also read the Django 1.7 Applications doc but don't see what I'm doing wrong. Nothing has turned up in my web searches either. This looks like something simple. Can anyone see what I'm missing?
Thanks!