Package Installation Not working with uv, ModuleNotFoundError: No module named 'rest_framework'

Author: dkcshivamCreated Oct 11, 2025Updated Nov 6, 2025

Hi,

Steps to Recreate:

  1. Initialize a project using cookiecutter.
  2. Choose docker as yes
  3. build and run the project, it will work
  4. add a new package in the pyproject.toml (eg:djangorestframework)
  5. run docker compose -f docker-compose.local.yml run --rm django uv lock
  6. build the image again
  7. run the container, it will work.
  8. Now go into the config/settings/base.py file and put "rest_framework", inside THIRD_PARTY_APPS.
  9. build the image
  10. run the container, you will see error. ModuleNotFoundError: No module named 'rest_framework'I installed rest framework just for dummy, I know we can directly install it from the cookiecutter, in all of my recent projects with cookiecutter , whenever I try to use a new package it doesn't work. Seems like it's not getting installed inside the environment. In the 6th step when I went into the bash of the container and did pip freeze it did not showed rest_framework, so I knew that it will fail in the 7,8 and 9 steps.

Seems like some issue with the docker compose / docker file . Not sure exactly about it.

Earlier when pip was being used to install packages it was working like them. Here are the details.

My configurations:

Machine: Macbook Pro Chip: Apple M3 Max Memory: 48 GB macOS: Tahoe 26.0

Docker version 28.5.1, build e180ab8 docker desktop: 4.48.0 (207573)

cookie-cutter version(maybe latest): 11 Oct 2025 2:44 pm from here: cookiecutter gh:cookiecutter/cookiecutter-django . And chose when prompted to download the latest.

Dockerfile ###################################################################################################### `# define an alias for the specific python version used in this file. FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python

Python build stage

FROM python AS python-build-stage

ARG APP_HOME=/app

WORKDIR ${APP_HOME}

we need to move the virtualenv outside of the $APP_HOME directory because it will be overriden by the docker compose mount

ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0

Install apt packages

RUN apt-get update && apt-get install --no-install-recommends -y \

dependencies for building Python packages

build-essential \

psycopg dependencies

libpq-dev
gettext
wait-for-it

Requirements are installed here to ensure they will be cached.

RUN --mount=type=cache,target=/root/.cache/uv
--mount=type=bind,source=pyproject.toml,target=pyproject.toml
--mount=type=bind,source=uv.lock,target=uv.lock:rw
uv sync --no-install-project

COPY . ${APP_HOME}

RUN --mount=type=cache,target=/root/.cache/uv
--mount=type=bind,source=pyproject.toml,target=pyproject.toml
--mount=type=bind,source=uv.lock,target=uv.lock:rw
uv sync

devcontainer dependencies and utils

RUN apt-get update && apt-get install --no-install-recommends -y
sudo git bash-completion nano ssh

Create devcontainer user and add it to sudoers

RUN groupadd --gid 1000 dev-user
&& useradd --uid 1000 --gid dev-user --shell /bin/bash --create-home dev-user
&& echo dev-user ALL=(root) NOPASSWD:ALL > /etc/sudoers.d/dev-user
&& chmod 0440 /etc/sudoers.d/dev-user

ENV PATH="/${APP_HOME}/.venv/bin:$PATH" ENV PYTHONPATH="${APP_HOME}/.venv/lib/python3.13/site-packages:$PYTHONPATH"

COPY ./compose/production/django/entrypoint /entrypoint RUN sed -i 's/\r$//g' /entrypoint RUN chmod +x /entrypoint

COPY ./compose/local/django/start /start RUN sed -i 's/\r$//g' /start RUN chmod +x /start

ENTRYPOINT ["/entrypoint"] ` ######################################################################################################

docker-compose.local.yml file ###################################################################################################### `volumes: my_awesome_project_local_postgres_data: {} my_awesome_project_local_postgres_data_backups: {}

services: django: build: context: . dockerfile: ./compose/local/django/Dockerfile image: my_awesome_project_local_django container_name: my_awesome_project_local_django depends_on: - postgres volumes: - /app/.venv - .:/app:z env_file: - ./.envs/.local/.django - ./.envs/.local/.postgres ports: - '8000:8000' command: /start

