This project is a Django‑based web application that integrates with OpenAI to provide a chatbot experience through a browser UI.
The app runs as a standard Django project (django_chatbot) with a chatbot app, served by Gunicorn behind NGINX in Docker. Static files are collected into staticfiles and served directly by NGINX.
The repository includes:
- A Dockerfile for building the Django application image
- A
docker-compose.ymlstack with a Django/Gunicorn container and an NGINX reverse proxy - Basic NGINX configuration under
./nginx
To enable HTTPS support, you will need to extend the NGINX configuration with SSL directives and provide certificates (see HTTPS / TLS).
Note Some operational details (for example, exact OpenAI model names or advanced deployment guidance) are intentionally left as TODOs where they are not explicitly configured in this repository.
- Language: Python 3.11 (Docker base image); supports Python
>=3.9.13perpyproject.toml - Web framework: Django 4.2.2 (
django_chatbotproject,chatbotapp) - ASGI/WSGI server: Gunicorn
- Reverse proxy / static: NGINX
- Database: SQLite (file
db.sqlite3, configurable viaDJANGO_DB_PATH) - OpenAI integration:
openaiPython SDK (v2.x) - Markdown rendering:
markdown+pymdown-extensions - Containerization: Docker + docker‑compose
- Dependency management:
requirements.txtfor runtimepyproject.toml(PEP 621 metadata, alternative dependency declaration)
Local (no Docker)
- Python 3.11 (recommended; matches Docker image)
- pip
- (Optional but recommended) virtualenv (
python -m venv)
Docker setup
- Docker
- docker‑compose
git clone https://github.com/yourgithubusername/django-openai-chatbot.git
cd django-openai-chatbotYou can rename the Git remote/URL to your fork as needed.
python3.11 -m venv .venv
source .venv/bin/activateOn Windows (PowerShell):
python -m venv .venv
.venv\Scripts\Activate.ps1pip install --upgrade pip
pip install -r requirements.txtAt minimum for development:
export DJANGO_DEBUG=True
export OPENAI_API_KEY=sk-... # required if you want to call the OpenAI APIOptional environment variables are described in Environment variables.
You can set these in your shell profile (.bashrc, .zshrc, etc.) or use a .env loader of your choice (not provided by default).
python manage.py migrate
python manage.py collectstatic --no-inputpython manage.py runserver 0.0.0.0:8000Open your browser at:
The recommended way to run the full stack (Django via Gunicorn behind NGINX) is via docker-compose.
export OPENAI_API_KEY=sk-...You may also export DJANGO_DEBUG=True if you want debug settings inside the container, but this is not strictly required for basic usage.
docker-compose up --buildThis will:
- Build the
django_appimage using the provided Dockerfile - Start
django_appwith Gunicorn using/app/gunicorn.conf.py - Start an
nginxcontainer listening on port8888 - Mount
./staticfilesinto the NGINX container for static assets
Once containers are up, access the application via NGINX at:
For development, you may want to run Django’s development server instead of Gunicorn inside the django_app container. One option is to temporarily override the command in docker-compose.yml:
services:
django_app:
command: python manage.py runserver 0.0.0.0:8000Then start the stack:
docker-compose upTODO: Provide a dedicated
docker-compose.override.ymlexample for dev mode.
- Django management:
manage.py- Example:
python manage.py runserver 0.0.0.0:8000
- Example:
- Gunicorn (Docker):
- Defined in
docker-compose.yml:gunicorn -c /app/gunicorn.conf.py django_chatbot.wsgi:application --bind 0.0.0.0:8000
- Defined in
- Container entrypoint:
entrypoint.sh- Collects static files and runs migrations the first time
db.sqlite3is absent, then execs the container command.
- Collects static files and runs migrations the first time
- Local Gunicorn helper script:
start_gunicorn.sh- Activates a local virtualenv (
.venv) and starts Gunicorn withgunicorn -c ./gunicorn.conf.py django_chatbot.wsgi:application --bind 0.0.0.0:8000 --workers 3
- This script assumes a particular directory layout and shell configuration; adjust it to your environment or treat it as an example.
- Activates a local virtualenv (
The following environment variables are read by the project (see django_chatbot/settings.py and docker-compose.yml):
-
DJANGO_SECRET_KEY- Secret key for Django.
- If not set, a random key is generated at startup (suitable for local development only).
-
DJANGO_DEBUG- Set to the string
Trueto enable Django DEBUG mode. - Example:
export DJANGO_DEBUG=True
- Set to the string
-
DJANGO_DB_PATH- Optional; directory path for the SQLite database.
- If set, Django uses
<DJANGO_DB_PATH>/db.sqlite3if it exists; otherwise it falls back to<BASE_DIR>/db.sqlite3.
-
OPENAI_API_KEY- Required to make outbound OpenAI requests.
- Passed into the Django container in
docker-compose.yml.
TODO: Document any additional OpenAI‑specific settings (e.g., default model, temperature) if configuration is added in the codebase.
The project uses Django’s built‑in test runner (no pytest).
python manage.py test -v 2At the time of writing, there is a single test class in chatbot/tests.py:
FiltersTest.test_markdown_output— checks the HTML produced by themarkdown_to_htmltemplate filter.
Known issue: This test is currently failing due to strict HTML expectations that may not match the exact output of the Markdown renderer. See
chatbot/tests.pyandchatbot/templatetags/custom_filters.pybefore relying on it as a regression test.
python manage.py test chatbot.tests.FiltersTest -v 2
python manage.py test chatbot.tests.FiltersTest.test_markdown_output -v 2- There is both a module
chatbot/tests.pyand a package directorychatbot/tests/. - In Python, the module
chatbot.testsshadows the packagechatbot/tests/, so Django will not discover tests insidechatbot/tests/via labels likechatbot.tests.test_smoke.
Current recommendations for adding tests:
- Add new tests to
chatbot/tests.pyor create new top‑level modules such aschatbot/test_*.py. - Run them with labels like:
python manage.py test chatbot.test_example -v 2
TODO: Refactor the tests layout (for example, rename
chatbot/tests.pytochatbot/test_filters.py) so thatchatbot/tests/can be used as a proper package.
Inside the Django app container:
docker-compose run --rm django_app python manage.py test -v 2
docker-compose run --rm django_app python manage.py test chatbot.tests.FiltersTest -v 2The test database uses SQLite (in memory by default) for speed.
High‑level layout (non‑exhaustive):
django-openai-chatbot/
├── chatbot/ # Django app with chatbot views, models, templates, tests
│ ├── management/ # Custom management commands (if any)
│ ├── migrations/ # Django migrations
│ ├── templatetags/ # Custom template tags/filters (e.g., markdown_to_html)
│ ├── tests.py # Main test module (currently shadows chatbot/tests/)
│ └── tests/ # Additional tests (not fully wired due to module name clash)
├── django_chatbot/ # Django project configuration (settings, URLs, WSGI)
├── templates/ # HTML templates
├── static/ # Source static assets (CSS, JS, images)
├── staticfiles/ # Collected static files (built via collectstatic)
├── nginx/ # NGINX configuration
├── certs/ # Certificate-related directories (hooks; certs not included)
├── Dockerfile # Django application image definition
├── docker-compose.yml # Multi‑container stack (Django + NGINX)
├── gunicorn.conf.py # Gunicorn configuration
├── entrypoint.sh # Container entrypoint script
├── start_gunicorn.sh # Helper script for running Gunicorn locally
├── manage.py # Django management script
├── requirements.txt # Runtime dependencies
├── pyproject.toml # Project metadata and dependencies
├── LICENSE # MIT license
└── README.md # This file
TODO: Document key Django views, URL routes, and templates once the chatbot UI and API surface are finalized.
-
Static files
STATIC_URL = '/static/'STATIC_ROOT = BASE_DIR / 'staticfiles'STATICFILES_DIRS = [ BASE_DIR / 'static' ]- In the Docker stack, NGINX serves
/static/from/app/staticfiles, which is mapped to./staticfileson the host.
-
Gunicorn
- Started in Docker with:
gunicorn -c /app/gunicorn.conf.py django_chatbot.wsgi:application --bind 0.0.0.0:8000
- Logging: access and error logs go to stdout/stderr; log level is
errorby default; timeout is 120s.
- Started in Docker with:
-
NGINX
- Listens on port
8888, proxies todjango_app:8000. - Static location
/static/is mapped to/app/staticfiles.
- Listens on port
To enable HTTPS support with NGINX you will need to:
-
Obtain TLS certificates (for example via Let’s Encrypt or another CA).
-
Mount the certificates into the NGINX container (e.g., under
/etc/letsencrypt). -
Update the NGINX configuration in
nginx/default.confto include directives such as:ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem;
-
Enable the SSL server block and redirect HTTP to HTTPS as required.
Consult the official NGINX documentation for detailed SSL/TLS configuration options.
TODO: Provide a concrete example
default.confwith SSL blocks enabled and documented volume mounts for certificates.
Contributions are welcome. A typical workflow is:
- Fork this repository.
- Create a new branch:
git checkout -b feature/my-feature. - Make your changes and add tests where appropriate.
- Run the test suite:
python manage.py test -v 2(or the relevant subset). - Commit with a descriptive message:
git commit -m "Describe your change". - Push to your fork:
git push origin feature/my-feature. - Open a Pull Request against the main repository.
For more details, see GitHub’s documentation on creating a pull request.
This project is licensed under the MIT License.
Copyright © 2024 Alexey Bogomolov
