I had a Flask app that worked fine until, due to growth, I decided to modularize. The new structure is as follows:
├── Dockerfile
├── README.md
├── app
│ ├── __init__.py
│ ├── config.py
│ ├── cron.py
│ ├── database.ini
│ ├── db.py
│ ├── db.sqlite3
│ └── webapp
│ ├── __init__.py
│ └── routes.py
├── db.sqlite3
├── docker-compose.yml
├── error.log
├── gunicorn_config.py
├── rd.py
├── requirements.txt
├── static
│ ├── css
│ │ └── bootstrap.min.css
│ ├── data.html
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── images
│ │ ├── ajax-loader.gif
│ │ ├── gear.png
│ │ ├── gear_small.png
│ │ └── logo.png
│ ├── index.html
│ ├── js
│ │ ├── app.js
│ │ ├── bootbox.min.js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── npm.js
│ ├── login.html
│ ├── manage_users.html
│ ├── register.html
│ ├── reset_password.html
│ ├── settings.html
│ └── upload.html
└── templates
└── base.html
Here is the __init__.py for webapp:
from flask import Flask
from app.config import DebugConfig
from flask_sqlalchemy import SQLAlchemy
from importlib import import_module
from logging import basicConfig, DEBUG, getLogger, StreamHandler
import os
import uuid
def register_blueprints(app):
for module_name in (app.config['MODULES']):
module = import_module('app.{}.routes'.format(module_name))
app.register_blueprint(module.blueprint)
def configure_logs(app):
basicConfig(filename='error.log', level=DEBUG)
logger = getLogger()
logger.addHandler(StreamHandler())
def create_app():
file = (__file__)
app = Flask(__name__)
app.secret_key = str(uuid.uuid4())
app.config.from_object(DebugConfig)
register_blueprints(app)
configure_logs(app)
return app
Here is login page route code:
#blueprint.route("/login", methods=["GET", "POST"])
def login():
if request.method == 'GET':
return render_template(url_for('static', filename='login.html')
Unfortunately this new structure leads to this error when I attempt to serve the app:
builtins.FileNotFoundError FileNotFoundError: [Errno 2] No such file
or directory: '/static/login.html'
I have been messing with this for a while now and just can't figure out how to get the app to work and manage to locate the files. I tried setting the static_url_path value when instantiating the flask app but, although that manages to locate the HTML files, I'm unable to load the other static files like CSS and images because I have my paths defined relative to the static folder as below in the HTML:
<link href="css/bootstrap.min.css?version=24" > or
<link rel="icon" href="/static/images/gear.png">
Please assist, I feel like I'm going to pull my hair out as I've spent too much time on this issue. Thanks in advance.
What your are looking for is the Flask jinja_loader.
In your create_app method, you could overwrite the jinja_loader provided by default for Flask, which look into the template_folder directory to search for file using render_template method.
def create_app():
file = (__file__)
app = Flask(__name__)
app.secret_key = str(uuid.uuid4())
app.config.from_object(DebugConfig)
register_blueprints(app)
configure_logs(app)
# Overwrite Flask jinja_loader, using ChoiceLoader
template_loader = jinja2.ChoiceLoader([
app.jinja_loader,
jinja2.FileSystemLoader('/path/to/static'),
])
app.jinja_loader = template_loader
return app
Jinja2 ChoiceLoader look for template in the list of loaders.
So first in app.jinja_loader : the template_folder directory.
Then using the FileSystemLoader in the /static directory.
Be warn that if you have a template something.html in both the template and the static directory, the first one will be returned.
But Jinja2 has more loader than just the CoiceLoader and you should try to find one that suite your desires. For exemple the DictLoader with a key 'static' could be fine also
Related
I would like to know how Django's imports work. For example, in this code:
# in some_app/views.py
from another_app.models import UserModel
# another_app is another app of the same project
there's an import statement that imports UserModel from models.py in another_app (another app of the same project).
I was just wondering how Django handles this importing because usual Django project's directory structure looks like this:
.
├── another_app
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
├── some_app
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── some_project
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
some_app and another_app are separate directories.
I want to know how the importing works because I want to find a workaround for one of my projects that have separate directories but requires each other's functions.
If you register the app name in installed app in django settings you can easily handle most migrations and other stuff other wise you can just branch off from the folder of the app name.
What i recommend is making a separate directory named app and you can place all your app inside app director so the app and project directory gets separated easily and your import will also be easy
you can import in this manner after wards
from app.some_new_app_name.models import MyModel
from app.some_new_app_name_2.models import MyModel2
I have a dash app with multiple pages.
.
├── adduser.py
├── app.py
├── apps/
│ ├── __init__.py
│ ├── exome.py
│ ├── familial.py
│ ├── oncomine.py
│ ├── prenatal.py
│ ├── rapidexome.py
│ └── targeted.py
├── auth.py
├── data/
├── dataprocessor.py
├── index.py
├── layouts.py
└── static
└── fileiconn.png
I just want to prompt the use for an admin password when they try to access the /apps/exome route. is there a way to do that?
Before I say something, let me show the current project hierarchy. The app name is api.
── api
│ ├──
│ ├── admin.py
│ ├── apps.py
│ ├── init.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_wallet_customer_id.py
│ │ ├── 0003_auto_20201201_1103.py
│ │ ├── 0004_auto_20201203_0703.py
│ │ ├── 0005_auto_20201207_1355.py
│ │ ├── __init__.py
│ │
│ ├── models.py
│ ├── permissions.py
│ ├── serializers.py
│ ├── stellar.py
│ ├── te_s_ts_bk.py
│ ├── te_sts_2.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── debug.log
├── manage.py
└── myapp
├── __init__.py
├── asgi.py
├── settings-local.py
├── settings-remote.py
├── settings.py
├── urls.py
└── wsgi.py
As it was suggested here, I even removed __init__.py file from the api app folder, yet having the issue.
My TestCase Class look like below:
class CreateWalletTestCase(APITestCase):
app_id = 0
app = None
def test_create_wallet(self):
response = self.client.post(
'/wallets/',
data={'app_id': self.app_id, 'customer_id': 'A-001'},
**{'HTTP_api_key': 'test-api', 'HTTP_api_secret': 'test-api-password'}
)
data = json.loads(response.content)
self.assertEqual(data['status'], 'OK
When I run as python manage.py test api.CreateWalletTestCase.test_create_wallet or even python manage.py test CreateWalletTestCase.test_create_wallet, it generates the error:
ImportError: Failed to import test module: CreateWalletTestCase
Traceback (most recent call last):
File "/usr/local/lib/python3.9/unittest/loader.py", line 154, in loadTestsFromName
module = __import__(module_name)
ModuleNotFoundError: No module named 'api.CreateWalletTestCase'
The way to call the tests in python is very similar to the way you import things in that language. For example, if you want to import that TestCase in your file and assuming it is in the tests.py file, you should write import CreateWalletTestCase from api.tests in the elegant way. You can also write import api.tests.CreateWalletTestCase, to import it.
So, to call that specific test, you should write the command in the following way:
python manage.py test api.tests.CreateWalletTestCase.test_create_wallet
You can check the Django Documentation here about running tests.
It is not necessary to delete the __init__.py file.
When in my app.py, I am trying to import something from models.py and when I use
from .models import *
but I'm receiving the following error on my shell
ImportError: attempted relative import with no known parent package
My directory tree looks as following:
└── PROJECT_FOLDER
├── README.md
├── __pycache__
│ ├── app.cpython-36.pyc
│ ├── app.cpython-38.pyc
│ ├── scraping.cpython-36.pyc
│ └── scraping.cpython-38.pyc
├── app.py
├── db.sqlite3
├── models.py
├── scraping.py
├── static
│ └── css
│ ├── bootstrap-theme.min.css
│ ├── bootstrap.min.css
│ ├── sign.css
│ └── theme.css
└── templates
├── base.html
└── index.html
I've tried putting a main.py in an outer folder and importing from PROJECT_FOLDER.models import *
but that hasn't worked.
I also have tried putting an __init__.py in my root directory.
Any help is appreciated. Thanks!
django-celery-beat running so far ... tasks get queued and worker is executing simple tasks :)
now I would like to have my celery task to do a query towards the django database (to get a list of IP addresses for which I want to check reachability).
can i use the django 'helper code' to do the query or do I need to make a 'raw' connection from celery to sqlite/mysql?
thanks for any help on this
/pat
celery.py
# http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
#from celery import shared_task
from django.conf import settings
#settings.configure()
#from portal import models
#logger = logging.getLogger(__name__)
#from portal.models import location
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sc_custportal.settings')
app = Celery('sc_custportal')
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
#app.config_from_object('django.conf:settings')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
#app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
queryset = location.objects.all()
# response = os.system("ping -c 1 8.8.8.8")
# if response == 0:
# print("up!")
error:
[2017-05-04 14:55:09,962: ERROR/PoolWorker-1] Task sc_custportal.celery.debug_task[ecb79b33-7246-4e4e-9b4e-3d7f9b0102dc] raised unexpected: NameError("global name 'location' is not defined",)
Traceback (most recent call last):
File "/home/pat/Documents/Development/sc_custportal/env/local/lib/python2.7/site-packages/celery/app/trace.py", line 367, in trace_task
R = retval = fun(*args, **kwargs)
File "/home/pat/Documents/Development/sc_custportal/env/local/lib/python2.7/site-packages/celery/app/trace.py", line 622, in __protected_call__
return self.run(*args, **kwargs)
File "/home/pat/Documents/Development/sc_custportal/sc_custportal/sc_custportal/celery.py", line 32, in debug_task
queryset = location.objects.all()
NameError: global name 'location' is not defined
tree:
sc_custportal
├── celerybeat.pid
├── celerybeat-schedule
├── db.sqlite3
├── manage.py
├── portal
│ ├── admin.py
│ ├── admin.pyc
│ ├── apps.py
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0001_initial.pyc
│ │ ├── 0002_auto_20170503_1212.py
│ │ ├── 0002_auto_20170503_1212.pyc
│ │ ├── __init__.py
│ │ └── __init__.pyc
│ ├── models.py
│ ├── models.pyc
│ ├── templates
│ │ ├── index.html
│ │ ├── inspinia.html
│ │ ├── issue_tracker.html
│ │ ├── login.html
│ │ ├── login.html.sic
│ │ ├── modal_window.html
│ │ ├── notifications.html
│ │ ├── partials
│ │ │ ├── footer.html
│ │ │ ├── head.html
│ │ │ ├── menu.html
│ │ │ └── scripts.html
│ │ ├── profile.html
│ │ ├── table_data_tables.html
│ │ └── toastr_notifications.html
│ ├── tests.py
│ ├── urls.py
│ ├── urls.pyc
│ ├── views.py
│ └── views.pyc
├── rest
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── serializers.py
│ ├── serializers.pyc
│ ├── tests.py
│ ├── urls.py
│ ├── urls.pyc
│ ├── views.py
│ └── views.pyc
└── sc_custportal
├── celery.py
├── celery.pyc
├── __init__.py
├── __init__.pyc
├── settings.py
├── settings.pyc
├── settings.py.orig
├── urls.py
├── urls.pyc
├── wsgi.py
└── wsgi.pyc
Yes, you can do it like
from portal.models import MyModel
#app.task(bind=True)
def debug_task(self):
MyModel.objects.all()
If you're considering accessing objects recently created/updated, please take care that the transaction commited before starting your task. Typically, you could start your task with a transaction.on_commit(your_task_call).
This answer gives you more details.