Pytest Django Importing apps issues - python

I have a question regarding pytest and django 3.1. I have an app structure like that:
main_app
├── config
│   └── settings
│   └── base.py / local.py / prod.py
├── main_app
│   ├── sub_apps
│   │   └── models.py tests.py apps.py views.py etc...
│   ├── templates
│   │   ├── account
│   │   ├── sub_apps
│   │   ├── pages
│   │   ├── userpreferences
│   │   └── users
│   ├── userpreferences
│   │   └── models.py tests.py apps.py views.py etc...
│   ├── users
│   │   └── tests --> test_models.py test_views.py test_forms.py etc...
│   └── utils
└── requirements
Following the structure of pydanny/cookiecutter.
With this cookiecutter, the preferred test method is via pytest. But pytest is giving me a bunch of headaches:
In my settings, INSTALLED_APPS I register sub_apps within the
LOCAL_APPS =["sub_app_1", "sub_app_2", ...]
When I start django, everything is fine. But if I want to run tests, pytest is complaining heavily, it can't import the sub_app modules.
I suspect mixed up relative and absolute import paths but am not seeing how to solve this atm.
As a background: I use a separate userpreferences model which is imported in the settings via
LOCAL_APPS = ["main_app.userpreferences.apps.UserpreferencesConfig"]
In the apps.py I have to define the app name as
name = "main_app.userpreferences"
Otherwise I get an Runtime error stating the Model class does'nt declare an explicit app_label / is not installed in INSTALLED_APPS.
While django runs just fine with these imports, pytest exits before running tests with:
ModuleNotFoundError: No module named "sub_app_1"
I tried to change every import of modules in the sub_apps to e.g.:
from .sub_app_1 import models --> from main_app.sub_app_1 import models
but then django won't run anymore while the tests seem to run (pytest is starting and telling me 5/7 tests passed, while also occasionally printing import errors)
How do I resolve this?

Related

Python ModuleNotFoundError: No module named 'xxx'

Pycharm imports works correctly, but when I execute test_settings.py in the terminal, I have this error:
ImportError while importing test module '/home/ed/PycharmProjects/TTime/tests/test_settings.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_settings.py:3: in
from ttime import app, db
E ModuleNotFoundError: No module named 'ttime'
Here is my Flask project structure. I tried to include init.py in the main folder and in the tests folder, but nothing changes. It seems like somethings is wrong with python paths.
.
├── config.py
├── README.md
├── requirements.txt
├── runserver.py
├── tests
│   ├── functional
│   │   └── __init__.py
│   ├── pytest.ini
│   ├── test_settings.py
│   └── unit
│   ├── __init__.py
│   └── test_models.py
└── ttime
├── __init__.py
├── models.py
├── routes.py
├── static
└── templates
├── base.html
└── index.html

Django cannot setup when not using manager

I am having a strange issue, hopefully someone has encountered it before.
I have a custom script located at my_project/my_app/scripts/custom_script.py -- My desired use case is to feed this script a filepath and have it process the file and load/modify some data within my database.
Here is a snippet from that script:
import django
def setup_django(env):
if env == 'dev':
settings = "my_project.my_project.dev_settings"
elif env == 'stg':
settings = "my_project.my_project.staging_settings"
elif env == 'prod':
settings = "my_project.my_project.prod_settings"
else:
raise ValueError("Invalid choice for --env argument: {}".format(env))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings)
django.setup()
def main():
env = 'dev'
setup_django(env)
# Do stuff with my script
When I run the above from within the same virtualenv as my project, I get the error ModuleNotFoundError: No module named 'my_app'
Inside the settings file:
...
INSTALLED_APPS = [
'my_app',
'django.contrib.admin',
'django.contrib.auth',
...
]
...
It seems that, when I call django.setup(), it goes and parses my my dev_settings file and finds my_app in the INSTALLED_APPS list, then tries to import it directly (e.g. import my_app). This will never work, because my_app is a sub-module of my_project (should be import my_project.my_app). Here is a sample of the directory structure:
my_project
├── my_project
│   ├── __init__.py
│   ├── dev_settings.py
│   ├── prod_settings.py
│   ├── staging_settings.py
│   ├── urls.py
│   └── wsgi.py
├── my_app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── scripts
│   │   ├── __init__.py
│   │   ├── **custom_script.py**
│   │   └── utils.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── __init__.py
└── manage.py
This settings file seems to work fine with manage.py, both in runserver and shell (can find the my_app application just fine). However inside the custom_script.py all seems lost.
Any ideas?
Use management commands to add custom scripts to your app so that all django configs get loaded up correctly.
In your my_app folder, create folder structure below
management/
__init__.py
commands/
__init__.py
my_command.py
In my_command.py
from django.core.management import BaseCommand
class Command(BaseCommand):
def handle(self, *args, **options):
print('running custom command')
on your shell
python manage.py my_command

