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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ jobs:
command: |
pip install --upgrade uv"==0.8.*" --quiet --no-input
- run: uv sync --only-group deploy --no-python-downloads
- setup_remote_docker
- run: printenv DC_DEPLOY_NAME DJANGO_SETTINGS_MODULE SAM_CONFIG_FILE DC_ENVIRONMENT SAM_PUBLIC_CONFIG_ENV
- run: printenv SECRET_KEY | md5sum
- run: printenv AWS_ACCESS_KEY_ID | md5sum
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.25 on 2025-10-15 15:01

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("core", "0001_initial"),
]

operations = [
migrations.DeleteModel(
name="Country",
),
migrations.DeleteModel(
name="EmailAlert",
),
migrations.DeleteModel(
name="EmailQue",
),
migrations.DeleteModel(
name="ImageQue",
),
migrations.DeleteModel(
name="ImageQueSeq",
),
]
12 changes: 12 additions & 0 deletions electionleaflets/apps/leaflets/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.contrib.auth.mixins import AccessMixin


class StaffuserRequiredMixin(AccessMixin):
"""Require that the user is a staff member."""

permission_denied_message = "You must be a staff user to access this page."

def dispatch(self, request, *args, **kwargs):
if not request.user.is_staff:
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
16 changes: 10 additions & 6 deletions electionleaflets/apps/leaflets/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
from copy import deepcopy
from pathlib import Path

import pytest
from django.conf import settings
from django.test import override_settings
from leaflets.models import Leaflet, LeafletImage
from leaflets.tests.conftest import TEST_IMAGE_LOCATION

TEST_STORAGES = deepcopy(settings.STORAGES)
TEST_STORAGES["default"]["BACKEND"] = (
"electionleaflets.storages.TempUploadS3MediaStorage"
)


@pytest.fixture
def leaflet():
Expand Down Expand Up @@ -95,12 +103,8 @@ def test_image_moved_from_temp_upload(db, uploaded_temp_file):
assert str(path) == leaflet_image.image.path


def test_image_moved_from_temp_upload_s3_backend(
db, settings, s3_bucket, s3_client
):
settings.DEFAULT_FILE_STORAGE = (
"electionleaflets.storages.TempUploadS3MediaStorage"
)
@override_settings(STORAGES=TEST_STORAGES)
def test_image_moved_from_temp_upload_s3_backend(db, s3_bucket, s3_client):
leaflet = Leaflet()
leaflet.save()
leaflet.refresh_from_db()
Expand Down
3 changes: 2 additions & 1 deletion electionleaflets/apps/leaflets/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import json
import random

from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
from core.helpers import CacheControlMixin
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.signing import Signer
from django.db import transaction
from django.db.models import Q
Expand All @@ -24,6 +24,7 @@
SingleLeafletImageForm,
UpdatePublisherDetails,
)
from .mixins import StaffuserRequiredMixin
from .models import Leaflet, LeafletImage


Expand Down
66 changes: 21 additions & 45 deletions electionleaflets/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from os.path import abspath, dirname, join

import dc_design_system
from dc_utils.settings.pipeline import * # noqa
from dc_utils.settings.pipeline import get_pipeline_settings


def here(x):
Expand Down Expand Up @@ -51,7 +53,10 @@ def root(x):
STATIC_URL = "/static/"
STATICFILES_DIRS = (root("assets"),)

DEFAULT_FILE_STORAGE = "electionleaflets.storages.TempUploadLocalMediaStorage"
STORAGES["default"] = { # noqa F405
"BACKEND": "electionleaflets.storages.TempUploadLocalMediaStorage"
}

