Following microblog tutorial on Flask: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
In Pycharm, no matter how I structure or name the files, I cannot get the dev server to run if I separate the code and import the files. I also can't get it to inherit the codes no matter where I move the init, views, run files. The only way for me to get the server to run is to have all the commands execute on the same file. What am I doing wrong?
I have it setup as:
Project 1 > app(directory) > tmp(directory) > run.py(file)
app(directory) > static(directory) > templates(directory) > init.py(file) > views.py(file) (I have tried different arrangements.)
Inside views.py:
from app import app
Inside run.py:
from app import app
Inside init.py:
from flask import Flask
from app import views
(I have tried many different combinations such as from app import app.views. from app import views as app_views. I have also tried renaming the directories/files, nothing is working.)
Build the new project with PyCharm, it will create a virtual environment for you. Then put these into a run.py in a root of your
a project like that (don't forget to turn debugging mode off in prod)
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
Set up init.py file inside you 'app':
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
bcrypt.init_app(app)
login_manager.init_app(app)
mail.init_app(app)
Store your credentials into Config class:
class Config:
SECRET_KEY = 'your key... '
SQLALCHEMY_DATABASE_URI = 'your db...'
SQLALCHEMY_TRACK_MODIFICATIONS = False
MAIL_SERVER = 'smtp.google.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = 'your email'
MAIL_PASSWORD = 'email password'
Structure your project, placing an empty init.py into each directory( accordingly to your architecture). Here is an example below, how to structure your project in Flask. It runs with no problem on
.
├── README.md
├── app
│ ├── __init__.py
│ ├── config.py
│ ├── errors
│ │ ├── 403.html
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── __init__.py
│ │ └── handlers.py
│ ├── main
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── models.py
│ ├── posts
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ └── routes.py
│ ├── site.db
│ ├── static
│ │ ├── main.css
│ │ └── profile_pics
│ │ ├── 3c4feb2bb50d90df.png
│ │ ├── ba3d328163a8125e.png
│ │ └── default.jpg
│ ├── templates
│ │ ├── about.html
│ │ ├── account.html
│ │ ├── create_post.html
│ │ ├── home.html
│ │ ├── layout.html
│ │ ├── login.html
│ │ ├── post.html
│ │ ├── register.html
│ │ ├── reset_request.html
│ │ ├── reset_token.html
│ │ └── user_posts.html
│ └── users
│ ├── __init__.py
│ ├── forms.py
│ ├── routes.py
│ └── utils.py
└── run.py
Related
After reading through this question, I have some insight as to why when trying to launch my app after deploying to Heroku, I get the following error: raise TemplateNotFound(template), jinja2.exceptions.TemplateNotFound: index.html.
They are saying that the templates should be at the project directory root as shown here. Is there anyway I can modify where Heroku is trying to look for the templates directory? I modified my project structure since my app was growing in size and starting to look a bit unorganized.
Here is a look at my current project structure:
Project
│
├── App
│ ├── DbMs
│ │ ├── db_actions.py
│ │ └── user_operations.py
│ ├── UI
│ │ ├── static
│ │ │ ├── css
│ │ │ │ └── main.css
│ │ │ ├── fonts
│ │ │ │ └── Gotham_Medium_Regular.json
│ │ │ ├── images
│ │ │ │ ├── favicons
│ │ │ │ │ ├── android-chrome-192x192.png
│ │ │ │ │ ├── android-chrome-512x512.png
│ │ │ │ │ ├── apple-touch-icon.png
│ │ │ │ │ ├── favicon-16x16.png
│ │ │ │ │ ├── favicon-32x32.png
│ │ │ │ │ ├── favicon.ico
│ │ │ │ │ └── site.webmanifest
│ │ │ │ ├── header.jpeg
│ │ │ │ ├── logo.png
│ │ │ │ └── radar-chart.png
│ │ │ └── javascript
│ │ │ ├── FontLoader.js
│ │ │ ├── TextGeometry.js
│ │ │ ├── create.js
│ │ │ ├── exploreMusic.js
│ │ │ └── tracks.js
│ │ └── templates
│ │ ├── base.html
│ │ ├── create.html
│ │ ├── index.html
│ │ ├── information.html
│ │ └── tracks.html
│ ├── __init__.py
│ ├── authenticate.py
│ ├── routes.py
│ ├── services.py
│ └── templates
├── Pipfile
├── Procfile
├── README.md
├── Testing
│ ├── __init__.py
│ └── testing.py
├── __pycache__
│ ├── authenticate.cpython-39.pyc
│ ├── config.cpython-39.pyc
│ ├── main.cpython-39.pyc
│ ├── services.cpython-39.pyc
│ └── user_operations.cpython-39.pyc
├── config.py
├── package-lock.json
├── package.json
├── requirements.txt
├── run.py
└── setup.py
For more context, I have everything running perfectly fine locally, I only see this error after deployment. Thanks to anyone who can provide insight.
EDIT: I tried moving the templates folder into the App directory as well as the project root and changing the following line in __init__.py both times:
template_dir = os.path.abspath('../Project/templates/')
After deploying each time, I changed the location of templates, still see the same error from Heroku: raise TemplateNotFound(template) jinja2.exceptions.TemplateNotFound: index.html
So it turns out that Heroku is picky with modifying the location of the templates & static folders.
Whats was very misleading about this issue was that I could run everything fine locally but as soon as I deployed to Heroku, the entire App would break..
The way I fixed this was by moving templates & static into the App directory. I also had to make sure that i changed the following line from:
template_dir = os.path.abspath('../Soulify/App/templates/')
static_dir = os.path.abspath('../Soulify/App/UI/static/')
app = Flask(__name__, template_folder=template_dir, static_folder=static_dir)
to:
app = Flask(__name__)
Also note that the template folder has to be named templates exactly or Heroku will fail. Again, pretty annoying.
Trying to run a basic functional test with pytest-flask but keep getting this error:
tests/conftest.py:2: in <module>
from learning_flashcards import create_app
E ImportError: cannot import name 'create_app'
Here is my directory structure:
.
├── Procfile
├── __pycache__
├── config.py
├── learning_flashcards
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── app.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── app.py
│ ├── db.py
│ ├── models.py
│ ├── static
│ │ └── style.css
│ ├── templates
│ └── views.py
├── learning_flashcards.egg-info
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ ├── dependency_links.txt
│ ├── requires.txt
│ └── top_level.txt
├── manage.py
├── migrations
│ ├── README
│ ├── alembic.ini
│ ├── env.py
│ ├── script.py.mako
│ └── versions
├── requirements
│ ├── common.txt
│ ├── dev.txt
│ └── runtime.txt
├── requirements.txt
├── setup.py
├── tests
│ ├── __pycache__
│ │ ├── conftest.cpython-36-pytest-5.4.3.pyc
│ │ ├── test_data.cpython-36-pytest-5.4.3.pyc
│ │ └── test_site.cpython-36-pytest-5.4.3.pyc
│ ├── conftest.py
│ ├── test_data.py
│ └── test_site.py
└── venv
And here is my conftest.py file:
import pytest
from learning_flashcards import create_app
#pytest.fixture
def app():
app = create_app()
return app
Have tried various ways of exploring the import system (from .learning_flashcards, from .learning_flashcards.learning_flashcards, etc.), have also investigated the init file to see if it is not creating the app instance correctly, but it looks to be fine. App runs on local server but can't get test suite to work.
Here's init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
import learning_flashcards.views
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres#localhost/flashcards'
db = SQLAlchemy()
And app.py:
from flask import Flask
from models import db
def create_app():
app = Flask(__name__)
db.init_app(app)
#app.route('/')
def learning_flashcards():
return "Hello World!"
POSTGRES = {
'user': 'postgres',
'pw': 'password',
'db': 'my_database',
'host': 'localhost',
'port': '5432',
}
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%(user)s:%(pw)s#%(host)s:%(port)s/%(db)s' % POSTGRES
return app
if __name__ == '__main__':
app = create_app()
app.run()
I just moved tests.py file to a new directory called tests, then I added __init__.py file therein, but as I run the test python manage.py test it says ran 0 tests in 0.000s. How to solve it?
I don't know how to show my files like most do, but here is an image!
This app is also added in settings.py
Thanks
edit:
this is a sample of test_models.py
from django.test import TestCase
# Create your tests here.
from django.test import TestCase
from django.urls import reverse
from board.models import Board
from board.views import board_topics
class HomeTest(TestCase):
def home_test_case(self):
url = reverse('home')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
class BoardTest(TestCase):
def setup(self):
Board.objects.create(title='Hello world',
description='My first Django app!')
def board_topics_status_code(self):
url = reverse('board_topics', kwargs={id: 1})
response = self.client.get(url)
return self.assertEqual(response.status_code, 200)
def board_topics_status_code_not_found(self):
url = reverse('board_topics', kwargs={id: 123})
response = self.client.get(url)
return assertEqual(response.status_code, 200)
def resolve_url_to_specific_fun(self):
url = resolve('board/1/')
return assertEqual(view.func, board_topics)
def HomeTests(TestCase):
def setUp(self):
self.board = Board.objects.create(
title='Django', description='Django Desc')
url = reverse('home')
self.response = self.client.get(url)
def home_test_view_status_code(self):
self.assertEqual(self.response.status_code, 200)
def home_test_func(self):
view = resolve('/')
self.assertEqual(view.func, home)
def test_home_contains_link_to_topics_page(self):
board_topics_url = reverse(
'board_topics', kwargs={'id': self.board.pk})
self.assertContains(self.response, 'href={0}'.format(board_topics_url))
All your tests must have the test_ prefix attached. Rename all your tests adding that to the name.
For example:
def test_board_topics_status_code(self):
url = reverse('board_topics', kwargs={id: 1})
response = self.client.get(url)
return self.assertEqual(response.status_code, 200)
Also, you need to change def HomeTests(TestCase): to class HomeTests(TestCase):, that's why your last test is named correctly but it is still not being discovered.
There are 2 ways you can keep your tests in your Project. I prefer the
1st one.
1. Your development code contains all of your tests. This way it's easier to add a new test when you write development code and your tests now ships with your development code.
Project
├── __init__.py
├── api
│ ├── v1
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_serializers.py
│ │ │ └── test_views.py
│ │ ├── __init__.py
│ │ ├── serializers.py
│ │ ├── urls.py
│ │ └── views.py
│ ├── v2
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_serializers.py
│ │ │ └── test_views.py
│ │ ├── __init__.py
│ │ ├── serializers.py
│ │ ├── urls.py
│ │ └── views.py
│ ├── __init__.py
│ ├── serializers.py
│ └── urls.py
├── models
│ ├── tests
│ │ ├── __init__.py
│ │ ├── test_data_structures.py
│ │ ├── test_miscellaneous_models.py
│ │ ├── test_models.py
│ ├── __init__.py
│ ├── models.py
│ ├── data_structures.py
│ └── miscellaneous_models.py
├── resume_handler
│ ├── tests
│ │ ├── __init__.py
│ │ ├── test_handlers.py
│ │ ├── test_managers.py
│ │ ├── test_parsers.py
│ │ ├── test_uploaders.py
│ │ └── test_validators.py
│ ├── __init__.py
│ ├── handlers.py
│ ├── managers.py
│ ├── parsers.py
│ ├── uploaders.py
│ └── validators.py
├── tasks
│ ├── tests
│ │ ├── __init__.py
│ │ └── test_tasks.py
│ ├── __init__.py
│ ├── general.py
│ └── model_tasks.py
├── tests
│ └── test_utils.py
└── utils.py
2. Another way is to put a test folder separate from the project folder. This test folder maintains the same hierarchy as of the project folder. This keeps the test code separate from the development code.
Project
├── api
│ ├── v1
│ │ └── more code files ...
│ ├── v2
│ │ └── more code files ...
│ └── v3
│ └── more code files ...
├── choices
├── constants
├── models
│ ├── data_filters
│ ├── querysets
│ └── more code files ...
├── resume_builder
│ └── more code files ...
├── resume_handler
│ └── more code files ...
├── tasks
│ └── more code files ...
└── more code files ...
Now in the same directory in which the Project folder is present create a test folder which maintains the same hierarchy but only contain the corresponding tests files.
test
├── api
│ ├── v1
│ │ └── test files ...
│ ├── v2
│ │ └── test files ...
│ └── v3
│ └── test files ...
├── choices
├── constants
├── models
│ ├── data_filters
│ ├── querysets
│ └── test files ...
├── resume_builder
│ └── test files ...
├── resume_handler
│ └── test files ...
├── tasks
│ └── test files ...
└── test files ...
I have the following file structure:
.
├── app
│ ├── api_routes
│ │ ├── forms.py
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── __init__.py
│ ├── main_routes
│ │ ├── forms.py
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── models.py
│ ├── static
│ │ └── styles.css
│ ├── templates
│ │ └── base.html
│ └── uploads
│ └── 10_0_0.jpg
├── application.py
└── config.py
In my config.py I have this:
class Config(object):
UPLOAD_FOLDER = 'uploads/'
When I'm saving an uploaded file, and then sending it back to the user (just as example) I'm using:
fname = 'foo.jpg'
fname_save = os.path.join(current_app.root_path, current_app.config['UPLOAD_FOLDER'], fname)
fname_retr = os.path.join(current_app.config['UPLOAD_FOLDER'], fname)
file.save(fname_save)
return send_from_directory(os.path.dirname(fname_retr),
os.path.basename(fname_retr))
Having different names for the upload folder in the cwd (where the file is saved), and the folder the flask module is running (app/), is a bit tedious. Are there any more elegant solutions than my current one to solve this issue?
What I would do this :
#app.route('/upload', methods=['POST'])
def myroute():
fname = 'foo.jpg'
file = request.file[0] # not save at all
send_back_file = io.BytesIO(file.read())
file.seek(0)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], fname))
return send_file(send_back_file, attachment_filename=fname, as_attachement=True)
Resource :
http://flask.pocoo.org/snippets/32/
http://flask.pocoo.org/docs/0.12/patterns/fileuploads/
Flask: app.register_blueprint works fine when run using the builtin app.run. However fails when tied to apache. I am getting a 404 error when I access the url
http://ipadddress/register - 404 Not Found
I have setup a Flask App with Apache2 and wsgi configuration. Below is the code. I have done the apache setup using Digital Ocean - Apache Flask configuration on debian systems
init.py
from flask import Flask, render_template
from register.registeration import account_api
app = Flask(__name__)
app.register_blueprint(account_api)
#app.route('/')
def home():
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True)
register/registration.py
from flask import Blueprint, render_template
account_api = Blueprint('account_api', __name__)
#account_api.route('/register')
def register():
return render_template('register.html')
flaskapp.wsgi
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/home/pi/ReSTServices/env/")
from FlaskApp import app as application
application.secret_key = 'MyHappyNewsWithHacker'
Project Structure
├── flaskapp.wsgi
├── __init__.py
├── register
│ ├── __init__.py
│ └── registeration.py
├── static
│ └── dist
│ ├── css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ ├── bootstrap.min.css
│ │ ├── bootstrap.min.css.map
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap-theme.min.css.map
│ │ ├── font-awesome.min.css
│ │ ├── sticky_footer.css
│ │ └── style.css
│ ├── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ ├── fontawesome-webfont.woff2
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── img
│ │ └── rpi.png
│ └── js
│ ├── bootstrap.js
│ ├── bootstrap.min.js
│ └── npm.js
└── templates
├── index.html
└── register.html