Django project dependencies are normally installed with a simple
pip install myapp
But if you want to be a code contributor to a dependency such as a reusable Django app (or if you are writing one), the usual pattern is to:
git clonethat app to another directory, outside of your project
- From within your project dir, use
pip install -e /path/to/the/clone
This creates a
foo.pth link and/or a
foo.egg-link in your project’s virtualenv, rather than copying the code into the project itself, so you can work on the separate repo and have changes reflected in your project in real time.
That’s all well and good, but if you use pytest and need to run tests in the dependency, just running
pytest from your project dir won’t find tests that live in the dependency. So can’t you just run
pytest from within the dependency’s directory? Not quite – since it’s a Django app, it’s going to assume access to Django itself, and likely to other apps installed in the Django project, such as
users. It would be redundant and cumbersome to install Django in the dependency’s directory, and that still wouldn’t solve the problem of access to
I can’t seem to find mention anywhere of a “best-practice” solution to this dilemma, but after much futzing around and feeling like I must be missing something obvious I tried what should have been plain from the outset:
- From the project dir,
pip uninstall myapp
- From the project dir, create a symlink:
ln -s /path/to/the/clone myapp
Now the separate reusable app appears to Django and to pytest like it’s present in the project, while maintaining physical separation between the project and the dependency. Tests run, and there’s no confusion. Just be sure to
.gitignore the symlink.
There’s a gotcha to look out for here: Typically, a reusable app called “myapp” will live in a parent folder that’s also called “myapp”. If you make your symlink to the top-level folder, the imports inside it will not work. You’ll want to create your symlink to the inner folder, e.g.:
ln -s /Users/yourname/dev/myapp/myapp .
Unless I’m mistaken about something, a simple symlink (rather than
pip install -e appears to be the easiest way to organize the relationship.