Install poetry with the install-poetry.py script or with pip. Read the documentation about the pros/cons of each method.
You can create a new project by using the poetry new
command.
poetry new django-poetry-example
The project will have the following structure.
django-poetry-example
├── README.rst
├── django_poetry_example
│ └── __init__.py
├── pyproject.toml
└── tests
├── __init__.py
└── test_django_poetry_example.py
Poetry uses a pyproject.toml
to configure the package.
It stores the meta data, dependencies and configurations of the package.
When you get into the project folder you can start using the poetry command for several tasks such as managing dependencies, running scripts or building the package.
cd django-poetry-example
I had to update poetry's pytest version from the default to avoid a TypeError with python 3.10.
poetry add pytest^7.1
Install django
poetry add django^4.0
After installing django you can use django-admin to create the project. Be aware that you have to either enter the projects shell or use the poetry run command to use this instance of django.
poetry shell
cd django_poetry_example
django-admin startproject project .
or
poetry run django-admin startproject project ./django_poetry_example/
This will add the project named "project" inside the django_poetry_example directory.
django-poetry-example
├── README.rst
├── django_poetry_example
│ ├── __init__.py
│ ├── manage.py
│ └── project
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── poetry.lock
├── pyproject.toml
└── tests
├── __init__.py
└── test_django_poetry_example.py
I prefer the generic name "project" because I find it easier to find when there are tons of django apps around. I also prefer to have the django code in a subdirectory and not mixed with other stuff that is in the poetry root folder.
The downside of the extra directory is that manage.py is not in the root level. You also have to point pytest to the correct directory. Finally editors like pycharm need a hint too for auto-importing modules.
cp django_poetry_example/manage.py .
Alter the new manage.py to change the working directory before running any subcommand.
root = os.path.join(os.getcwd(), "django_poetry_example")
sys.path.insert(0, root)
os.chdir(root)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
You can configure pytest in the tool.pytest.ini_options
section of the pyproject.toml file.
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "django_poetry_example.project.settings"
pythonpath = "django_poetry_example"
If you are using pycharm you should mark the django_poetry_example
directory as "Sources" in the "Project Structure" configuration.
You can assign python functions to commands which can be called in the shell directly or outside the shell with poetry run
[tool.poetry.scripts]
server = "scripts:run_server"
shell = "scripts:shell_plus"
manage = "scripts:manage"
After updating the local installation with poetry install
the command server
would call the run_server function from the scripts.py file.
To use pytest with django install the pytest-django package as development dependency.
It offers some usefull fixtures like rf
, client
, db
poetry add -D pytest-django
Although django creates a test.py file for every app I prefer to keep tests inside the test directory.
So a django project containing two apps pizza
and restaurant
would look like this.
django-poetry-example
├── README.rst
├── django_poetry_example
│ ├── __init__.py
│ ├── manage.py
│ ├── pizza
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── migrations
│ │ │ ├── 0001_initial.py
│ │ │ └── __init__.py
│ │ ├── models.py
│ │ └── views.py
│ ├── project
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── restaurant
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ └── views.py
├── manage.py
├── poetry.lock
├── pyproject.toml
├── scripts.py
└── tests
├── __init__.py
├── conftest.py
├── pizza
│ ├── fixtures.py
│ └── test_pizza.py
├── restaurant
│ ├── fixtures.py
│ └── test_restaurants.py
└── test_django_poetry_example.py
Usually you put fixtures in a conftest.py file next to the tests files. Those fixtures are only available in that folder and below.
So to avoid declaring all fixtures that might be used in multiple apps in the roots conftest.py I define common fixtures like
model factories in a separate fixtures.py
file. You have to add those files to the roots conftest.py to have them always accessible.
pytest_plugins = ("tests.pizza.fixtures", "tests.restaurant.fixtures")