Django manage.py outside of project - python

Is there a method of having manage.py outside of the Django project directory without having to change all the imports to from backend.<app>.<module> import ...?
├── project
│   ├── api
│ ├── frontend
│   ├── project
│   ├── manage.py
│ ├── Pipfile
│ ├── Pipfile.lock
├── project
│   ├── backend
│   │   ├── api
│   │   ├── project
│ │ ├── __init__.py
│ ├── frontend
│   ├── manage.py
│   ├── Pipfile
│   ├── Pipfile.lock
As expected after moving the Django project into the backend directory and modifying manage.py with the line below there's a ModuleNotFoundError when trying to run the server.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.project.settings')

To enable import api instead of import backend.api, you need to add the parent directory backend to the python path.
import sys
sys.path.append('/path/to/project/backend')
You can also use a relative path if manage.py is in /path/to/project/:
import sys
sys.path.append('backend')
You should then use
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
After making the changes, make sure you import api everywhere. Mixing import api and import backend.api can cause problems when the same modules are imported in different places. You can probably remove backend/__init__.py if you are going to stop importing backend.

Related

How does Django handle importing of apps?

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

ModuleNotFoundError: No module named 'python'

I have a python project and want to write a command line launcher. My project works fine when I run tests or launch from my IDE (pycharm). However when I try to launch via the command line I get a ModuleNotFoundError: No module named 'python' error.
Here is my directory structure:
.
├── Makefile
├── Pipfile
├── Pipfile.lock
├── README.md
├── create_jenkins_jobs.sh
└── python
├── __init__.py
├── create_credentials.py
├── create_jenkins_jobs_cli.py
├── credential_builder.py
├── jenkins_multibranch_job_builder.py
├── templates
│   ├── job.xml
│   ├── multibranch_job_template.xml
│   ├── ssh_cred_template.xml
│   └── user_pw_cred_template.xml
└── tests
├── __init__.py
├── integration
│   ├── __init__.py
│   ├── build_credential_test.py
│   ├── build_job_test.py
│   ├── conftest.py
│   ├── test_id_rsa
│   └── test_id_rsa.pub
└── unit
The shell script create_jenkins_jobs.sh contains:
#!/bin/bash
python3 python/create_jenkins_jobs_cli.py "${#}"
the file create_jenkins_jobs_cli.py contains the following code:
from typing import Set
from shared.common import preflight_env_check
from python.jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
def configure_jenkins_jobs(git_repos: Set[str]):
jenkins_job_builder = JenkinsMultibranchJobBuilder(jenkins_server_url=JENKINS_BASE_SERVER_URL,
jenkins_folder=JENKINS_ROOT_JOB_FOLDER,
user=JENKINS_USER, token=JENKINS_TOKEN,
git_cred_id=GIT_SSH_CRED_ID,
git_repos=git_repos)
jenkins_job_builder.configure_jobs()
configure_jenkins_jobs(GIT_REPOS)
When I launch create_jenkins_jobs.sh or create_jenkins_jobs_cli.py I always get
ModuleNotFoundError: No module named 'python'
$>./create_jenkins_jobs.sh
/Users/pswenson/dev/cc-cicd-automation/.venv/bin/python3: Error while finding module specification for 'python/create_jenkins_jobs_cli.py' (ModuleNotFoundError: No module named 'python/create_jenkins_jobs_cli')
I've tried all sorts of different techniques to get this to work with PYTHONPATH, working directories, etc...
It seems there is something basic about how python modules work that I don't understand.
Does changing the line:
from python.jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
to
from jenkins_multibranch_job_builder import JenkinsMultibranchJobBuilder
Sort you?

Django double import during tests

whenever I run Django tests, I fall into a double import trap with my models.
Every time I get
RuntimeError: Conflicting 'userdevice' models in application 'cart': <class 'cart.models.devices.UserDevice'> and <class 'fridge.libs.cart.models.devices.UserDevice'>
Minimal failing example is at https://www.dropbox.com/sh/m802q544cet5dui/AACRGOMQXWqxUzi92WfqfvYea?dl=0
My folder structure is
.
├── apps
│   ├── __init__.py
│   └── milk
│      ├── __init__.py
│      └── tests
│      ├── __init__.py
│      └── test_commands.py
├── __init__.py
├── libs
│   ├── cart
│   │   ├── __init__.py
│   │   └── models
│   │      ├── devices.py
│   │      └── __init__.py
│   └── __init__.py
├── Makefile
├── manage.py
└── settings
├── __init__.py
└── settings.py
I have apps and libs folders in INSTALLED_APPS.
My models/__init__.py file contains
from .devices import *
From test_commands.py I include model with
from cart.models import UserDevice
I read multiple questions here at SO and some articles on web. I was also debugging this for a few hours, so I know the problem is that my model is imported twice. Once during the Django project initialization as cart.models.devices.UserDevice and once by the unittest library as fridge.libs.cart.models.devices.UserDevice but I simply do not know how to fix this situation.
This is also causing more problems in files, which can be initialized only once during the app run, but I guess that the solution will be same as to this one.
I am using Django 1.10.8 as this is a legacy project but I experience the same on Django 2.0.7.
Python version is 3.5. OS is Ubuntu 16.04.
Thanks for any advice or hint. Nothing I found so far did not help.
Edit
So I experimented a bit and the problem persist even when no import are made in tests and even if there are no tests at all. Just running the tests will make the double import and RuntimeError happen
No-tests version: https://www.dropbox.com/sh/qqzg842rihbh5im/AADzay8up3d_rFKqy2OAsx1za?dl=0
New folder structure
.
├── __init__.py
├── libs
│   ├── cart
│   │   ├── __init__.py
│   │   └── models
│   │      ├── devices.py
│   │      └── __init__.py
│   └── __init__.py
├── Makefile
├── manage.py
└── settings
├── __init__.py
└── settings.py
Edit:
For the future's sake - content of libs/cart/models/devices.py is just simple Django model class
from django.db import models
class UserDevice(models.Model):
is_active = models.BooleanField(default=True)
class Meta:
app_label = 'cart'
I somehow "solved" the problem by deleting libs/__init__.py file. I am not sure why it was present in the project in the first place.

