Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions samples/django-railpack/.github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Deploy

on:
push:
branches:
- main

jobs:
deploy:
environment: playground
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

steps:
- name: Checkout Repo
uses: actions/checkout@v4

- name: Deploy
uses: DefangLabs/defang-github-action@v1.1.0
58 changes: 58 additions & 0 deletions samples/django-railpack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Django-Railpack

[![1-click-deploy](https://raw.githubusercontent.com/DefangLabs/defang-assets/main/Logos/Buttons/SVG/deploy-with-defang.svg)](https://portal.defang.dev/redirect?url=https%3A%2F%2Fgithub.com%2Fnew%3Ftemplate_name%3Dsample-django-template%26template_owner%3DDefangSamples)

This sample is a simple Django to-do app that uses SQLite as the database, which will be reset every time you deploy. **It is not production-ready**. For production use cases, you should check out the Django + Postgres sample.

The app includes a management command which is run on startup to create a superuser with the username `admin` and password `admin`. This means you can login to the admin interface at `/admin/` and see the Django admin interface without any additional steps. The `example_app` is already registered and the `Todo` model is already set up to be managed in the admin interface.

The compose files are already set up for you and are ready to be deployed and the image is built by [Railpack](https://railpack.com/). Serving is done using [Gunicorn](https://gunicorn.org/) and uses [WhiteNoise](https://whitenoise.readthedocs.io/en/latest/) for static files. The `CSRF_TRUSTED_ORIGINS` setting is configured to allow the app to run on a `defang.dev` subdomain.

## Prerequisites

1. Download [Defang CLI](https://github.com/DefangLabs/defang)
2. (Optional) If you are using [Defang BYOC](https://docs.defang.io/docs/concepts/defang-byoc) authenticate with your cloud provider account

## Configuration

For this sample, you will not need to provide [configuration](https://docs.defang.io/docs/concepts/configuration).

If you wish to provide configuration, see below for an example of setting a configuration for a value named `API_KEY`.

```bash
defang config set API_KEY
```

## Deployment

> [!NOTE]
> Download [Defang CLI](https://github.com/DefangLabs/defang)

### Defang Playground

Deploy your application to the Defang Playground by opening up your terminal and typing:

```bash
defang compose up
```

### BYOC (AWS)

If you want to deploy to your own cloud account, you can use Defang BYOC:

1. [Authenticate your AWS account](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html), and check that you have properly set your environment variables like `AWS_PROFILE`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`.
2. Make sure to update the `CSRF_TRUSTED_ORIGINS` setting in the `settings.py` file to include an appropriate domain.
3. Run in a terminal that has access to your AWS environment variables:
```bash
defang --provider=aws compose up
```

---

Title: Django

Short Description: A simple Django app that uses SQLite as the database.

Tags: Django, SQLite, Python, Railpack

Languages: python
31 changes: 31 additions & 0 deletions samples/django-railpack/app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Ignore Python bytecode files
__pycache__
*.pyc
*.pyo
*.pyd
*.pyc.so

# Ignore all log files
*.log

# Ignore local configuration files
local_settings.py

# Ignore test and coverage directories
htmlcov/
.coverage
.tox/

# Ignore database files
*.sqlite3

# Ignore media files
media/

# Ignore all .env files
*.env

# Ignore all .DS_Store files (Mac OS)
.DS_Store

.venv/
14 changes: 14 additions & 0 deletions samples/django-railpack/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
*.log
*.pyc
__pycache__
db.sqlite3
media

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
Empty file.
16 changes: 16 additions & 0 deletions samples/django-railpack/app/defang_sample/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for defang_sample project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'defang_sample.settings')

application = get_asgi_application()
140 changes: 140 additions & 0 deletions samples/django-railpack/app/defang_sample/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""
Django settings for defang_sample project.

Generated by 'django-admin startproject' using Django 5.0.4.

For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""

from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-r(z^n29_r&ax*%(!la2i*cy@*$2q1h(ulie!%@qy)5j-i9kepw'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG', 'False') == 'True'

ALLOWED_HOSTS = [
'*'
]


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'example_app',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
]

ROOT_URLCONF = 'defang_sample.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

WSGI_APPLICATION = 'defang_sample.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}


# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]


# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/

STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# CSRF
CSRF_TRUSTED_ORIGINS = [
'https://*.defang.dev'
]

if DEBUG:
CSRF_TRUSTED_ORIGINS = [
'http://localhost:8000',
]
25 changes: 25 additions & 0 deletions samples/django-railpack/app/defang_sample/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
URL configuration for defang_sample project.

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from django.views.generic import RedirectView

urlpatterns = [
path('admin/', admin.site.urls),
path('todos/', include('example_app.urls', namespace='example_app')),
path('', RedirectView.as_view(url='/todos/')),
]
16 changes: 16 additions & 0 deletions samples/django-railpack/app/defang_sample/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
WSGI config for defang_sample project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'defang_sample.settings')

application = get_wsgi_application()
Empty file.
7 changes: 7 additions & 0 deletions samples/django-railpack/app/example_app/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.contrib import admin
from django.contrib import admin
from .models import Todo

@admin.register(Todo)
class ToDoAdmin(admin.ModelAdmin):
pass
6 changes: 6 additions & 0 deletions samples/django-railpack/app/example_app/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ExampleAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'example_app'
8 changes: 8 additions & 0 deletions samples/django-railpack/app/example_app/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.forms import ModelForm

from .models import Todo

class TodoForm(ModelForm):
class Meta:
model = Todo
fields = ['title', 'completed']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model

class Command(BaseCommand):
def handle(self, *args, **options):
User = get_user_model()
if not User.objects.filter(username='admin').exists():
User.objects.create_superuser('admin', 'admin@example.com', 'admin')
23 changes: 23 additions & 0 deletions samples/django-railpack/app/example_app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.0.4 on 2024-04-12 22:07

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Todo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('completed', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
),
]
Empty file.
Loading
Loading