postgres: build: context: . dockerfile: ./compose/production/postgres/Dockerfile image: my_awesome_project_production_postgres container_name: my_awesome_project_local_postgres volumes: - my_awesome_project_local_postgres_data:/var/lib/postgresql/data - my_awesome_project_local_postgres_data_backups:/backups env_file: - ./.envs/.local/.postgres ` ######################################################################################################

pyproject.toml

###################################################################################################### `# ==== pytest ==== [tool.pytest.ini_options] minversion = "6.0" addopts = "--ds=config.settings.test --reuse-db --import-mode=importlib" python_files = [ "tests.py", "test_*.py", ]

==== Coverage ====

[tool.coverage.run] include = ["my_awesome_project/**"] omit = ["/migrations/", "/tests/"] plugins = ["django_coverage_plugin"]

==== mypy ====

[tool.mypy] python_version = "3.13" check_untyped_defs = true ignore_missing_imports = true warn_unused_ignores = true warn_redundant_casts = true warn_unused_configs = true plugins = [ "mypy_django_plugin.main", ]

[[tool.mypy.overrides]]

Django migrations should not produce any errors:

module = ".migrations." ignore_errors = true

[tool.django-stubs] django_settings_module = "config.settings.test"

==== djLint ====

[tool.djlint] blank_line_after_tag = "load,extends" close_void_tags = true format_css = true format_js = true

TODO: remove T002 when fixed https://github.com/djlint/djLint/issues/687

ignore = "H006,H030,H031,T002" include = "H017,H035" indent = 2 max_line_length = 119 profile = "django"

[tool.djlint.css] indent_size = 2

[tool.djlint.js] indent_size = 2

[tool.ruff]

Exclude a variety of commonly ignored directories.

extend-exclude = [ "/migrations/.py", "staticfiles/*", ]

[tool.ruff.lint] select = [ "F", "E", "W", "C90", "I", "N", "UP", "YTT", # "ANN", # flake8-annotations: we should support this in the future but 100+ errors atm "ASYNC", "S", "BLE", "FBT", "B", "A", "COM", "C4", "DTZ", "T10", "DJ", "EM", "EXE", "FA", 'ISC', "ICN", "G", 'INP', 'PIE', "T20", 'PYI', 'PT', "Q", "RSE", "RET", "SLF", "SLOT", "SIM", "TID", "TC", "INT", # "ARG", # Unused function argument "PTH", "ERA", "PD", "PGH", "PL", "TRY", "FLY", # "NPY", # "AIR", "PERF", # "FURB", # "LOG", "RUF", ] ignore = [ "S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/ "RUF012", # Mutable class attributes should be annotated with typing.ClassVar "SIM102", # sometimes it's better to nest # of types for comparison. # Deactivated because it can make the code slow: # https://github.com/astral-sh/ruff/issues/7871 ]

[tool.ruff.lint.isort] force-single-line = true

[dependency-groups] dev = [ "coverage==7.10.7", "django-coverage-plugin==3.2.0", "django-debug-toolbar==6.0.0", "django-extensions==4.1", "django-stubs[compatible-mypy]==5.2.7", "djlint==1.36.4", "factory-boy==3.3.2", "ipdb==0.13.13", "mypy==1.18.2", "pre-commit==4.3.0", "psycopg[c]==3.2.10", "pytest==8.4.2", "pytest-django==4.11.1", "pytest-sugar==1.1.1", "ruff==0.14.0", "sphinx==8.2.3", "sphinx-autobuild==2025.8.25", "werkzeug[watchdog]==3.1.3", ]

[project] name = "my_awesome_project" version = "0.1.0" description = "Behold My Awesome Project!" readme = "README.md"

license = { text = "MIT" } authors = [ { name = "Daniel Roy Greenfeld", email = "[email protected]" }, ] requires-python = "==3.13.*" dependencies = [ "argon2-cffi==25.1.0", "collectfasta==3.3.1", "crispy-bootstrap5==2025.6", "django==5.2.7", "django-allauth[mfa]==65.12.0", "django-anymail[mailgun]==13.1", "django-crispy-forms==2.4", "django-environ==0.12.0", "django-model-utils==5.0.0", "django-redis==6.0.0", "django-storages[s3]==1.14.6", "gunicorn==23.0.0", "hiredis==3.2.1", "pillow==11.3.0", "psycopg[c]==3.2.10", "python-slugify==8.0.4", "redis==6.4.0", "djangorestframework==3.16.1" ] `

Source: cookiecutter/cookiecutter-django