Python: AttributeError module x has no attribute y

I have a project with directory structure like below
.
├── Pipfile
├── Pipfile.lock
├── module
│   ├── __init__.py
│   ├── helpers
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   └── __init__.cpython-36.pyc
│   │   ├── dynamo.py
│   │   └── logger.py
│   └── test.py
Relavant code
logger.py
import click
import sys
from tabulate import tabulate
def formatter(string, *rest):
return string.format(*rest)
def info(*rest):
"""Write text in blue color
"""
click.echo(click.style('☵ ' + formatter(*rest), fg='blue'))
test.py
import helpers
helpers.logger.info('Trying')
When I try to run using the command
python3 module/test.py
I get this error
Traceback (most recent call last):
File "module/test.py", line 4, in <module>
helpers.logger.info('Trying')
AttributeError: module 'helpers' has no attribute 'logger'
I have tried restructuring the code. Putting the helpers directory outside, in level with module directory. But still it didn't work, which it should not have, from what I have read. I tried researching a bit about __init__.py and python module system. The more I read, the more confusing it gets. But from whatever I learned, I created another sample project. With the following structure,
.
└── test
├── __init__.py
├── helpers
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── quote.cpython-36.pyc
│   └── quote.py
├── index.py
├── logger
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── info.cpython-36.pyc
│   └── info.py
Code is same as first project.
Here when I do,
python3 test/index.py
It works as expected. The only difference between the two projects:
In the first project, I used pipenv to install deps and create virtual environment.
Using your initial layout (with loggers as a submodule of the helpers package), you'd need to explicitely import loggers in helpers/__init__.py to expose it as an attribute of the helpers package:
# helpers/__init__.py
from . import logger
logger is module and not attribute and helpers.logger evalutes logger as attribute. Actually you should do as follow:
from helpers import logger
print(logger.info('Trying'))

Django Project and Standalone Python project

i have the following file structure:
ihe/
├── dcmt
│   ├── actions
│   ├── calendar_observer
│   ├── cms
│   ├── consumption
│   ├── data_mining
│   ├── dcmt
│   ├── dcmt_db
│   ├── dcmt_db.bak.bak
│   ├── dcmt_db.sqlite
│   ├── devices
│   ├── d.py
│   ├── gadgets
│   ├── history
│   ├── houses
│   ├── hwc_settings
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── manage.py
│   ├── notifications
│   ├── profitable
│   ├── rules
│   └── schedule
├── hwc
│   ├── configuration
│   ├── daemons
│   ├── database
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── utils
│   └── wrapper
├── __init__.py
├── __init__.pyc
dcmt is a django project. hwc is pure python. however for instance in hwc/daemons there is a runme.py script. in that runme.py script i want to be able to import the models from the django project. Now as i understand it i have to have the correct python path and then somehow set the django settings. My question is how do i best do this so that for the whole hwc modules I only have to do that once?
Your project structure seems a bit confused.
It's probably not a good idea to have a Django project inside another package hierarchy. A lot of the import paths assume your project is in a top-level package and the only reason you're probably not running into issues already is that Python 2.x still supports relative imports (which have been removed in 3.x). This makes references to packages very ambiguous and can cause weird bugs.
From what I can see your settings package is actually called (fully-qualified) ihe.dcmt.hwc_settings. If ihe is in your Python path (check the value of sys.path in the script you're trying to run), that (i.e. the fully-qualified path) is probably what DJANGO_SETTINGS_MODULE should point at.
If you want to hook into Django's functionality in your scripts, you might want to look into the documentation for writing manage.py commands. This would let you write Django-related scripts more consistently and save you the worry about referencing and initialising Django's settings correctly yourself.

Categories

Resources