Django 1.8 No module named front

Here is my project folder structure.
<pre>
front
├── __init__.py
├── __init__.pyc
├── manage.py
├── middleware.py
├── settings.py
├── news
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── admin.py
│   ├── admin_views.py
│   ├── models.py
│   ├── search_indexes.py
│   ├── search_sites.py
│   ├── utils.py
│   ├── views.py
</pre>
After I run
./manage.py runserver
then I visit http://127.0.0.1:8000/
It gives me error:
No module named front
This is caused by the following line in file views.py under news folder.
from front import settings
So the front folder is one level up to the views.py file. How I import the settings from one level up folder?
Thanks!
Either way this is wrong, whenever you're importing your own settings you should be importing from django.conf
from django.conf import settings
This isn't a module, its an object that does magic to import any settings you have set in your DJANGO_SETTINGS_MODULE
From the docs:
Also note that your code should not import from either global_settings or your own settings file. django.conf.settings abstracts the concepts of default settings and site-specific settings; it presents a single interface. It also decouples the code that uses settings from the location of your settings.

Importing app when using Alembic raises ImportError

I am trying to study how to use alembic in flask, I want to import a method in flask app:
tree .
.
├── README.md
├── alembic
│   ├── README
│   ├── env.py
│   ├── env.pyc
│   ├── script.py.mako
│   └── versions
│   ├── 8f167daabe6_create_account_table.py
│   └── 8f167daabe6_create_account_table.pyc
├── alembic.ini
├── app
│   ├── __init__.py
│   ├── main
│   │   ├── __init__.py
│   │   ├── errors.py
│   │   ├── forms.py
│   │   └── views.py
│   ├── models.py
│   └── templates
│   ├── 404.html
│   ├── 500.html
│   ├── base.html
│   ├── index.html
│   └── user.html
├── config.py
├── data.sqlite
├── manage.py
└── requirements.txt
in app/__init__.py:
def create_app(config_name):
app = Flask(__name__)
I want to import create_app in env.py:
from app import create_app
but the error shows as below when I run the command alembic upgrade head:
File "alembic/env.py", line 5, in <module>
from app import create_app
ImportError: No module named app
Any idea for this?
I guess you are trying to run
python env.py
In this case, your app directory is not in PYTHONPATH.
solution 1
Run the app from parent dir:
python alembic/env.py
solution 2
Set the PYTHONPATH before running the app
PYTHONPATH=/path/to/parent/dir python env.py
edit
I read about alembic. As #mrorno said, just set the PYTHONPATH before running alembic:
PYTHONPATH=. alembic upgrade head
alembic just tries to load your env.py source code. It's not in your package, so it can't access your app module.
Use solution 2 #tomasz-jakub-rup suggested, you can execute like
$ PYTHONPATH=. alembic upgrade head
and you should get your result.
Create file .env and insert PYTHONPATH=.

Backporting from 3 to 2.7: ImportError: cannot import name

After reading this, and crying a lot, I'm trying to make my Django app work with Python 2.7.
Here's my Django web dir:
├── locale
│   ├── en
│   ├── fr
│   └── sv
├── produits
│   ├── migrations
│   └── templatetags
├── pyweb
├── templates
│   └── produits
├── third_party
│   ├── authomatic_0_1_0
│   ├── defusedxml-0.4.1
│   ├── google_appengine_1_9_25
│   ├── python-openid_2_2_5
│   └── python3-openid
└── uploads
The most important to notice is that I've tried to add all my "external" module into a folder third_party.
In my views.py, the following code was working:
from third_party.authomatic_0_1_0 import authomatic
from third_party.authomatic_0_1_0.authomatic import adapters
from third_party.authomatic_0_1_0.authomatic.providers import oauth1, oauth2
It was working because I added those lines in settings.py at the very beginning:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR+'/third_party/defusedxml-0.4.1')
sys.path.append(BASE_DIR+'/third_party/python3-openid')
sys.path.append(BASE_DIR+'/third_party/google_appengine_1_9_25')
sys.path.append(BASE_DIR+'/third_party/authomatic_0_1_0')
But now, with python 2.7 it doesnt work anymore. What should I do to make it work? And what is a good practice in Python (because Pycharm doesn't recognize all the subfolders of third_party)?
Two problems: (1) encoding, so I added in all files at the very beginning:
# coding=UTF-8
(2) Decorator python_2_unicode_compatible: needed this for all my models with __str__ implemented, for example:
#python_2_unicode_compatible
class Texte(models.Model):
texte = models.CharField(max_length=200)
def __str__(self):
return self.texte
See here for more information

Categories