I'm a 2 Scoops of Django 1.8 reader. Chapter 29 (what about those random utilities) suggests to create a core app to store commonly used code. It also suggests that you can use this syntax to import code from it:
e.g.
from core.models import TimeStampedModel
How ever it seems that this relative import does not work. I'm using cookiecutter-django and I needed to do:
from projectname.apps.core.models import TimeStampedModel
I tried adding my APPS_DIR to the path:
sys.path.insert(str(APPS_DIR))
But that resulted in import conflicts given that now there were 2 modules with the same name, new_app and projectname.apps.new_app.
I just want to avoid explicit imports. Is there a way to include the Installed Apps in the python path without creating import conflicts? what are best practices regarding external apps imports?
edit: adds project structure
.
├── README.rst
├── manage.py
├── config
│ ├── __init__.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── common.py
│ │ ├── local.py
│ │ ├── test.py
│ │ ├── production.py
│ │ └── staging.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── projectname
│ ├── __init__.py
│ ├── apps
│ │ ├── __init__.py
│ │ ├── core
│ │ │ └── __init__.py
│ │ └── new_app
│ │ └── __init__.py
│ ├── static
│ │ └── ...
│ └── templates
│ └── ...
├── requirements
│ ├── base.txt
│ ├── local.txt
│ ├── production.txt
│ └── test.txt
└── tests
└── ...
If you want to use relative imports you need to import it this way
from .core.models import TimeStampedModel
This would take the relative path from which the code is being executed, unlike absolute imports which are not supported in Django 1.8
Related
I have a Django 2.0 project using celery 4.2.1 and redis 2.10.6. The django project has two apps, memorabilia and face_recognition. I have it all successfully running tasks with django running on my development machine. I uploaded everything to my git server, then installed the apps on my laptop from git, updated all requirements, etc. Both are Ubuntu machines. I am not using django-celery.
When I try to run celery -A MemorabiliaJSON worker -l debug,
I get an exception saying ModuleNotFoundError: No module named 'face_recognition.tasks'
I am not sure how to fix this, as the same code base is running on my development machine.
My file structure is:
├── celery.sh
├── face_recognition
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ ├── models.py
│ ├── __pycache__
│ ├── tasks.py
│ ├── tests.py
│ └── views.py
├── __init__.py
├── manage.py
├── memorabilia
│ ├── admin.py
│ ├── apps.py
│ ├── fields.py
│ ├── fixtures
│ ├── __init__.py
│ ├── logs
│ ├── migrations
│ ├── models.py
│ ├── __pycache__
│ ├── storage.py
│ ├── tasks.py
│ ├── templates
│ ├── tests
│ ├── urls.py
│ ├── validators.py
│ ├── views.py
│ ├── widgets.py
├── MemorabiliaJSON
│ ├── celery.py
│ ├── default_images
│ ├── documents
│ ├── __init__.py
│ ├── __pycache__
│ ├── settings
│ ├── static
│ ├── urls.py
│ ├── views.py
│ ├── wsgi.py
├── __pycache__
│ ├── celery.cpython-36.pyc
│ └── __init__.cpython-36.pyc
├── requirements.txt
└── tests
MemorabiliaJSON/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 django.apps import apps
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MemorabiliaJSON.settings.tsunami')
app = Celery('MemorabiliaJSON')
app.config_from_object('django.conf:settings', namespace='CELERY')
#app.autodiscover_tasks(lambda: [n.name for n in apps.get_app_configs()])
app.autodiscover_tasks()
#app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
(memorabilia-JSON) mark#octopus:~/python-projects/memorabilia-JSON
face_recognition/__init__.py
default_app_config = 'face_recognition.apps.FaceRecognitionConfig'
memorabilia/__init__.py
default_app_config = 'memorabilia.apps.MemorabiliaConfig'
INSTALLED_APPS has these two apps
'memorabilia.apps.MemorabiliaConfig',
'face_recognition.apps.FaceRecognitionConfig',
I'm completely new for django and I'd want to list the apps of a django project, for example:
FeinCMS
I know that startapp creates the directory structure for an app. I wonder if there is either a function or a file to get the app list.
For example taking FeinCMS as an example, the repo contains:
feincms
├── AUTHORS
├── CHANGELOG.rst
├── CONTRIBUTING.rst
├── docs
│ ├── admin.rst
│ ├── advanced
│ ├── conf.py
│ ├── contenttypes.rst
│ ├── contributing.rst
│ ├── deprecation.rst
│ ├── extensions.rst
│ ├── faq.rst
│ ├── images
│ ├── index.rst
│ ├── installation.rst
│ ├── integration.rst
│ ├── Makefile
│ ├── medialibrary.rst
│ ├── migrations.rst
│ ├── page.rst
│ ├── releases
│ ├── settings.rst
│ ├── templatetags.rst
│ └── versioning.rst
├── feincms
│ ├── admin
│ ├── apps.py
│ ├── content
│ ├── contents.py
│ ├── context_processors.py
│ ├── contrib
│ ├── default_settings.py
│ ├── extensions
│ ├── __init__.py
│ ├── _internal.py
│ ├── locale
│ ├── management
│ ├── models.py
│ ├── module
│ ├── shortcuts.py
│ ├── signals.py
│ ├── static
│ ├── templates
│ ├── templatetags
│ ├── translations.py
│ ├── urls.py
│ ├── utils
│ └── views
├── LICENSE
├── MANIFEST.in
├── README.rst
├── setup.cfg
├── setup.py
└── tests
├── cov.sh
├── manage.py
├── requirements.txt
├── testapp
└── tox.ini
How can I use django to list the apps in the repo?
settings.INSTALLED_APPS is the list of apps. You can start a django shell (manage.py shell) to query the settings:
from django.conf import settings
print(settings.INSTALLED_APPS)
>>> ['user', 'django.contrib.auth', 'django.contrib.sites', ...]
Query django.apps ...
from django.apps import apps
for app in apps.get_app_configs():
print(app, app.name, app.label)
Results in ...
<ContentTypesConfig: contenttypes> django.contrib.contenttypes contenttypes
<AdminConfig: admin> django.contrib.admin admin
This is my project structure:
├── run.py
└── test_blueprint
├── __init__.py
├── __init__.pyc
├── mainsite
│ ├── controllers
│ │ ├── controllers.py
│ │ ├── controllers.pyc
│ │ ├── __init__.py
│ │ └── __init__.pyc
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── static
│ │ ├── css
│ │ │ ├── bootstrap.min.css
│ │ │ └── signin.css
│ │ └── js
│ └── templates
│ └── mainsite
│ └── homepage.html
├── static
│ ├── css
│ │ ├── bootstrap.min.css
│ │ └── signin.css
│ └── js
├── templates
│ └── mainsite
│ └── index1.html
└── usermanagement
├── controllers
│ ├── controllers.py
│ ├── controllers.pyc
│ ├── __init__.py
│ └── __init__.pyc
├── __init__.py
├── __init__.pyc
├── static
└── templates
Here I have two blueprints, mainsite and usermanagement. I have registered them in file __init__.py under the test_blueprint folder which is the main folder (one below the blueprint_project folder which has run.py).
__init__ file under test_blueprint
from flask import Flask
app = Flask(__name__)
from test_blueprint.mainsite.controllers.controllers import mod
from test_blueprint.usermanagement.controllers.controllers import mod
app.register_blueprint(mainsite.controllers.controllers.mod, url_prefix="/")
app.register_blueprint(usermanagement.controllers.controllers.mod, url_prefix="/usermanagement")
Now post that I have under each blueprint folder I have created __init__.py in which I have defined Blueprints along with template folder. However, it does not take the template from there. It keeps on throwing error 'template not found'. So, I have created template folder under test_blueprint folder. It perfectly picks index.html from templates/mainsite folder.
Also, if I provide /home/user/flaskenv/blueprint_project/... templates folder which is an absolute path for my template under blueprint folder, it works fine.
Not sure if the bug is in Flask. I saw a video on YouTube and expected my flask project to behave the same. Unfortunately it didn't.
This is what my controller.py/views.py file looks like for mainsite:
from flask import Blueprint, render_template, url_for
mod = Blueprint('mainsite', __name__, static_folder='static',template_folder='templates')
#mod.route("/")
def home():
return render_template('mainsite/homepage.html')
Now if I used os.path.abspath to locate the template folder under the blueprint folder, and then passed that path as variable to template_folder, it works fine.
Now my expectation as per flask documentation is that just mentioning template_folder='templates' should automatically locate templates under the blueprint folder or it entirely defeats the purpose.
I solved by renaming the html file by unique name
Eclipse Neon (4.6.0).
PyDev for Eclipse 5.1.2.201606231256
I have created a Django project:
File / New / Project / PyDev Django project
Selected "Add project directory to the PYTHONPATH".
Now I have this folder structure.
(django_comments) michael#ThinkPad:~/workspace/formsets$ tree
.
└── formsets
├── db.sqlite3
├── formsets
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── home_page
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ └── __init__.cpython-35.pyc
│ ├── models.py
│ ├── __pycache__
│ │ ├── admin.cpython-35.pyc
│ │ ├── __init__.cpython-35.pyc
│ │ ├── models.cpython-35.pyc
│ │ └── views.cpython-35.pyc
│ ├── templates
│ │ └── home_page
│ │ └── home_page.html
│ ├── tests.py
│ └── views.py
└── manage.py
In prjoect properties in PyDev-PYTHONPATH at the tab Source Folders I have:
/${PROJECT_DIR_NAME}
In home_page/views.py I have created HomePageView. And in urls.py I would like to import it:
from home_page.views import HomePageView
The problem is:
1) HomePageView is underlined with red line. Error is Unresolved import: HomePageView.
2) Code completion is not working.
By the way, if I run the project, it works. That HomePageView shows what was expected.
Could you help me understand what have I done wrongly.
Try to add a path to the directory where your manage.py file is located. So I'm guessing it to add:
/${PROJECT_DIR_NAME}/formsets
So I have a flask app structured in this manner
calvin % tree -L 3 .
.
├── README
├── alembic
│ ├── README
│ ├── env.py
│ ├── env.pyc
│ ├── script.py.mako
│ └── versions
├── alembic.ini
├── api.sublime-project
├── app
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── admin
│ │ ├── __init__.py
│ │ └── __init__.pyc
│ ├── agencies
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── models.py
│ │ └── models.pyc
│ ├── agents
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── models.py
│ │ ├── models.pyc
│ │ ├── views.py
│ │ └── views.pyc
│ ├── api.py
│ ├── api.pyc
│ ├── auth
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── constants.py
│ │ ├── constants.pyc
│ │ ├── decorators.py
│ │ ├── decorators.pyc
│ │ ├── models.py
│ │ ├── models.pyc
│ │ ├── views.py
│ │ └── views.pyc
│ ├── districts
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── models.py
│ │ ├── models.pyc
│ │ ├── views.py
│ │ └── views.pyc
│ ├── helpers.py
│ ├── helpers.pyc
│ ├── middleware.py
│ ├── middleware.pyc
│ ├── models.py
│ ├── models.pyc
│ ├── properties
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── models.py
│ │ └── models.pyc
│ ├── templates
│ │ └── index.html
│ ├── users
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── models.py
│ │ ├── models.pyc
│ │ ├── views.py
│ │ └── views.pyc
│ └── viewings
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── models.py
│ ├── models.pyc
│ ├── views.py
│ └── views.pyc
├── config.py
├── config.pyc
├── manage.py
├── requirements.txt
├── run.py
└── shell.py
I am setting up my shell so that it auto-imports all the classes located in the models.py files when I execute ./manage.py shell
And this is the script in manage.py that is intended to achieve that (reference flask-script docs)
def _make_context():
from app import models
return dict(app=app, db=db, models=models) # TODO: this is not working appropriately
manager.add_command("shell", Shell(make_context=_make_context))
In my app/models.py, I have import statements from every module, "agencies", "auth" etc etc.
However, when I enter my shell environment, I have to access my classes as models.Users instead of directly Users, which is not what I am expecting. How do I auto-import everything so that I can access the classes directly?
Below is a simplified solution that assumes you're using SQLAlchemy (db.Model). If not, you should only need to change the issubclass if-statement to match your appropriate check of what to import.
from app import db, create_app
import app.models as models
from flask.ext.script import Manager, Shell
app = create_app()
manager = Manager(app)
def make_shell_context():
return_dict = {}
# grab everything we can possibly import from the models module
module_importables = dir(models)
for importable in module_importables:
# if it isn't a class, it'll throw a TypeError exception that importable is not a class
try:
# we only want our SQLAlchemy models
if issubclass(getattr(models,importable),db.Model):
return_dict[importable] = getattr(models,importable)
except TypeError as inst:
pass
return_dict['app'] = app
return_dict['db'] = db
return return_dict
manager.add_command("shell", Shell(make_context=make_shell_context))
if __name__ == '__main__':
manager.run()
Instead of
from app import models
You can do:
from app.models import *
This will import all classes,variables from models. Note: It is usually not recommended to import * but in this case, it could work for you. Ideally, you should do something like:
from app.models import Users, ...and so on