|
1 | | -# Django + D1 Template for Cloudflare Workers |
| 1 | +# Django D1 Template for Cloudflare Workers |
| 2 | + |
| 3 | +This template provides a starting point for running a Django application on Cloudflare Workers, utilizing Cloudflare D1 for serverless SQL database. |
| 4 | + |
| 5 | +[](https://deploy.workers.cloudflare.com/?url=https://github.com/G4brym/django-cf/tree/main/templates/d1) |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +This template is pre-configured to: |
| 10 | +- Use `django-cf` to bridge Django with Cloudflare's environment. |
| 11 | +- Employ Cloudflare D1 as the primary data store through the `django_cf.d1_binding` database engine. |
| 12 | +- Include a basic Django project structure within the `src/` directory. |
| 13 | +- Provide example worker entrypoint (`src/worker.py`). |
| 14 | + |
| 15 | +## Project Structure |
| 16 | + |
| 17 | +``` |
| 18 | +template-root/ |
| 19 | + |-> src/ |
| 20 | + | |-> manage.py # Django management script |
| 21 | + | |-> worker.py # Cloudflare Worker entrypoint |
| 22 | + | |-> app/ # Your Django project (rename as needed) |
| 23 | + | | |-> settings.py # Django settings, configured for D1 |
| 24 | + | | |-> urls.py # Django URLs, includes management endpoints |
| 25 | + | | |-> wsgi.py # WSGI application |
| 26 | + | |-> your_django_apps/ # Add your Django apps here |
| 27 | + | |-> vendor/ # Project dependencies (managed by vendor.txt) |
| 28 | + |-> staticfiles/ # Collected static files (after build) |
| 29 | + |-> .gitignore |
| 30 | + |-> package.json # For Node.js dependencies like wrangler |
| 31 | + |-> package-lock.json |
| 32 | + |-> requirements-dev.txt # Python dev dependencies |
| 33 | + |-> vendor.txt # Pip requirements for vendoring |
| 34 | + |-> wrangler.jsonc # Wrangler configuration |
| 35 | +``` |
| 36 | + |
| 37 | +## Setup and Deployment |
| 38 | + |
| 39 | +1. **Install Dependencies:** |
| 40 | + * **Node.js & Wrangler:** Ensure you have Node.js and npm installed. Then install dependencies with this command: |
| 41 | + ```bash |
| 42 | + npm install |
| 43 | + ``` |
| 44 | + * **Python Dependencies (Vendoring):** |
| 45 | + List your Python dependencies (including `django` and `django-cf`) in `vendor.txt`. |
| 46 | + ```txt |
| 47 | + # vendor.txt |
| 48 | + django~=5.0 |
| 49 | + django-cf |
| 50 | + tzdata # For timezone support |
| 51 | + # Add other dependencies here |
| 52 | + ``` |
| 53 | + Install them into the `src/vendor` directory: |
| 54 | + ```bash |
| 55 | + pip install -t src/vendor -r vendor.txt |
| 56 | + ``` |
| 57 | + |
| 58 | + * **Python Dependencies (Local Development):** |
| 59 | + List your Python dev dependencies (including `django` and `django-cf`) in `requirements-dev.txt`. |
| 60 | + ```txt |
| 61 | + # requirements-dev.txt |
| 62 | + django==5.1.2 |
| 63 | + django-cf |
| 64 | + # For local D1 API access during development (e.g., running migrations) |
| 65 | + # Add other dev dependencies here |
| 66 | + ``` |
| 67 | + Install them: |
| 68 | + ```bash |
| 69 | + pip install -r requirements-dev.txt |
| 70 | + ``` |
| 71 | + |
| 72 | +2. **Configure `wrangler.jsonc`:** |
| 73 | + Review and update `wrangler.jsonc` for your project. Key sections: |
| 74 | + * `name`: Your worker's name. |
| 75 | + * `main`: Should point to `src/worker.py`. |
| 76 | + * `compatibility_date`: Keep this up-to-date. |
| 77 | + * `d1_databases`: |
| 78 | + * `binding`: The name used to access the D1 database in your worker (e.g., "DB"). |
| 79 | + * `database_name`: The name of your D1 database in the Cloudflare dashboard. |
| 80 | + * `database_id`: The ID of your D1 database. |
| 81 | + * `site`: |
| 82 | + * `bucket`: Points to `./staticfiles` for serving static assets. |
| 83 | + * `build`: |
| 84 | + * `command`: `"python src/manage.py collectstatic --noinput"` to automatically collect static files during deployment. |
| 85 | +
|
| 86 | + Example `d1_databases` configuration in `wrangler.jsonc`: |
| 87 | + ```jsonc |
| 88 | + // ... other wrangler.jsonc configurations |
| 89 | + "d1_databases": [ |
| 90 | + { |
| 91 | + "binding": "DB", // Must match CLOUDFLARE_BINDING in Django settings |
| 92 | + "database_name": "my-django-db", |
| 93 | + "database_id": "your-d1-database-id-here" |
| 94 | + } |
| 95 | + ], |
| 96 | + // ... |
| 97 | + ``` |
| 98 | +
|
| 99 | +3. **Django Settings (`src/app/settings.py`):** |
| 100 | + The template should be configured to use D1 binding: |
| 101 | + ```python |
| 102 | + # src/app/settings.py |
| 103 | + DATABASES = { |
| 104 | + 'default': { |
| 105 | + 'ENGINE': 'django_cf.d1_binding', |
| 106 | + # This name 'DB' must match the 'binding' in your wrangler.jsonc d1_databases section |
| 107 | + 'CLOUDFLARE_BINDING': 'DB', |
| 108 | + } |
| 109 | + } |
| 110 | +
|
| 111 | + # Static files |
| 112 | + import os |
| 113 | + BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 114 | + STATIC_URL = '/static/' |
| 115 | + # STATIC_ROOT should point to the 'bucket' directory in wrangler.jsonc, |
| 116 | + # often one level above the 'src' directory. |
| 117 | + STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'staticfiles', 'static') |
| 118 | +
|
| 119 | + # Optional: Settings for local development using D1 API |
| 120 | + # You can create a separate settings_dev.py or use environment variables |
| 121 | + # DATABASES_DEV = { |
| 122 | + # 'default': { |
| 123 | + # 'ENGINE': 'django_cf.d1_api', |
| 124 | + # 'CLOUDFLARE_DATABASE_ID': '<your_database_id>', |
| 125 | + # 'CLOUDFLARE_ACCOUNT_ID': '<your_account_id>', |
| 126 | + # 'CLOUDFLARE_TOKEN': '<your_d1_api_token>', |
| 127 | + # } |
| 128 | + # } |
| 129 | + ``` |
| 130 | +
|
| 131 | +4. **Worker Entrypoint (`src/worker.py`):** |
| 132 | + This file contains the main `on_fetch` handler for your Django application. |
| 133 | + ```python |
| 134 | + from django_cf import DjangoCFAdapter |
| 135 | +
|
| 136 | + async def on_fetch(request, env): |
| 137 | + # Ensure your Django project's WSGI application is importable |
| 138 | + # For example, if your project is 'app' inside 'src': |
| 139 | + from app.wsgi import application # Import application inside on_fetch |
| 140 | + |
| 141 | + # The DjangoCFAdapter requires the Django application and the environment (for D1 binding) |
| 142 | + adapter = DjangoCFAdapter(application, env) |
| 143 | + return await adapter.handle_request(request) |
| 144 | + ``` |
| 145 | + |
| 146 | +5. **Deploy to Cloudflare:** |
| 147 | + ```bash |
| 148 | + npx wrangler deploy |
| 149 | + ``` |
| 150 | + This command will also run the `collectstatic` command if configured in `wrangler.jsonc`. |
| 151 | + |
| 152 | +## Running Management Commands |
| 153 | + |
| 154 | +* **Migrations & `createsuperuser` (Local Development - Recommended for D1):** |
| 155 | + For D1, it's often easiest and safest to run migrations and `createsuperuser` from your local machine by configuring your development Django settings to use the D1 API. |
| 156 | +
|
| 157 | + 1. Ensure you have `django-cf` and your other dependencies installed in your local Python environment (`pip install -r requirements-dev.txt`). |
| 158 | + 2. Set up your Django settings for local D1 API access. You can do this by: |
| 159 | + * Creating a `settings_dev.py` and using `python src/manage.py migrate --settings=app.settings_dev`. |
| 160 | + * Or, by temporarily modifying your main `settings.py` (ensure you don't commit API keys). |
| 161 | + * Or, by using environment variables to supply D1 API credentials to your settings. |
| 162 | + |
| 163 | + Example local D1 API settings in `settings_dev.py` (place it alongside your main `settings.py`): |
| 164 | + ```python |
| 165 | + # app/settings_dev.py |
| 166 | + from .settings import * # Inherit base settings |
| 167 | +
|
| 168 | + DATABASES = { |
| 169 | + 'default': { |
| 170 | + 'ENGINE': 'django_cf.d1_api', |
| 171 | + 'CLOUDFLARE_DATABASE_ID': 'your-actual-d1-database-id', |
| 172 | + 'CLOUDFLARE_ACCOUNT_ID': 'your-cloudflare-account-id', |
| 173 | + 'CLOUDFLARE_TOKEN': 'your-cloudflare-d1-api-token', # Ensure this token has D1 Read/Write permissions |
| 174 | + } |
| 175 | + } |
| 176 | + ``` |
| 177 | + 3. Run commands: |
| 178 | + ```bash |
| 179 | + # From the template root directory |
| 180 | + python src/manage.py migrate --settings=app.settings_dev |
| 181 | + python src/manage.py createsuperuser --settings=app.settings_dev |
| 182 | + ``` |
| 183 | + |
| 184 | +* **Via a Worker Endpoint (Use with Extreme Caution):** |
| 185 | + While possible, running migrations or creating users directly via a worker endpoint is generally **not recommended for D1** due to the direct database access available locally via the D1 API. If you absolutely must, you can adapt the management command endpoints from the Durable Objects template (`src/app/urls.py`), but ensure they are **extremely well-secured**. |
| 186 | + The main risk is exposing sensitive operations over HTTP and potential complexities with the worker environment. |
| 187 | + |
| 188 | + If you choose this path, remember: |
| 189 | + * The worker needs the D1 binding (`env`) passed to the `DjangoCFAdapter` and accessible to your management command functions. |
| 190 | + * Secure the endpoints robustly (e.g., IP restrictions, strong authentication tokens, not just Django's `is_superuser` if the admin user might not exist yet). |
| 191 | +
|
| 192 | +## Development Notes |
| 193 | +
|
| 194 | +* **D1 Limitations:** |
| 195 | + * **Transactions are disabled** for D1. Every query is committed immediately. This is a fundamental aspect of D1. |
| 196 | + * The D1 backend has some limitations compared to traditional SQLite or other SQL databases. Many advanced ORM features or direct SQL functions (especially those used in Django Admin) might not be fully supported. Refer to the `django-cf` README and official Cloudflare D1 documentation. |
| 197 | + * Django Admin functionality might be limited. |
| 198 | +* **Local Testing with D1:** |
| 199 | + * Wrangler allows local development and can simulate D1 access. `npx wrangler dev --remote` can connect to your actual D1 database for more accurate testing. |
| 200 | + * Using the D1 API for local management tasks (as described above) is the most common workflow. |
| 201 | +* **Security:** |
| 202 | + * If you implement management command endpoints on your worker, secure them rigorously. |
| 203 | + * Protect your Cloudflare API tokens and credentials. |
| 204 | +
|
| 205 | +--- |
| 206 | +*For more details on `django-cf` features and configurations, refer to the main [django-cf GitHub repository](https://github.com/G4brym/django-cf).* |
0 commit comments