how to include tests in a distributable django app? - python

I distribute a small django app that I wanted to write a test for. It uses some settings and I was importing
from django.conf import settings
in the app file but this leaves me with a problem because the standalone app has no django project so how would one write and run tests on it?

In your app folder, create a folder named tests, and in that folder place your tests (in a single .py file or multiple files.
You will end up with a folder structure like this:
my_app/
tests/
test_views.py
test_other_stuff.py
Then you will be able to run your test suite for that app using:
`./manage.py test my_app`
Where my_app is the name of your app. As far as how to write the tests themselves, the Django docs are very helpful.

My solution was to create a django project with the name of the app and then put all the distribution files such as
setup.py
MANIFEST.in
in the project level directory and then indicate only the files I want to include with the distribution in the MANIFEST.in file.
MAINFEST.in:
include myapp/*

Related

How to tell passenger_wsgi.py to look for Django project inside another folder?

I'm trying to host a django app on cpanel but i cant find a way to tell passenger_wsgi.py to look for the django project(main file) inside another folder
My site structure is:
/home/project/
tmp/
public/
passenger_wsgi.py
abdi-group/
passenger_wsgi.py:
from abdiGroup.wsgi import application
this works fine if i move everything inside abdi-group/ to /home/project/
I tried this:
passenger_wsgi.py:
from abdi-group.abdiGroup.wsgi import application
but it can't find abdiGroup(django project name) inside abdi-group/
am i missing something?
abdiGroup is supposed to be a folder in your project directory that contains the wsgi file not abdi-group. If you're making it a subfolder add an empty __init__.py to any new folder so Django knows it is a package and can import from it.

How (or where) do I call db.create_all() in a multi-file flask project?

I have a multi-file flask project where I have a single model and a couple routes. Initially, the project was just a single app.py file and I was able to just run db.create_all() within that file. Now that I have complicated imports with my multi-file structure, I am wondering how I would go about creating the tables defined in my models.py file.
Application structure:
app/
__init__.py
config.py
extensions.py
models.py
routes.py
.env
.flaskenv
Pipfile
Pipfile.lock
I solved my problem with the following lines of code in my __init__.py file:
with app.app_context():
db.create_all()
Before, I was simply calling db.create_all() but without the application context, it was failing. More information on this can be found at:
https://flask-sqlalchemy.palletsprojects.com/en/2.x/contexts/.

Can a Python script use a Django database while not being in the same folder?

I have a python application (which we'll call app) I'd like to have a web front for. The application has many files and it's important the folder tree structure stays the way it is.
I've built a Django project and put it in a folder named "Web" in the app's folder, so now the folder tree looks like so:
[Data]
[Resources]
[Web]
[WebFront]
normal django app files
[Web]
__init__.py
settings.py
urls.py
wsgi.py
__init__.py
manage.py
main.py
Here's the code on the app's main.py:
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Web.Web.settings")
django.setup()
This code causes an exception on the django.setup() line as (I think) django does not find the project modules: ImportError: No module named WebFront (WebFront is the name of the django app)
I suspect this is caused because django runs in the directory of python app, and therefore cannot find the folder WebFront - Which should actually be Web/WebFront
Can this be done? Or should I reverse the order and put the python app in the django app?
This is not a duplicate of the following questions as the folder nesting causes a different problem (I think)
Django 1.7 throws django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet
Easiest way to write a Python program with access to Django database functionality
Using only the DB part of Django
You can locate your main.py script where you like. However, if it is outside of the Web folder, then you will have to add Web to the Python path, otherwise imports like import Webfront are going to fail.
import sys
sys.path.append('/path/to/Web/')
Once you have done that, you can change the DJANGO_SETTINGS_MODULE to
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Web.settings")

How to structure a python project with three applications that use common module

My project contains three Python applications. Application 1 is a web app. Applications 2 and 3 contain scripts downloading some data.
All three apps need to use a module Common containing a "model" (classes that are saved to database) and common settings.
I have no clue how to structure this project. I could create three directories, one for each application, and copy Common three times into their directories (doesn't seem right).
Another idea that comes to mind is; create a main directory and put there all files from Common, including __init__.py. Then, crete three subdirectories (submodules), one for each application.
Another way would be installing Common using pip, but that means I would have to reinstall every time I change something in that module.
In previous projects I used .NET - the equivalent in that world would be a Solution with four projects, one of them being Common.
Any suggestions?
I have a similar project that is set up like this
project_root/
App1/
__init__.py
FlaskControlPanel/
app.py
static/
templates/
models/
__init__.py
mymodels.py
Then, I run everything from project_root. I have a small script (either batch or shell depending on my environment) that sets PYTHONPATH=. so that imports work correctly. This is done because I usually develop using PyCharm, where the imports "just work", but when I deploy the final product the path doesn't match what it did in my IDE.
Once the PYTHONPATH is set to include everything from your project root, you can do standard imports.
For example, from my FlaskControlPanel app.py, I have this line:
from models.mymodels import Model1, Model2, Model3
From the App1 __init__.py I have the exact same import statement:
from models.mymodels import Model1, Model2, Model3
I can start the Flask application by running this from my command line (in Windows) while I am in the project_root directory:
setlocal
SET PYTHONPATH=.
python FlaskControlPanel\app.py
The setlocal is used to ensure the PYTHONPATH is only modified for this session.
I like this approach
projects/
__init__.py
project1/
__init__.py
project2/
__init__.py
lib1/
__init__.py
libfile.py
lib2/
__init__.py
So, I need to cd into the projects folder.
To start a projects use
python -m project_name
This allows me to easily import from any external lib like
from lib1.libfile import [imoprt what you want]
or
from lib1 import libfile
Make standard Python modules from your apps. I recommend structure like this:
apps/
common/
setup.py
common/
__init__.py
models.py
app1/
setup.py
app1/
__init__.py
models.py
project/
requirements.txt
Basic setup.py for app common:
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(
name='common',
version='1.0.0',
packages=find_packages(),
zip_safe=False,
)
Make similar setup.py for other apps.
Set editable "-e" option for your apps in requirements.txt:
-e apps/common
-e apps/app1
Install requirements with pip:
$ pip install -r requirements.txt
Editable option means that source files will be linked into Python enviroment. Any change in source files of your apps will have immediate effect without reinstalling them.
Now you can import models from your common app (or any other app) anywhere (in other apps, project files, ...).
I would create a structure like this:
project_root/
app1/
__init__.py
script.py
common/
__init__.py
models.py (all "common" models)
app1/script.py
import os, sys
# add parent directory to pythonpath
basepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
if basepath not in sys.path:
sys.path.append(basepath)
from common.models VeryCommonModel
print VeryCommonModel
If you don't want to set the python path at runtime, set the python path before running the script:
$ export PYTHONPATH=$PYTHONPATH:/path/to/project_root
And then you can do:
python app1/script.py

Python - packages and settings file

I have a python package that needs to pull in settings from my project directory, here is how my project is currently structured:
~/Project/bin/mypackage
- package files
~/Project/myproject/
- project files
- start.py
- settings.py
I guess it's similar to how Django is structured, you have a settings.py file in your project directory that is somehow referenced by the Django system package in your Python directory.
So, if I am running start.py like so:
python ~/Project/myproject/start.py
..and start.py imports and utilizes the mypackage package, is there any way I can reference the settings.py file local to start.py from within the package? Would I have to load the settings file in start.py and store the values in a global? Does anyone know how this is possible?
The way I see it you have several options:
look for settings and import them either from the current working directory or as determined from environment variables. This is the "django way" using DJANGO_SETTINGS_MODULE and PYTHONPATH. This is nice and magical when it works and inconvenient when it doesn't such as in your case when you are running from a different directory.
rely on module search path which will include the directory of the calling package. Nice and simple but the settings will vary based on the caller. For example all you need in mypackage is:
import settings
pass in settings as a variable
The directory containing the script that was used to invoke the python interpreter is added to the PYTHONPATH. It is available at sys.path[0]. See http://docs.python.org/library/sys.html#sys.path
This means that settings should be available from mypackage.mymodule simply by import settings.
However, I would consider handling the loading of settings in start.py and structuring your app so that a settings object (perhaps just a dict) is passed to it.

Categories