From 978b6fa24b38e7fa532e583ed8403928fa896e14 Mon Sep 17 00:00:00 2001 From: marwin Date: Mon, 16 Mar 2026 20:24:20 +0100 Subject: [PATCH] Store background images in DB, persist SQLite via volume --- Dockerfile | 2 +- .../0002_userprofile_background_image.py | 7 ++--- accounts/models.py | 7 +---- accounts/views.py | 30 ++++++++----------- diora/settings.py | 2 +- templates/accounts/settings.html | 4 +-- templates/base.html | 6 ++-- 7 files changed, 22 insertions(+), 36 deletions(-) diff --git a/Dockerfile b/Dockerfile index fc23571..22e29f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ RUN pip install --no-cache-dir -r requirements.txt gunicorn COPY . . -RUN python manage.py collectstatic --noinput +RUN python manage.py collectstatic --noinput && mkdir -p /app/data EXPOSE 8000 diff --git a/accounts/migrations/0002_userprofile_background_image.py b/accounts/migrations/0002_userprofile_background_image.py index f206262..0dbe202 100644 --- a/accounts/migrations/0002_userprofile_background_image.py +++ b/accounts/migrations/0002_userprofile_background_image.py @@ -1,6 +1,3 @@ -# Generated by Django 4.2.29 on 2026-03-15 21:37 - -import accounts.models from django.db import migrations, models @@ -13,7 +10,7 @@ class Migration(migrations.Migration): operations = [ migrations.AddField( model_name='userprofile', - name='background_image', - field=models.FileField(blank=True, null=True, upload_to=accounts.models._bg_upload_path), + name='background_image_data', + field=models.TextField(blank=True), ), ] diff --git a/accounts/models.py b/accounts/models.py index 3be0b7c..aedc261 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -4,17 +4,12 @@ from django.db.models.signals import post_save from django.dispatch import receiver -def _bg_upload_path(instance, filename): - ext = filename.rsplit('.', 1)[-1].lower() - return f'backgrounds/bg_{instance.user_id}.{ext}' - - class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') lastfm_session_key = models.CharField(max_length=100, blank=True) lastfm_username = models.CharField(max_length=100, blank=True) lastfm_scrobble = models.BooleanField(default=True) - background_image = models.FileField(upload_to=_bg_upload_path, null=True, blank=True) + background_image_data = models.TextField(blank=True) # base64 data URL def has_lastfm(self) -> bool: return bool(self.lastfm_session_key) diff --git a/accounts/views.py b/accounts/views.py index d40daa0..c23ec7a 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,4 +1,4 @@ -import os +import base64 from django.conf import settings from django.contrib.auth import authenticate, login, get_user_model from django.contrib.auth.decorators import login_required @@ -123,35 +123,29 @@ def upload_background(request): return JsonResponse({'error': 'no file'}, status=400) ext = f.name.rsplit('.', 1)[-1].lower() if '.' in f.name else '' - if ext not in ('jpg', 'jpeg', 'png', 'webp'): + mime_map = {'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'webp': 'image/webp'} + if ext not in mime_map: return JsonResponse({'error': 'only jpg, png, or webp allowed'}, status=400) if f.size > settings.BG_MAX_BYTES: return JsonResponse({'error': 'file too large (max 5 MB)'}, status=400) - profile = request.user.profile - # Delete old file from disk before replacing - if profile.background_image: - old_path = profile.background_image.path - if os.path.exists(old_path): - os.remove(old_path) + data = base64.b64encode(f.read()).decode('ascii') + data_url = f"data:{mime_map[ext]};base64,{data}" - profile.background_image = f - profile.save(update_fields=['background_image']) - return JsonResponse({'ok': True, 'url': profile.background_image.url}) + profile = request.user.profile + profile.background_image_data = data_url + profile.save(update_fields=['background_image_data']) + return JsonResponse({'ok': True, 'url': data_url}) @login_required @require_http_methods(['POST']) def delete_background(request): profile = request.user.profile - if profile.background_image: - path = profile.background_image.path - if os.path.exists(path): - os.remove(path) - profile.background_image = None - profile.save(update_fields=['background_image']) - return JsonResponse({'ok': True}) + profile.background_image_data = '' + profile.save(update_fields=['background_image_data']) + return redirect('settings') @login_required diff --git a/diora/settings.py b/diora/settings.py index b25c940..7c64f01 100644 --- a/diora/settings.py +++ b/diora/settings.py @@ -59,7 +59,7 @@ WSGI_APPLICATION = 'diora.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + 'NAME': BASE_DIR / 'data' / 'db.sqlite3', } } diff --git a/templates/accounts/settings.html b/templates/accounts/settings.html index d721f25..3684caa 100644 --- a/templates/accounts/settings.html +++ b/templates/accounts/settings.html @@ -42,9 +42,9 @@

Background

- {% if request.user.profile.background_image %} + {% if request.user.profile.background_image_data %}

- Your background + Your background

{% csrf_token %} diff --git a/templates/base.html b/templates/base.html index 5ba04f1..122406b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -12,10 +12,10 @@ {% block title %}diora{% endblock %} - {% if user.is_authenticated and user.profile.background_image %} + {% if user.is_authenticated and user.profile.background_image_data %} {% endif %} - +