AWS_S3_FILE_OVERWRITE = False
STATICFILES_MANIFEST_NAME = environ.get(
"STATICFILES_MANIFEST_NAME", "staticfiles.json"
Expand All @@ -61,61 +66,33 @@ def root(x):
# AWS_S3_HOST = "s3-eu-west-1.amazonaws.com"
# AWS_S3_CUSTOM_DOMAIN = "data.electionleaflets.org"

PIPELINE = {
"COMPILERS": ("pipeline.compilers.sass.SASSCompiler",),
"SASS_BINARY": "pysassc",
"CSS_COMPRESSOR": "pipeline.compressors.NoopCompressor",
"STYLESHEETS": {
"styles": {
"source_filenames": [
"scss/styles.scss",
"scss/vendor/filepond.css",
"scss/vendor/filepond-plugin-image-preview.css",
],
"output_filename": "scss/styles.css",
"extra_context": {
"media": "screen,projection",
},
},
},
"JAVASCRIPT": {
"scripts": {
"source_filenames": [
"javascript/app.js",
"javascript/vendor/filepond.js",
"javascript/vendor/filepond-plugin-image-exif-orientation.js",
"javascript/vendor/filepond-plugin-image-preview.js",
"javascript/image_uploader.js",
# "javascript/vendor/ImageEditor.js",
],
"output_filename": "app.js",
}
},
}

PIPELINE = get_pipeline_settings(
extra_css=[
"scss/styles.scss",
"scss/vendor/filepond.css",
"scss/vendor/filepond-plugin-image-preview.css",
],
extra_js=[
"javascript/app.js",
"javascript/vendor/filepond.js",
"javascript/vendor/filepond-plugin-image-exif-orientation.js",
"javascript/vendor/filepond-plugin-image-preview.js",
"javascript/image_uploader.js",
# "javascript/vendor/ImageEditor.js",
],
)

PIPELINE["CSS_COMPRESSOR"] = "pipeline.compressors.NoopCompressor"
PIPELINE["JS_COMPRESSOR"] = "pipeline.compressors.NoopCompressor"


PIPELINE["SASS_ARGUMENTS"] = (
" -I " + dc_design_system.DC_SYSTEM_PATH + "/system"
)

STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
"pipeline.finders.CachedFileFinder",
"pipeline.finders.PipelineFinder",
"pipeline.finders.ManifestFinder",
)

WHITENOISE_STATIC_PREFIX = "/static/"

SITE_ID = 1
SITE_LOGO = "images/logo.png"
USE_I18N = False
USE_L10N = True
LOGIN_URL = "/"

# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
Expand Down Expand Up @@ -173,7 +150,6 @@ def root(x):
"s3file",
"django_filters",
"dc_utils",
"querystring_tag",
] + LEAFLET_APPS


Expand Down
6 changes: 4 additions & 2 deletions electionleaflets/settings/base_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
WHITENOISE_STATIC_PREFIX = "/static/"

STATIC_URL = WHITENOISE_STATIC_PREFIX
STATICFILES_STORAGE = "electionleaflets.storages.StaticStorage"
STORAGES["staticfiles"] = {"BACKEND": "electionleaflets.storages.StaticStorage"} # noqa F405
STATICFILES_DIRS = (root("assets"),) # noqa: F405
STATIC_ROOT = root("static") # noqa: F405
MEDIA_ROOT = root( # noqa: F405
Expand All @@ -41,7 +41,9 @@

AWS_DEFAULT_ACL = "public-read"

DEFAULT_FILE_STORAGE = "electionleaflets.storages.TempUploadS3MediaStorage"
STORAGES["default"] = { # noqa F405
"BACKEND": "electionleaflets.storages.TempUploadS3MediaStorage"
}

AWS_STORAGE_BUCKET_NAME = os.environ.get("LEAFLET_IMAGES_BUCKET_NAME")
AWS_S3_SECURE_URLS = True
Expand Down
12 changes: 10 additions & 2 deletions electionleaflets/settings/local.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ DATABASES = {
}
}

DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
STORAGES = {
"default": { "BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": { "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"},
}

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
Expand All @@ -25,3 +28,8 @@ CACHES = {

#THUMBNAIL_DEBUG = True
THUMBNAIL_KVSTORE ='sorl.thumbnail.kvstores.cached_db_kvstore.KVStore'

# Debug Toolbar Setup
if DEBUG:
INSTALLED_APPS += ("debug_toolbar",)
MIDDLEWARE = ("debug_toolbar.middleware.DebugToolbarMiddleware",) + MIDDLEWARE # noqa: F405
8 changes: 6 additions & 2 deletions electionleaflets/settings/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"

DEFAULT_FILE_STORAGE = "electionleaflets.storages.TempUploadLocalMediaStorage"
STATICFILES_STORAGE = "electionleaflets.storages.StaticStorage"
STORAGES = {
"default": {
"BACKEND": "electionleaflets.storages.TempUploadLocalMediaStorage"
},
"staticfiles": {"BACKEND": "electionleaflets.storages.StaticStorage"},
}

# This is cleaned up in core/conftest.py
MEDIA_ROOT = mkdtemp()
Expand Down
1 change: 0 additions & 1 deletion electionleaflets/templates/core/pager.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{% load querystring_tag %}
{% if page_obj.paginator.num_pages > 1 %}
<nav class="ds-pagination">

Expand Down
15 changes: 15 additions & 0 deletions electionleaflets/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
Expand Down Expand Up @@ -122,8 +124,21 @@ def get_redirect_url(self, *args, **kwargs):
),
)


urlpatterns += redirect_urls

urlpatterns += static(
settings.STATIC_URL, document_root=settings.STATIC_ROOT
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG and "test" not in os.environ.get(
"DJANGO_SETTINGS_MODULE", ""
):
import debug_toolbar
from dc_utils.urls import dc_utils_testing_patterns

urlpatterns = (
[path("__debug__/", include(debug_toolbar.urls))]
+ dc_utils_testing_patterns
+ urlpatterns
)
30 changes: 13 additions & 17 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ name = "ElectionLeaflets"
version = "0.0.0"
description = "An online archive of political leaflets"
readme = "README.md"
requires-python = ">=3.12"
requires-python = "==3.12.*"
dependencies = [
"dj-pagination==2.5.0",
"django-braces==1.16.0",
"django-extensions==3.2.3",
"django-filter==25.1",
"django-formtools==2.2",
"django-localflavor==4.0",
"django-pipeline==4.0.0",
"django-extensions== 4.1.0 ",
"django-filter==25.2",
"django-formtools==2.5.1",
"django-localflavor==5.0",
"django-pipeline==4.1.0",
"django-s3file==5.5.7",
"django-ses==4.4.0",
"django-static-jquery==2.1.4",
"django-storages==1.14.5",
"django==4.2.25",
"djangorestframework==3.15.2",
"django-storages==1.14.6",
"django==5.2.7",
"djangorestframework==3.16.1",
"factory-boy==3.3.3",
"markdown==3.7",
"piexif==1.0.12",
Expand All @@ -31,9 +30,6 @@ dependencies = [
"dc-design-system",
"dc-django-utils",
"django-uk-political-parties",
# Remove this once we are on Django>=5.1
# https://docs.djangoproject.com/en/5.1/releases/5.1/#querystring-template-tag
"django-querystring-tag==1.0.3",
]

[tool.uv]
Expand All @@ -45,8 +41,8 @@ members = ["thumbs"]

[tool.uv.sources]
aws-wsgi = { git = "https://github.com/DemocracyClub/awsgi.git", rev = "b286f129c5580547577f942c75be74cdca707386" }
dc-design-system = { git = "https://github.com/DemocracyClub/design-system.git", tag = "0.7.0" }
dc-django-utils = { git = "https://github.com/DemocracyClub/dc_django_utils.git", tag = "8.0.4" }
dc-design-system = { git = "https://github.com/DemocracyClub/design-system.git", tag = "0.9.0" }
dc-django-utils = { git = "https://github.com/DemocracyClub/dc_django_utils.git", tag = "8.0.5" }
django-uk-political-parties = { git = "https://github.com/DemocracyClub/django-uk-political-parties.git", rev = "86ffa51f8306858c379c9de5be2f4bdb24b3a910" }

[tool.pytest.ini_options]
Expand All @@ -70,10 +66,10 @@ lint.extend-select = [
dev = [
"pytest==8.3.4",
"pytest-cov==6.0.0",
"pytest-django==4.10.0",
"pytest-django==4.11.0",
"pytest-playwright==0.7.0",
"moto[s3]==5.1.1",
"django-debug-toolbar==5.0.1",
"django-debug-toolbar==6.0.0",
"ruff==0.9.10",
]
deploy = [
Expand Down
4 changes: 2 additions & 2 deletions thumbs/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ name = "thumbs"
version = "0.0.0"
description = "Lambda function that produces thumbnails from raw leaflets"
readme = "README.md"
requires-python = ">=3.12"
requires-python = "==3.12.*"
dependencies = [
"django==4.2.25",
"django==5.2.7",
"pillow-heif==0.22.0",
"pillow==11.1.0",
"sentry-sdk==2.20.0",
Expand Down
Loading