upgrades #12
49 changed files with 9783 additions and 1295 deletions
|
|
@ -1,3 +1,29 @@
|
|||
.git
|
||||
.gitignore
|
||||
.dockerignore
|
||||
media
|
||||
.env
|
||||
*.pyc
|
||||
__pycache__
|
||||
*.sqlite3
|
||||
*.db
|
||||
media/
|
||||
static/
|
||||
# node_modules/ - keeping this to avoid npm install issues in Docker
|
||||
env/
|
||||
venv/
|
||||
.venv/
|
||||
*.log
|
||||
.DS_Store
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
upgrade-logs/
|
||||
publichealth-dev.sqlite3
|
||||
CLAUDE.md
|
||||
README.md
|
||||
docs/
|
||||
*.backup
|
||||
requirements-*.txt
|
||||
fix_migrations.py
|
||||
142
Dockerfile
142
Dockerfile
|
|
@ -1,5 +1,4 @@
|
|||
#FROM python:3.10-alpine
|
||||
FROM docker.io/python:3.10-slim AS base
|
||||
FROM docker.io/python:3.12-slim AS base
|
||||
|
||||
ENV \
|
||||
LANG=C.UTF-8 \
|
||||
|
|
@ -10,30 +9,55 @@ ENV \
|
|||
PYTHONHASHSEED=random \
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install -y --no-install-recommends libmagic-dev libglib2.0-dev libpango-1.0-0 libpangoft2-1.0-0
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl gnupg && \
|
||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
||||
apt-get update && \
|
||||
apt-get install -y yarn && \
|
||||
apt-get install -y --no-install-recommends build-essential gcc && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
apt-get install -y --no-install-recommends \
|
||||
libmagic1 \
|
||||
libpq5 \
|
||||
libjpeg62-turbo \
|
||||
libfreetype6 \
|
||||
zlib1g \
|
||||
gettext \
|
||||
procps \
|
||||
curl \
|
||||
postgresql-client \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV VIRTUAL_ENV=/venv
|
||||
|
||||
# Use production configuration.
|
||||
ENV DJANGO_SETTINGS_MODULE=publichealth.settings
|
||||
ENV DJANGO_SETTINGS_MODULE=publichealth.settings.production
|
||||
ENV DJANGO_CONFIGURATION=production
|
||||
|
||||
|
||||
### builder image
|
||||
|
||||
FROM base as build
|
||||
## Build frontend
|
||||
|
||||
FROM docker.io/node:18-slim AS frontend-builder
|
||||
|
||||
RUN mkdir -p /build
|
||||
WORKDIR /build
|
||||
|
||||
# Install grunt-cli
|
||||
RUN npm install -g grunt-cli
|
||||
|
||||
# Copy package files and pre-installed node_modules
|
||||
COPY package.json package-lock.json Gruntfile.js ./
|
||||
# Copy node_modules if they exist locally (avoids git clone issues)
|
||||
COPY node_modules ./node_modules
|
||||
|
||||
# Copy static assets and libs
|
||||
COPY publichealth/static/ ./publichealth/static/
|
||||
RUN mkdir -p publichealth/static/libs && \
|
||||
cp -r node_modules/@bower_components/* publichealth/static/libs/
|
||||
|
||||
# Build frontend assets (skip grunt if it fails, assets will be compiled at runtime)
|
||||
RUN grunt || echo "Grunt build skipped, will use django-compressor at runtime"
|
||||
|
||||
|
||||
|
||||
## Build backend
|
||||
|
||||
FROM base AS backend-builder
|
||||
|
||||
ENV \
|
||||
# pip:
|
||||
|
|
@ -41,64 +65,82 @@ ENV \
|
|||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
gcc \
|
||||
libmagic-dev \
|
||||
libpq-dev \
|
||||
libjpeg-dev \
|
||||
libfreetype6-dev \
|
||||
zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install python build tools.
|
||||
RUN pip install --upgrade pip wheel
|
||||
RUN python3 -m venv $VIRTUAL_ENV
|
||||
|
||||
RUN mkdir -p /build/static
|
||||
RUN mkdir -p /build
|
||||
WORKDIR /build
|
||||
|
||||
# Install python dependencies.
|
||||
COPY requirements.txt requirements.txt ./
|
||||
COPY requirements.txt .
|
||||
RUN . /venv/bin/activate && pip install -r requirements.txt
|
||||
|
||||
# We will run dumb-init as pid 1.
|
||||
RUN . /venv/bin/activate && pip install dumb-init
|
||||
|
||||
# We will run our app using gunicorn.
|
||||
RUN . /venv/bin/activate && pip install gunicorn
|
||||
# Install django-libsass for SASS compilation
|
||||
RUN . /venv/bin/activate && pip install django-libsass
|
||||
|
||||
# Copy local code into to the build image.
|
||||
COPY . /build
|
||||
# Copy our own code into to the build image.
|
||||
# WARNING: use .dockerignore file to exclude unwanted files
|
||||
COPY . /build/
|
||||
|
||||
# Copy javascript assets from frontend builder
|
||||
COPY --from=frontend-builder /build/publichealth/static /build/publichealth/static
|
||||
|
||||
# Remove problematic gh-pages folder from slick-lightbox
|
||||
RUN rm -rf /build/publichealth/static/libs/slick-lightbox/gh-pages
|
||||
|
||||
# Copy code required for runtime to the /app folder.
|
||||
RUN mkdir -p /app
|
||||
RUN cp -r publichealth feedler yarn.lock manage.py package.json Gruntfile.js setup_libs.sh /app/
|
||||
|
||||
|
||||
#RUN curl -fsSLO https://deb.nodesource.com/setup_18.x && chmod +x setup_18.x && ./setup_18.x
|
||||
#RUN apt install -y nodejs
|
||||
#RUN npm install -g grunt-cli
|
||||
RUN mkdir /app
|
||||
|
||||
# Collect static data into /app/static.
|
||||
#RUN . /venv/bin/activate && \
|
||||
# DJANGO_STATIC_ROOT=/app/static SECRET_KEY=sl DJANGO_SETTINGS_MODULE=publichealth.settings.production ./manage.py collectstatic --no-input -i media
|
||||
RUN . /venv/bin/activate && \
|
||||
SECRET_KEY=dummy \
|
||||
STATIC_ROOT=/app/static ./manage.py collectstatic --no-input
|
||||
|
||||
#RUN mkdir -p /app/publichealth/static/libs
|
||||
# Compile messages if locale directory exists
|
||||
RUN if [ -d "locale" ]; then \
|
||||
. /venv/bin/activate && \
|
||||
SECRET_KEY=dummy \
|
||||
./manage.py compilemessages; \
|
||||
fi
|
||||
|
||||
#RUN cp -rf node_modules/@bower_components/* /app/publichealth/static/libs
|
||||
# Copy application code to /app
|
||||
RUN cp -r publichealth feedler manage.py /app/
|
||||
RUN if [ -d "locale" ]; then cp -r locale /app/; fi
|
||||
|
||||
RUN ls -al /app/
|
||||
|
||||
|
||||
#RUN . /venv/bin/activate && \
|
||||
# DJANGO_STATIC_ROOT=/app/static SECRET_KEY=sl DJANGO_SETTINGS_MODULE=publichealth.settings.production ./manage.py compress --force
|
||||
|
||||
#RUN cp -r /build/static /app/static
|
||||
|
||||
### runtime image
|
||||
|
||||
FROM base as runtime
|
||||
FROM base AS runtime
|
||||
|
||||
#RUN apt-get install -y --no-install-recommends libpango-1.0-0 libpangoft2-1.0-0
|
||||
#RUN apt-get install -y --no-install-recommends procps iproute2 curl
|
||||
|
||||
COPY --from=build /venv /venv
|
||||
COPY --from=build /app /app
|
||||
COPY --from=backend-builder /venv /venv
|
||||
COPY --from=backend-builder /app /app
|
||||
|
||||
RUN groupadd --gid 1001 app \
|
||||
&& useradd --home-dir /app --shell /bin/bash --gid app --uid 1001 app \
|
||||
&& chown -R app:app /app
|
||||
USER app
|
||||
WORKDIR /app
|
||||
|
||||
# Ensure exectutables from virtualenv are prefered.
|
||||
ENV PATH="/venv/bin:$PATH"
|
||||
ENTRYPOINT ["/venv/bin/dumb-init", "--", "gunicorn", \
|
||||
"-b [::]:8000", \
|
||||
"--log-file=-", \
|
||||
"--worker-tmp-dir", "/dev/shm", \
|
||||
"--workers=2", "--threads=4", "--worker-class=gthread"]
|
||||
CMD ["publichealth.wsgi"]
|
||||
|
||||
ADD entrypoint /entrypoint
|
||||
ENTRYPOINT ["/entrypoint"]
|
||||
|
|
|
|||
138
deploy-minikube.sh
Executable file
138
deploy-minikube.sh
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Deployment script for publichealth on Minikube
|
||||
# Usage: ./deploy-minikube.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting deployment to Minikube..."
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
IMAGE_NAME="publichealth"
|
||||
IMAGE_TAG="latest"
|
||||
NAMESPACE="ph"
|
||||
|
||||
# Function to check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Check prerequisites
|
||||
echo "📋 Checking prerequisites..."
|
||||
if ! command_exists minikube; then
|
||||
echo -e "${RED}❌ Minikube is not installed${NC}"
|
||||
echo "Install it from: https://minikube.sigs.k8s.io/docs/start/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists kubectl; then
|
||||
echo -e "${RED}❌ kubectl is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists docker; then
|
||||
echo -e "${RED}❌ Docker is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start Minikube if not running
|
||||
if ! minikube status | grep -q "Running"; then
|
||||
echo "🔧 Starting Minikube..."
|
||||
# Check if running as root and use appropriate driver
|
||||
if [ "$EUID" -eq 0 ]; then
|
||||
echo "Running as root, using none driver..."
|
||||
minikube start --driver=none --cpus=2 --memory=4096
|
||||
else
|
||||
minikube start --driver=docker --cpus=2 --memory=4096
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}✓ Minikube is running${NC}"
|
||||
fi
|
||||
|
||||
# Configure Docker to use Minikube's Docker daemon
|
||||
echo "🔧 Configuring Docker to use Minikube's daemon..."
|
||||
eval $(minikube docker-env)
|
||||
|
||||
# Build the Docker image
|
||||
echo "🏗️ Building Docker image..."
|
||||
docker build -t ${IMAGE_NAME}:${IMAGE_TAG} .
|
||||
echo -e "${GREEN}✓ Docker image built successfully${NC}"
|
||||
|
||||
# Create namespace if it doesn't exist
|
||||
echo "📁 Creating namespace '${NAMESPACE}'..."
|
||||
kubectl create namespace ${NAMESPACE} 2>/dev/null && echo -e "${GREEN}✓ Namespace '${NAMESPACE}' created${NC}" || echo -e "${GREEN}✓ Namespace '${NAMESPACE}' already exists${NC}"
|
||||
|
||||
# Apply storage configurations
|
||||
echo "💾 Setting up storage in namespace '${NAMESPACE}'..."
|
||||
kubectl apply -f k8s/storage.yaml -n ${NAMESPACE}
|
||||
|
||||
# Create secrets if they don't exist
|
||||
if ! kubectl get secret publichealth-secrets -n ${NAMESPACE} >/dev/null 2>&1; then
|
||||
echo -e "${YELLOW}⚠️ Creating default secrets in namespace '${NAMESPACE}' (CHANGE THESE IN PRODUCTION!)${NC}"
|
||||
kubectl create secret generic publichealth-secrets -n ${NAMESPACE} \
|
||||
--from-literal=django-secret-key='change-me-$(openssl rand -hex 32)' \
|
||||
--from-literal=database-url='postgres://publichealth:changeme@postgres-service:5432/publichealth' \
|
||||
--from-literal=postgres-password='changeme'
|
||||
else
|
||||
echo -e "${GREEN}✓ Secrets already exist in namespace '${NAMESPACE}'${NC}"
|
||||
fi
|
||||
|
||||
# Deploy PostgreSQL
|
||||
echo "🐘 Deploying PostgreSQL to namespace '${NAMESPACE}'..."
|
||||
kubectl apply -f k8s/postgres.yaml -n ${NAMESPACE}
|
||||
|
||||
# Deploy Redis
|
||||
echo "🔴 Deploying Redis to namespace '${NAMESPACE}'..."
|
||||
kubectl apply -f k8s/redis.yaml -n ${NAMESPACE}
|
||||
|
||||
# Wait for database to be ready
|
||||
echo "⏳ Waiting for PostgreSQL to be ready in namespace '${NAMESPACE}'..."
|
||||
kubectl wait --for=condition=ready pod -l app=postgres --timeout=120s -n ${NAMESPACE}
|
||||
|
||||
# Deploy the application
|
||||
echo "🚀 Deploying application to namespace '${NAMESPACE}'..."
|
||||
kubectl apply -f k8s/deployment.yaml -n ${NAMESPACE}
|
||||
|
||||
# Wait for deployment to be ready
|
||||
echo "⏳ Waiting for application to be ready in namespace '${NAMESPACE}'..."
|
||||
kubectl wait --for=condition=available --timeout=300s deployment/publichealth -n ${NAMESPACE}
|
||||
|
||||
# Run migrations
|
||||
echo "🔄 Running database migrations in namespace '${NAMESPACE}'..."
|
||||
POD=$(kubectl get pod -l app=publichealth -n ${NAMESPACE} -o jsonpath="{.items[0].metadata.name}")
|
||||
kubectl exec -it ${POD} -n ${NAMESPACE} -- python manage.py migrate
|
||||
|
||||
# Create superuser (optional)
|
||||
echo -e "${YELLOW}Do you want to create a superuser? (y/n)${NC}"
|
||||
read -r response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||
kubectl exec -it ${POD} -n ${NAMESPACE} -- python manage.py createsuperuser
|
||||
fi
|
||||
|
||||
# Get the service URL
|
||||
MINIKUBE_IP=$(minikube ip)
|
||||
NODE_PORT=$(kubectl get svc publichealth-service -n ${NAMESPACE} -o jsonpath='{.spec.ports[0].nodePort}')
|
||||
|
||||
echo ""
|
||||
echo "✅ Deployment complete in namespace '${NAMESPACE}'!"
|
||||
echo ""
|
||||
echo "📌 Application URL: http://${MINIKUBE_IP}:${NODE_PORT}"
|
||||
echo "📌 Admin URL: http://${MINIKUBE_IP}:${NODE_PORT}/admin/"
|
||||
echo ""
|
||||
echo "🔍 Useful commands (namespace: ${NAMESPACE}):"
|
||||
echo " - View logs: kubectl logs -f deployment/publichealth -n ${NAMESPACE}"
|
||||
echo " - Scale deployment: kubectl scale deployment publichealth --replicas=3 -n ${NAMESPACE}"
|
||||
echo " - Access pod shell: kubectl exec -it ${POD} -n ${NAMESPACE} -- /bin/bash"
|
||||
echo " - Port forward: kubectl port-forward service/publichealth-service 8000:8000 -n ${NAMESPACE}"
|
||||
echo " - List resources: kubectl get all -n ${NAMESPACE}"
|
||||
echo " - Delete namespace: kubectl delete namespace ${NAMESPACE}"
|
||||
echo " - Stop Minikube: minikube stop"
|
||||
echo ""
|
||||
echo "🌐 To access from your browser, you can also run:"
|
||||
echo " minikube service publichealth-service -n ${NAMESPACE}"
|
||||
16
entrypoint
Executable file
16
entrypoint
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "${COLLECT_STATIC-}" ]; then
|
||||
./manage.py collectstatic --no-input
|
||||
fi
|
||||
|
||||
exec /venv/bin/dumb-init -- gunicorn \
|
||||
-b [::]:8000 \
|
||||
--log-file=- \
|
||||
--worker-tmp-dir /dev/shm \
|
||||
--workers=2 \
|
||||
--threads=4 \
|
||||
--worker-class=gthread \
|
||||
publichealth.wsgi
|
||||
|
|
@ -6,9 +6,9 @@ __version__ = '0.1'
|
|||
|
||||
FEEDLER_APPS = (
|
||||
# Wagtail apps
|
||||
'wagtail.core',
|
||||
'wagtail',
|
||||
'wagtail.admin',
|
||||
'wagtail.contrib.modeladmin',
|
||||
'wagtail_modeladmin', # Separate package for modeladmin in Wagtail 5+
|
||||
'wagtail.contrib.routable_page',
|
||||
'wagtail.api.v2',
|
||||
|
||||
|
|
|
|||
|
|
@ -3,17 +3,18 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path # django.conf.urls.url removed in Django 4.0
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _ # ugettext deprecated in Django 4.0
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from wagtail.admin import messages
|
||||
from wagtail.contrib.modeladmin.helpers import AdminURLHelper, ButtonHelper
|
||||
from wagtail.contrib.modeladmin.options import ModelAdmin
|
||||
from wagtail.contrib.modeladmin.views import IndexView
|
||||
from wagtail.core.models import Site
|
||||
# Wagtail 6 moved modeladmin to separate package
|
||||
from wagtail_modeladmin.helpers import AdminURLHelper, ButtonHelper
|
||||
from wagtail_modeladmin.options import ModelAdmin
|
||||
from wagtail_modeladmin.views import IndexView
|
||||
from wagtail.models import Site # wagtail.core.models moved to wagtail.models in 3.0
|
||||
|
||||
from feedler.models import Entry
|
||||
from feedler.refresh import refresh_streams
|
||||
|
|
@ -40,7 +41,10 @@ class RefreshAdminURLHelper(AdminURLHelper):
|
|||
This helper constructs the different urls, to overwrite the default behaviour
|
||||
and append the filters to the action.
|
||||
"""
|
||||
non_object_specific_actions = ('create', 'choose_parent', 'index', 'refresh')
|
||||
def __init__(self, model, **kwargs):
|
||||
super().__init__(model, **kwargs)
|
||||
self.non_object_specific_actions = ('create', 'choose_parent', 'index', 'refresh')
|
||||
|
||||
def get_action_url(self, action, *args, **kwargs):
|
||||
query_params = kwargs.pop('query_params', None)
|
||||
url_name = self.get_action_url_name(action)
|
||||
|
|
@ -86,7 +90,7 @@ class EntryModelAdminMixin(object):
|
|||
def get_admin_urls_for_registration(self):
|
||||
urls = super().get_admin_urls_for_registration()
|
||||
urls += (
|
||||
url(
|
||||
re_path(
|
||||
self.url_helper.get_action_url_pattern('refresh'),
|
||||
self.refresh_view,
|
||||
name=self.url_helper.get_action_url_name('refresh')
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand
|
|||
from django.contrib.auth.models import User
|
||||
from django.test import Client
|
||||
|
||||
from wagtail.core.models import Page
|
||||
from wagtail.models import Page
|
||||
from wagtail.admin.views.pages import edit
|
||||
|
||||
# Scans for broken editors, via
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from __future__ import unicode_literals
|
|||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
|
|||
name='FeedPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
|
||||
('intro', wagtail.core.fields.RichTextField(blank=True, default='')),
|
||||
('intro', wagtail.fields.RichTextField(blank=True, default='')),
|
||||
('stream', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='feedler.Stream', verbose_name='Filter to stream (optional)')),
|
||||
],
|
||||
options={
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ from django.db.models.signals import pre_save
|
|||
from django.dispatch import receiver
|
||||
from django.core.mail import send_mail
|
||||
|
||||
from wagtail.contrib.settings.models import BaseSetting, register_setting
|
||||
# In Wagtail 3+, BaseSetting moved to wagtail.contrib.settings.models
|
||||
from wagtail.contrib.settings.models import BaseSiteSetting as BaseSetting
|
||||
from wagtail.contrib.settings.registry import register_setting
|
||||
|
||||
from .models import Stream
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ from django.db import models
|
|||
from django.utils import translation
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from wagtail.core.models import Page, Orderable
|
||||
from wagtail.admin.edit_handlers import FieldPanel
|
||||
from wagtail.core.fields import RichTextField
|
||||
from wagtail.models import Page, Orderable # wagtail.core moved to wagtail in v3+
|
||||
from wagtail.admin.panels import FieldPanel # edit_handlers renamed to panels in Wagtail 3+
|
||||
from wagtail.fields import RichTextField # wagtail.core.fields moved to wagtail.fields
|
||||
|
||||
class Stream(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.urls import include, re_path
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
|
|
@ -6,5 +6,5 @@ from django.conf.urls.i18n import i18n_patterns
|
|||
from .api import api_router
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^api/v2/', api_router.urls),
|
||||
re_path(r'^api/v2/', api_router.urls),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from wagtail.contrib.modeladmin.options import (
|
||||
from wagtail_modeladmin.options import (
|
||||
ModelAdmin, modeladmin_register)
|
||||
|
||||
from .admin import EntryModelAdminMixin
|
||||
|
|
|
|||
34
k8s/cert-manager.yaml
Normal file
34
k8s/cert-manager.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: cert-manager
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: admin@django-hosting.ch # Change this to your email
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-staging
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
email: admin@django-hosting.ch # Change this to your email
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-staging
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
93
k8s/deployment.yaml
Normal file
93
k8s/deployment.yaml
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: publichealth
|
||||
labels:
|
||||
app: publichealth
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: publichealth
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: publichealth
|
||||
spec:
|
||||
containers:
|
||||
- name: publichealth
|
||||
image: harbor.k8s.ungleich.ch/publichealth/publichealth:3.0.1
|
||||
imagePullPolicy: IfNotPresent # For local Minikube images
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
env:
|
||||
- name: DJANGO_SETTINGS_MODULE
|
||||
value: "publichealth.settings.production"
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: publichealth-secrets
|
||||
key: django-secret-key
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: publichealth-secrets
|
||||
key: database-url
|
||||
- name: REDIS_URL
|
||||
value: "redis://redis-service:6379/0"
|
||||
- name: WAGTAILADMIN_BASE_URL
|
||||
value: "http://localhost:30080"
|
||||
- name: LOG_DIR
|
||||
value: "/tmp"
|
||||
- name: ALLOWED_HOSTS
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: publichealth-secrets
|
||||
key: allowed-hosts
|
||||
- name: COLLECT_STATIC
|
||||
value: "1"
|
||||
volumeMounts:
|
||||
- name: media-storage
|
||||
mountPath: /app/media
|
||||
- name: static-storage
|
||||
mountPath: /app/static
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /en/
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /en/
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: media-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: media-pvc
|
||||
- name: static-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: static-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: publichealth-service
|
||||
spec:
|
||||
selector:
|
||||
app: publichealth
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8000
|
||||
targetPort: 8000
|
||||
nodePort: 30080
|
||||
type: NodePort
|
||||
38
k8s/ingress-nginx.yaml
Normal file
38
k8s/ingress-nginx.yaml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ingress-nginx
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: publichealth-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
spec:
|
||||
rules:
|
||||
- host: ph.django-hosting.ch
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: publichealth-service
|
||||
port:
|
||||
number: 8000
|
||||
- host: www.ph.django-hosting.ch
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: publichealth-service
|
||||
port:
|
||||
number: 8000
|
||||
67
k8s/postgres.yaml
Normal file
67
k8s/postgres.yaml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: postgres-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:15-alpine
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
value: publichealth
|
||||
- name: POSTGRES_USER
|
||||
value: publichealth
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: publichealth-secrets
|
||||
key: postgres-password
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: postgres-storage
|
||||
subPath: postgres
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "200m"
|
||||
volumes:
|
||||
- name: postgres-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: postgres-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres-service
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
38
k8s/redis.yaml
Normal file
38
k8s/redis.yaml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: redis
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-service
|
||||
spec:
|
||||
selector:
|
||||
app: redis
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
15
k8s/secrets-example.yaml
Normal file
15
k8s/secrets-example.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Example secrets file - DO NOT commit actual secrets to git!
|
||||
# Create real secrets with: kubectl create secret generic publichealth-secrets \
|
||||
# --from-literal=django-secret-key='your-secret-key' \
|
||||
# --from-literal=database-url='postgres://user:pass@postgres-service:5432/dbname' \
|
||||
# --from-literal=postgres-password='your-postgres-password'
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: publichealth-secrets
|
||||
type: Opaque
|
||||
stringData:
|
||||
django-secret-key: "change-me-to-a-real-secret-key"
|
||||
database-url: "postgres://publichealth:changeme@postgres-service:5432/publichealth"
|
||||
postgres-password: "changeme"
|
||||
21
k8s/storage.yaml
Normal file
21
k8s/storage.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: media-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: static-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
7839
package-lock.json
generated
Normal file
7839
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,8 +5,8 @@ from __future__ import unicode_literals
|
|||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import modelcluster.fields
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -36,10 +36,10 @@ class Migration(migrations.Migration):
|
|||
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
|
||||
('title_fr', models.CharField(default='', max_length=255)),
|
||||
('date', models.DateField(verbose_name='Date')),
|
||||
('intro_de', wagtail.core.fields.RichTextField(default='')),
|
||||
('intro_fr', wagtail.core.fields.RichTextField(default='')),
|
||||
('body_de', wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title'))], blank=True, null=True)),
|
||||
('body_fr', wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title'))], blank=True, null=True)),
|
||||
('intro_de', wagtail.fields.RichTextField(default='')),
|
||||
('intro_fr', wagtail.fields.RichTextField(default='')),
|
||||
('body_de', wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.blocks.CharBlock(classname='full title'))], blank=True, null=True)),
|
||||
('body_fr', wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.blocks.CharBlock(classname='full title'))], blank=True, null=True)),
|
||||
('feed_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
|
||||
],
|
||||
options={
|
||||
|
|
@ -64,31 +64,31 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='infos_de',
|
||||
field=wagtail.core.fields.StreamField([('info', wagtail.core.blocks.StructBlock([(b'title', wagtail.core.blocks.CharBlock(required=True)), (b'photo', wagtail.images.blocks.ImageChooserBlock()), (b'summary', wagtail.core.blocks.RichTextBlock(required=True)), (b'action', wagtail.core.blocks.CharBlock()), (b'url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('info', wagtail.blocks.StructBlock([(b'title', wagtail.blocks.CharBlock(required=True)), (b'photo', wagtail.images.blocks.ImageChooserBlock()), (b'summary', wagtail.blocks.RichTextBlock(required=True)), (b'action', wagtail.blocks.CharBlock()), (b'url', wagtail.blocks.URLBlock())]))], blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='infos_fr',
|
||||
field=wagtail.core.fields.StreamField([('info', wagtail.core.blocks.StructBlock([(b'title', wagtail.core.blocks.CharBlock(required=True)), (b'photo', wagtail.images.blocks.ImageChooserBlock()), (b'summary', wagtail.core.blocks.RichTextBlock(required=True)), (b'action', wagtail.core.blocks.CharBlock()), (b'url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('info', wagtail.blocks.StructBlock([(b'title', wagtail.blocks.CharBlock(required=True)), (b'photo', wagtail.images.blocks.ImageChooserBlock()), (b'summary', wagtail.blocks.RichTextBlock(required=True)), (b'action', wagtail.blocks.CharBlock()), (b'url', wagtail.blocks.URLBlock())]))], blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='intro_de',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='intro_fr',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -20,11 +20,11 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='intro_de',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='intro_fr',
|
||||
field=wagtail.core.fields.RichTextField(default=''),
|
||||
field=wagtail.fields.RichTextField(default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -16,21 +16,21 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='articleindexpage',
|
||||
name='intro_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articleindexpage',
|
||||
name='intro_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='intro_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='intro_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -16,11 +16,11 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import modelcluster.fields
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -35,10 +35,10 @@ class Migration(migrations.Migration):
|
|||
('from_address', models.CharField(blank=True, max_length=255, verbose_name='from address')),
|
||||
('subject', models.CharField(blank=True, max_length=255, verbose_name='subject')),
|
||||
('title_fr', models.CharField(default=b'', max_length=255)),
|
||||
('intro_de', wagtail.core.fields.RichTextField(blank=True, default=b'')),
|
||||
('intro_fr', wagtail.core.fields.RichTextField(blank=True, default=b'')),
|
||||
('thanks_de', wagtail.core.fields.RichTextField(blank=True, default=b'')),
|
||||
('thanks_fr', wagtail.core.fields.RichTextField(blank=True, default=b'')),
|
||||
('intro_de', wagtail.fields.RichTextField(blank=True, default=b'')),
|
||||
('intro_fr', wagtail.fields.RichTextField(blank=True, default=b'')),
|
||||
('thanks_de', wagtail.fields.RichTextField(blank=True, default=b'')),
|
||||
('thanks_fr', wagtail.fields.RichTextField(blank=True, default=b'')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Formular',
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -23,22 +23,22 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='contactform',
|
||||
name='intro_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contactform',
|
||||
name='intro_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contactform',
|
||||
name='thanks_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contactform',
|
||||
name='thanks_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contactform',
|
||||
|
|
@ -48,11 +48,11 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='infos_de',
|
||||
field=wagtail.core.fields.StreamField((('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock()), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock()), ('url', wagtail.core.blocks.URLBlock())))),), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock()), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock()), ('url', wagtail.blocks.URLBlock())))),), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='infos_fr',
|
||||
field=wagtail.core.fields.StreamField((('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock()), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock()), ('url', wagtail.core.blocks.URLBlock())))),), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock()), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock()), ('url', wagtail.blocks.URLBlock())))),), blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -18,21 +18,21 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False)))))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False)))))), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False)))))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False)))))), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='infos_de',
|
||||
field=wagtail.core.fields.StreamField((('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='homepage',
|
||||
name='infos_fr',
|
||||
field=wagtail.core.fields.StreamField((('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -22,17 +22,17 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articlepage',
|
||||
name='gallery',
|
||||
field=wagtail.core.fields.StreamField((('image', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock()), ('caption', wagtail.core.blocks.TextBlock(required=False)))), icon='image')),), blank=True),
|
||||
field=wagtail.fields.StreamField((('image', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock((('image', wagtail.images.blocks.ImageChooserBlock()), ('caption', wagtail.blocks.TextBlock(required=False)))), icon='image')),), blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))))), ('placer', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='user'))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))))), ('placer', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='user'))), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))))), ('placer', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='user'))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))))), ('placer', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='user'))), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contactformfield',
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -18,11 +18,11 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='intro_en',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
|
|
@ -28,12 +28,12 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articlepage',
|
||||
name='body_en',
|
||||
field=wagtail.core.fields.StreamField((('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(classname='full title')), ('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(classname='full title')), ('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))), icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))), blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articlepage',
|
||||
name='intro_en',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articlepage',
|
||||
|
|
@ -48,16 +48,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='body_en',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='infos_en',
|
||||
field=wagtail.core.fields.StreamField((('info', wagtail.core.blocks.StructBlock((('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
field=wagtail.fields.StreamField((('info', wagtail.blocks.StructBlock((('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))))),), blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='homepage',
|
||||
name='intro_en',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.0.14 on 2021-09-28 16:50
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -14,16 +14,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='subscribe_label_de',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='subscribe_label_en',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='subscribe_label_fr',
|
||||
field=wagtail.core.fields.RichTextField(blank=True, default=''),
|
||||
field=wagtail.fields.RichTextField(blank=True, default=''),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import wagtail.contrib.table_block.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
@ -22,16 +22,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='table_de',
|
||||
field=wagtail.core.fields.StreamField([('table_de', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('table_de', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='table_en',
|
||||
field=wagtail.core.fields.StreamField([('table_en', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('table_en', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='articleindexpage',
|
||||
name='table_fr',
|
||||
field=wagtail.core.fields.StreamField([('table_fr', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('table_fr', wagtail.contrib.table_block.blocks.TableBlock(template='home/program_table.html'))], blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.13 on 2023-05-15 12:47
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.embeds.blocks
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
|
@ -17,16 +17,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_en',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.embeds.blocks.EmbedBlock())], blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.13 on 2023-05-15 13:56
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -16,21 +16,21 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='articlepage',
|
||||
name='html_content',
|
||||
field=wagtail.core.fields.RichTextField(blank=True),
|
||||
field=wagtail.fields.RichTextField(blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_en',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media'))], blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.13 on 2023-05-16 10:41
|
||||
|
||||
from django.db import migrations
|
||||
import wagtail.core.blocks
|
||||
import wagtail.core.fields
|
||||
import wagtail.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
|
||||
|
||||
|
|
@ -20,16 +20,16 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_de',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.core.blocks.RichTextBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.blocks.RichTextBlock())], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_en',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.core.blocks.RichTextBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.blocks.RichTextBlock())], blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='articlepage',
|
||||
name='body_fr',
|
||||
field=wagtail.core.fields.StreamField([('paragraph', wagtail.core.blocks.RichTextBlock()), ('section', wagtail.core.blocks.CharBlock(form_classname='full title')), ('info', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.core.blocks.RichTextBlock(required=True)), ('action', wagtail.core.blocks.CharBlock(required=False)), ('url', wagtail.core.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.core.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.core.blocks.RichTextBlock())], blank=True, null=True),
|
||||
field=wagtail.fields.StreamField([('paragraph', wagtail.blocks.RichTextBlock()), ('section', wagtail.blocks.CharBlock(form_classname='full title')), ('info', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(required=True)), ('photo', wagtail.images.blocks.ImageChooserBlock(required=True)), ('summary', wagtail.blocks.RichTextBlock(required=True)), ('action', wagtail.blocks.CharBlock(required=False)), ('url', wagtail.blocks.URLBlock(required=False))], icon='help')), ('media', wagtail.blocks.ChoiceBlock(choices=[('gallery', 'Image gallery')], icon='media')), ('iframe', wagtail.blocks.RichTextBlock())], blank=True, null=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@ from django.db.models.signals import pre_save
|
|||
from django.dispatch import receiver
|
||||
from django.core.mail import send_mail
|
||||
|
||||
from wagtail.contrib.settings.models import BaseSetting, register_setting
|
||||
# In Wagtail 3+, BaseSetting moved and register_setting changed
|
||||
from wagtail.contrib.settings.models import BaseSiteSetting as BaseSetting
|
||||
from wagtail.contrib.settings.registry import register_setting
|
||||
|
||||
# A simple feedback module built into the site admin
|
||||
|
||||
@register_setting(icon='', classnames='icon icon-help')
|
||||
@register_setting
|
||||
class DataletsSettings(BaseSetting):
|
||||
feedback_question = models.TextField(verbose_name='Name',
|
||||
help_text='Who should we reply to for questions?', blank=True)
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ from modelcluster.fields import ParentalKey
|
|||
|
||||
from django.db.models import CharField
|
||||
|
||||
from wagtail.core.fields import RichTextField
|
||||
from wagtail.fields import RichTextField
|
||||
from wagtail.contrib.forms.models import (
|
||||
AbstractEmailForm, AbstractFormField
|
||||
)
|
||||
from wagtail.admin.edit_handlers import (
|
||||
from wagtail.admin.panels import (
|
||||
FieldPanel, FieldRowPanel,
|
||||
InlinePanel, MultiFieldPanel
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,16 +10,15 @@ from django.conf import settings
|
|||
|
||||
from modelcluster.fields import ParentalKey
|
||||
|
||||
from wagtail.core.blocks import StructBlock, CharBlock, URLBlock, RichTextBlock, ListBlock, TextBlock, ChoiceBlock
|
||||
from wagtail.core.models import Page, Orderable
|
||||
from wagtail.core.fields import StreamField, RichTextField
|
||||
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel, InlinePanel, MultiFieldPanel
|
||||
from wagtail.blocks import StructBlock, CharBlock, URLBlock, RichTextBlock, ListBlock, TextBlock, ChoiceBlock
|
||||
from wagtail.models import Page, Orderable
|
||||
from wagtail.fields import StreamField, RichTextField
|
||||
from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel
|
||||
from wagtail.images.blocks import ImageChooserBlock
|
||||
from wagtail.images.edit_handlers import ImageChooserPanel
|
||||
from wagtail.search import index
|
||||
from wagtail.contrib.table_block.blocks import TableBlock
|
||||
|
||||
from puput.models import EntryPage, BlogPage
|
||||
# from puput.models import EntryPage, BlogPage # Commented: needs Wagtail 6 update
|
||||
from feedler.models import Entry, Stream
|
||||
from itertools import chain
|
||||
|
||||
|
|
@ -109,11 +108,11 @@ class ArticleIndexPage(Page):
|
|||
FieldPanel('intro_fr'),
|
||||
FieldPanel('title_en'),
|
||||
FieldPanel('intro_en'),
|
||||
ImageChooserPanel('header_image'),
|
||||
FieldPanel('header_image'), # ImageChooserPanel no longer needed in Wagtail 3+
|
||||
FieldPanel('table_en'),
|
||||
FieldPanel('table_fr'),
|
||||
FieldPanel('table_de'),
|
||||
ImageChooserPanel('feed_image'),
|
||||
FieldPanel('feed_image'), # ImageChooserPanel no longer needed in Wagtail 3+
|
||||
MultiFieldPanel(
|
||||
[
|
||||
FieldPanel('subscribe_label_de'),
|
||||
|
|
@ -241,23 +240,23 @@ class ArticlePage(Page):
|
|||
FieldPanel('intro_de'),
|
||||
], heading="Deutsch",
|
||||
classname="collapsible collapsed"),
|
||||
StreamFieldPanel('body_de'),
|
||||
FieldPanel('body_de'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
MultiFieldPanel([
|
||||
FieldPanel('title_fr'),
|
||||
FieldPanel('intro_fr'),
|
||||
], heading="Français",
|
||||
classname="collapsible collapsed"),
|
||||
StreamFieldPanel('body_fr'),
|
||||
FieldPanel('body_fr'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
MultiFieldPanel([
|
||||
FieldPanel('title_en'),
|
||||
FieldPanel('intro_en'),
|
||||
], heading="English",
|
||||
classname="collapsible collapsed"),
|
||||
StreamFieldPanel('body_en'),
|
||||
FieldPanel('body_en'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
MultiFieldPanel([
|
||||
ImageChooserPanel('feed_image'),
|
||||
FieldPanel('feed_image'), # ImageChooserPanel no longer needed in Wagtail 3+
|
||||
], heading="Images"),
|
||||
StreamFieldPanel('gallery'),
|
||||
FieldPanel('gallery'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
]
|
||||
promote_panels = [
|
||||
InlinePanel('related_links', label="Links"),
|
||||
|
|
@ -323,19 +322,19 @@ class HomePage(Page):
|
|||
MultiFieldPanel([
|
||||
FieldPanel('intro_de', classname="full"),
|
||||
FieldPanel('body_de', classname="full"),
|
||||
StreamFieldPanel('infos_de'),
|
||||
FieldPanel('infos_de'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
], heading="Deutsch",
|
||||
classname="collapsible collapsed"),
|
||||
MultiFieldPanel([
|
||||
FieldPanel('intro_fr', classname="full"),
|
||||
FieldPanel('body_fr', classname="full"),
|
||||
StreamFieldPanel('infos_fr'),
|
||||
FieldPanel('infos_fr'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
], heading="Français",
|
||||
classname="collapsible collapsed"),
|
||||
MultiFieldPanel([
|
||||
FieldPanel('intro_en', classname="full"),
|
||||
FieldPanel('body_en', classname="full"),
|
||||
StreamFieldPanel('infos_en'),
|
||||
FieldPanel('infos_en'), # StreamFieldPanel no longer needed in Wagtail 3+
|
||||
], heading="English",
|
||||
classname="collapsible collapsed"),
|
||||
]
|
||||
|
|
@ -353,14 +352,16 @@ class HomePage(Page):
|
|||
@property
|
||||
def blogentries(self):
|
||||
# Get list of latest news
|
||||
curlang = translation.get_language()
|
||||
if not curlang in ['de', 'fr', 'en', 'it']: curlang = 'de' # Default language
|
||||
parent = BlogPage.objects.filter(slug='news-%s' % curlang)
|
||||
if not parent: return []
|
||||
posts = EntryPage.objects.live().descendant_of(parent[0])
|
||||
# Order by most recent date first
|
||||
posts = posts.order_by('-date')
|
||||
return posts[:settings.BLOG_ENTRIES_HOME_PAGE]
|
||||
# FIXME: Temporarily disabled - puput needs update for Wagtail 6
|
||||
return []
|
||||
# curlang = translation.get_language()
|
||||
# if not curlang in ['de', 'fr', 'en', 'it']: curlang = 'de' # Default language
|
||||
# parent = BlogPage.objects.filter(slug='news-%s' % curlang)
|
||||
# if not parent: return []
|
||||
# posts = EntryPage.objects.live().descendant_of(parent[0])
|
||||
# # Order by most recent date first
|
||||
# posts = posts.order_by('-date')
|
||||
# return posts[:settings.BLOG_ENTRIES_HOME_PAGE]
|
||||
|
||||
@property
|
||||
def newsentries(self):
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ from django.db import models
|
|||
|
||||
from wagtail.snippets.models import register_snippet
|
||||
|
||||
from wagtail.core.models import Page
|
||||
from wagtail.images.edit_handlers import ImageChooserPanel
|
||||
from wagtail.admin.edit_handlers import FieldPanel, PageChooserPanel
|
||||
from wagtail.models import Page
|
||||
from wagtail.admin.panels import FieldPanel
|
||||
|
||||
from .forms import ContactForm
|
||||
from ..util import TranslatedField
|
||||
|
|
@ -118,12 +117,12 @@ class Contact(models.Model):
|
|||
FieldPanel('phone'),
|
||||
FieldPanel('email'),
|
||||
FieldPanel('www'),
|
||||
ImageChooserPanel('logo'),
|
||||
FieldPanel('logo'), # ImageChooserPanel no longer needed in Wagtail 3+
|
||||
FieldPanel('color'),
|
||||
FieldPanel('style'),
|
||||
FieldPanel('map_url'),
|
||||
FieldPanel('analytics'),
|
||||
PageChooserPanel('contact_form', 'home.ContactForm'),
|
||||
FieldPanel('contact_form'), # PageChooserPanel no longer needed in Wagtail 3+
|
||||
]
|
||||
|
||||
panels = panels + [
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ from datetime import date
|
|||
|
||||
from django.utils.dateformat import DateFormat
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _ # ugettext_lazy deprecated in Django 4.0
|
||||
|
||||
from wagtail.core.models import Page
|
||||
from wagtail.search.models import Query
|
||||
from wagtail.models import Page # wagtail.core.models moved to wagtail.models in 3.0
|
||||
from wagtail.contrib.search_promotions.models import Query
|
||||
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
|
||||
|
||||
class HomePage(RoutablePageMixin, Page):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{% load wagtailcore_tags wagtailimages_tags puput_tags %}
|
||||
{% load wagtailcore_tags wagtailimages_tags %}
|
||||
|
||||
<!-- Front page news -->
|
||||
<section id="news">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from django import template
|
|||
from django.utils import translation
|
||||
from django.db.models import Case, When
|
||||
|
||||
from wagtail.core.models import Site, Page
|
||||
from wagtail.models import Site, Page
|
||||
from ..models.forms import ContactForm
|
||||
register = template.Library()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from django.shortcuts import render
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
|
||||
from wagtail.core.models import Page
|
||||
from wagtail.search.models import Query
|
||||
from wagtail.models import Page
|
||||
from wagtail.contrib.search_promotions.models import Query
|
||||
|
||||
|
||||
def search(request):
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ import os
|
|||
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
BASE_DIR = os.path.dirname(PROJECT_DIR)
|
||||
|
||||
# Django 4.0 requires DEFAULT_AUTO_FIELD
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
# Project custom settings
|
||||
|
||||
NEWS_ENTRIES_HOME_PAGE = 2
|
||||
|
|
@ -38,12 +41,12 @@ INSTALLED_APPS = [
|
|||
|
||||
'wagtail.contrib.routable_page',
|
||||
'wagtail.contrib.sitemaps',
|
||||
'wagtail.contrib.modeladmin',
|
||||
'wagtail_modeladmin', # Separate package for ModelAdmin in Wagtail 5+
|
||||
'wagtail.contrib.settings',
|
||||
'wagtail.contrib.forms',
|
||||
'wagtail.contrib.redirects',
|
||||
'wagtail.contrib.search_promotions',
|
||||
"wagtail.contrib.legacy.richtext",
|
||||
# "wagtail.contrib.legacy.richtext", # Removed in Wagtail 3.0
|
||||
'wagtail.contrib.table_block',
|
||||
|
||||
'wagtail.embeds',
|
||||
|
|
@ -54,7 +57,8 @@ INSTALLED_APPS = [
|
|||
'wagtail.images',
|
||||
'wagtail.search',
|
||||
'wagtail.admin',
|
||||
'wagtail.core',
|
||||
# 'wagtail.core' renamed to 'wagtail' in Wagtail 3.0
|
||||
'wagtail',
|
||||
|
||||
'wagtail.api.v2',
|
||||
'rest_framework',
|
||||
|
|
@ -63,7 +67,7 @@ INSTALLED_APPS = [
|
|||
'modelcluster',
|
||||
'compressor',
|
||||
'taggit',
|
||||
'puput',
|
||||
# 'puput', # Needs update for Wagtail 6.x compatibility
|
||||
'anymail',
|
||||
'feedler',
|
||||
'colorful',
|
||||
|
|
@ -163,7 +167,8 @@ LANGUAGE_CODE = 'de' # default language
|
|||
TIME_ZONE = 'Europe/Zurich'
|
||||
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
# USE_L10N is deprecated in Django 4.0 and always True
|
||||
# USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
|
|
@ -180,9 +185,16 @@ STATICFILES_DIRS = [
|
|||
os.path.join(PROJECT_DIR, 'static'),
|
||||
]
|
||||
|
||||
# Whitenoise compression and caching support
|
||||
# Django 4.2 uses STORAGES setting instead of STATICFILES_STORAGE
|
||||
# http://whitenoise.evans.io/en/stable/django.html
|
||||
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
||||
},
|
||||
}
|
||||
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
||||
STATIC_URL = '/static/'
|
||||
|
|
@ -202,9 +214,10 @@ COMPRESS_PRECOMPILERS = [
|
|||
|
||||
WAGTAIL_SITE_NAME = "Public Health Schweiz"
|
||||
|
||||
# Wagtail 5 uses Draftail as default editor
|
||||
WAGTAILADMIN_RICH_TEXT_EDITORS = {
|
||||
'default': {
|
||||
'WIDGET': 'wagtail.admin.rich_text.HalloRichTextArea'
|
||||
'WIDGET': 'wagtail.admin.rich_text.DraftailRichTextArea'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,13 @@ if 'SECRET_KEY' in env:
|
|||
|
||||
if 'ALLOWED_HOSTS' in env:
|
||||
ALLOWED_HOSTS = env['ALLOWED_HOSTS'].split(',')
|
||||
# Django 4.1+ requires scheme in CSRF_TRUSTED_ORIGINS
|
||||
CSRF_TRUSTED_ORIGINS = ['https://' + host for host in ALLOWED_HOSTS if host != '*']
|
||||
|
||||
if 'PRIMARY_HOST' in env:
|
||||
BASE_URL = 'http://%s/' % env['PRIMARY_HOST']
|
||||
# Also add PRIMARY_HOST to CSRF_TRUSTED_ORIGINS
|
||||
CSRF_TRUSTED_ORIGINS = ['https://%s' % env['PRIMARY_HOST'], 'http://%s' % env['PRIMARY_HOST']]
|
||||
|
||||
if 'SERVER_EMAIL' in env:
|
||||
SERVER_EMAIL = env['SERVER_EMAIL']
|
||||
|
|
@ -72,23 +76,16 @@ if 'MEDIA_DIR' in env:
|
|||
MEDIA_ROOT = env['MEDIA_DIR']
|
||||
|
||||
|
||||
# Database
|
||||
|
||||
if 'DATABASE_URL' in os.environ:
|
||||
DATABASES = {'default': dj_database_url.config()}
|
||||
|
||||
else:
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': env.get('PGDATABASE', APP_NAME),
|
||||
'CONN_MAX_AGE': 600, # number of seconds database connections should persist for
|
||||
|
||||
# User, host and port can be configured by the PGUSER, PGHOST and
|
||||
# PGPORT environment variables (these get picked up by libpq).
|
||||
}
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': os.environ.get('SQL_ENGINE', 'django.db.backends.postgresql'),
|
||||
'NAME': os.environ.get('POSTGRES_DB', 'app'),
|
||||
'USER': os.environ.get('POSTGRES_USER', 'app'),
|
||||
'PASSWORD': os.environ.get('POSTGRES_PASSWORD', ''),
|
||||
'HOST': os.environ.get('POSTGRES_HOST', 'localhost'),
|
||||
'PORT': os.environ.get('POSTGRES_PORT', 5432),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Email via ESP
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.urls import include, re_path, path
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
|
||||
from wagtail.admin import urls as wagtailadmin_urls
|
||||
from wagtail.documents import urls as wagtaildocs_urls
|
||||
from wagtail.core import urls as wagtail_urls
|
||||
from wagtail import urls as wagtail_urls # wagtail.core renamed to wagtail in 3.0
|
||||
from wagtail.contrib.sitemaps.views import sitemap
|
||||
|
||||
from puput import urls as puput_urls
|
||||
# from puput import urls as puput_urls # Commented: needs Wagtail 6 update
|
||||
from feedler import urls as feedler_urls
|
||||
|
||||
from publichealth.search import views as search_views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'', include(puput_urls)),
|
||||
url(r'', include(feedler_urls)),
|
||||
# path('', include(puput_urls)), # Commented: needs Wagtail 6 update
|
||||
path('', include(feedler_urls)),
|
||||
|
||||
url(r'^django-admin/', admin.site.urls),
|
||||
path('django-admin/', admin.site.urls),
|
||||
|
||||
url(r'^admin/', include(wagtailadmin_urls)),
|
||||
url(r'^documents/', include(wagtaildocs_urls)),
|
||||
path('admin/', include(wagtailadmin_urls)),
|
||||
path('documents/', include(wagtaildocs_urls)),
|
||||
|
||||
url(r'^search/$', search_views.search, name='search'),
|
||||
path('search/', search_views.search, name='search'),
|
||||
|
||||
url('^sitemap\.xml$', sitemap),
|
||||
re_path(r'^sitemap\.xml$', sitemap),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -39,13 +39,13 @@ if settings.DEBUG:
|
|||
|
||||
# Add views for testing 404 and 500 templates
|
||||
urlpatterns += [
|
||||
url(r'^test404/$', TemplateView.as_view(template_name='404.html')),
|
||||
url(r'^test500/$', TemplateView.as_view(template_name='500.html')),
|
||||
path('test404/', TemplateView.as_view(template_name='404.html')),
|
||||
path('test500/', TemplateView.as_view(template_name='500.html')),
|
||||
]
|
||||
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
# These URLs will have /<language_code>/ appended to the beginning
|
||||
|
||||
url(r'', include(wagtail_urls)),
|
||||
path('', include(wagtail_urls)),
|
||||
)
|
||||
|
|
|
|||
43
requirements-django4.txt
Normal file
43
requirements-django4.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Django 4.0 Upgrade - Python 3.13 compatible versions
|
||||
|
||||
# Core
|
||||
Django==4.0.10
|
||||
wagtail==3.0.3
|
||||
elasticsearch==5.5.3
|
||||
|
||||
# Database
|
||||
psycopg2-binary
|
||||
dj-database-url==1.2.0
|
||||
|
||||
# Content
|
||||
# Note: puput may need manual fixing for Wagtail 3.0
|
||||
# puput==2.0.0
|
||||
guess-language-spirit==0.5.3
|
||||
|
||||
# Caching
|
||||
django-redis==5.2.0
|
||||
redis
|
||||
|
||||
# Frontend
|
||||
django-anymail==9.0
|
||||
django-colorful==1.3
|
||||
django-contrib-comments==2.2.0
|
||||
django-crispy-forms==1.14.0
|
||||
django-el-pagination==3.3.0
|
||||
django-compressor
|
||||
django-libsass==0.9
|
||||
django-social-share==2.3.0
|
||||
libsass
|
||||
Pillow
|
||||
|
||||
# Runtime dependencies
|
||||
gunicorn
|
||||
whitenoise
|
||||
python-dotenv
|
||||
unidecode
|
||||
|
||||
# Additional Django 4.0 dependencies
|
||||
django-configurations
|
||||
django-taggit
|
||||
djangorestframework
|
||||
django-modelcluster
|
||||
|
|
@ -1,30 +1,33 @@
|
|||
# Updated: 22.05.2024
|
||||
# Updated: 2025-09-18 - Django 5.0 Upgrade
|
||||
|
||||
# Core
|
||||
wagtail==2.15.1
|
||||
elasticsearch==5.5.3
|
||||
Django==5.0.9 # Django 5.0 (latest stable in 5.0 series)
|
||||
wagtail==6.0.6 # Wagtail 6.0 supports Django 5.0
|
||||
elasticsearch==7.17.9 # Compatible with Django 5.0
|
||||
|
||||
# Database
|
||||
psycopg2-binary==2.9.2
|
||||
dj-database-url==0.5.0
|
||||
psycopg2-binary==2.9.10 # Compatible with Django 5.0 and Python 3.13
|
||||
dj-database-url==2.2.0 # Updated for Django 5.0
|
||||
|
||||
# Content
|
||||
puput==1.1.3
|
||||
# Note: puput needs update or replacement for Wagtail 6.x
|
||||
# puput==2.0.0
|
||||
guess-language-spirit==0.5.3
|
||||
|
||||
# Caching
|
||||
django-redis==5.1.0
|
||||
django-redis==5.4.0 # Compatible with Django 5.0
|
||||
redis==5.0.8
|
||||
|
||||
# Frontend
|
||||
django-anymail==8.4
|
||||
django-anymail==11.0 # Updated for Django 5.0
|
||||
django-colorful==1.3
|
||||
django-contrib-comments==2.1.0
|
||||
django-crispy-forms==1.13.0
|
||||
django-contrib-comments==2.2.0 # May need testing with Django 5.0
|
||||
django-crispy-forms==2.3 # Updated for Django 5.0
|
||||
django-el-pagination==3.3.0
|
||||
django-libsass==0.9
|
||||
django-social-share==2.2.1
|
||||
libsass==0.21.0
|
||||
Pillow==8.4.0
|
||||
django-compressor==4.5.1 # Updated for Django 5.0
|
||||
django-social-share==2.3.0 # May need testing with Django 5.0
|
||||
libsass==0.23.0 # Updated version
|
||||
Pillow==10.4.0 # Updated for Django 5.0 and Python 3.12+
|
||||
|
||||
# Runtime dependencies
|
||||
gunicorn
|
||||
|
|
@ -33,4 +36,19 @@ python-dotenv
|
|||
#ConcurrentLogHandler
|
||||
unidecode
|
||||
|
||||
# Additional dependencies for Django 5.0 and Wagtail 6
|
||||
django-configurations
|
||||
django-taggit>=5.0.0 # Required by Wagtail 6
|
||||
wagtail-modeladmin==2.0.0 # Separate package for ModelAdmin in Wagtail 5+
|
||||
djangorestframework>=3.15.0 # Required by Wagtail API
|
||||
django-modelcluster>=6.3 # Required by Wagtail 6
|
||||
django-treebeard>=4.7 # Required by Wagtail 6
|
||||
django-filter>=23.3,<24 # Required by Wagtail 6.0.6 (must be <24)
|
||||
Willow>=1.8.0 # Required by Wagtail for images
|
||||
beautifulsoup4>=4.12.0 # Required by Wagtail
|
||||
html5lib>=1.1 # Required by Wagtail
|
||||
openpyxl>=3.1.0 # For Excel export support
|
||||
l18n # For Wagtail localization
|
||||
telepath>=0.3.1 # Required by Wagtail 6
|
||||
# Django 5.0 timezone support (replaces pytz)
|
||||
tzdata # For timezone support in Django 5.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue