Add file selector to snapshots

This commit is contained in:
Edgar P. Burkhart 2022-12-21 14:02:15 +01:00
parent 996f6a9f18
commit e11749f187
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
6 changed files with 76 additions and 5 deletions

View file

@ -0,0 +1,44 @@
# Generated by Django 4.1.4 on 2022-12-21 08:53
import datetime
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("main", "0006_alter_category_options_alter_invoice_options_and_more"),
]
operations = [
migrations.AddField(
model_name="snapshot",
name="file",
field=models.FileField(
blank=True,
max_length=128,
null=True,
upload_to="snapshots/",
validators=[django.core.validators.FileExtensionValidator(["pdf"])],
verbose_name="Fichier",
),
),
migrations.AlterField(
model_name="invoice",
name="file",
field=models.FileField(
max_length=128,
upload_to="invoices/",
validators=[django.core.validators.FileExtensionValidator(["pdf"])],
verbose_name="Fichier",
),
),
migrations.AlterField(
model_name="snapshot",
name="date",
field=models.DateField(
default=datetime.date.today, unique=True, verbose_name="Date"
),
),
]

View file

@ -1,9 +1,11 @@
import pathlib
from datetime import date from datetime import date
import uuid import uuid
from django.db import models from django.db import models
from django.forms import ModelForm from django.forms import ModelForm
from django.core.validators import FileExtensionValidator from django.core.validators import FileExtensionValidator
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.core.files.storage import Storage
class Category(models.Model): class Category(models.Model):
@ -90,15 +92,20 @@ class TransactionForm(ModelForm):
] ]
def invoice_path(instance, filename):
return pathlib.Path("invoices", str(instance.id), filename)
class Invoice(models.Model): class Invoice(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField( name = models.CharField(
max_length=256, default=_("Invoice"), verbose_name=_("Name") max_length=256, default=_("Invoice"), verbose_name=_("Name")
) )
file = models.FileField( file = models.FileField(
upload_to="invoices/", upload_to=invoice_path,
validators=[FileExtensionValidator(["pdf"])], validators=[FileExtensionValidator(["pdf"])],
verbose_name=_("File"), verbose_name=_("File"),
max_length=128,
) )
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE) transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
@ -123,6 +130,10 @@ class InvoiceForm(ModelForm):
fields = ["name", "file"] fields = ["name", "file"]
def snapshot_path(instance, filename):
return pathlib.Path("snapshots", str(instance.id)).with_suffix(".pdf")
class Snapshot(models.Model): class Snapshot(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date = models.DateField(default=date.today, unique=True, verbose_name=_("Date")) date = models.DateField(default=date.today, unique=True, verbose_name=_("Date"))
@ -135,12 +146,22 @@ class Snapshot(models.Model):
diff = models.DecimalField( diff = models.DecimalField(
max_digits=12, decimal_places=2, editable=False, blank=True, null=True max_digits=12, decimal_places=2, editable=False, blank=True, null=True
) )
file = models.FileField(
upload_to=snapshot_path,
validators=[FileExtensionValidator(["pdf"])],
verbose_name=_("File"),
max_length=256,
blank=True,
)
def __str__(self): def __str__(self):
return f"{_('Snapshot')} {self.date}" return f"{_('Snapshot')} {self.date}"
def save(self, *args, only_super=False, **kwargs): def save(self, *args, only_super=False, **kwargs):
if not only_super: if not only_super:
_prever = Snapshot.objects.get(id=self.id)
if _prever.file and _prever.file != self.file:
pathlib.Path(_prever.file.path).unlink(missing_ok=True)
_prev = ( _prev = (
self.__class__.objects.order_by("-date") self.__class__.objects.order_by("-date")
.exclude(id=self.id) .exclude(id=self.id)
@ -188,6 +209,7 @@ class Snapshot(models.Model):
_next.save(only_super=True) _next.save(only_super=True)
def delete(self, *args, only_super=False, **kwargs): def delete(self, *args, only_super=False, **kwargs):
self.file.delete()
if not only_super: if not only_super:
try: try:
_next = self.__class__.objects.get(previous=self) _next = self.__class__.objects.get(previous=self)
@ -244,4 +266,4 @@ class SnapshotForm(ModelForm):
class Meta: class Meta:
model = Snapshot model = Snapshot
fields = ["date", "value"] fields = ["date", "value", "file"]

View file

@ -23,7 +23,7 @@
{{ snapshot }} {{ snapshot }}
</h1> </h1>
<form action="{% url 'snapshot' snapshot.id %}" method="post"> <form action="{% url 'snapshot' snapshot.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ form }} {{ form }}
{% form_buttons snapshot %} {% form_buttons snapshot %}

View file

@ -154,9 +154,11 @@ def snapshot(request, uuid=None):
_snapshot = Snapshot.objects.get(id=uuid) _snapshot = Snapshot.objects.get(id=uuid)
except Snapshot.DoesNotExist: except Snapshot.DoesNotExist:
_snapshot = Snapshot(id=uuid) _snapshot = Snapshot(id=uuid)
_form = SnapshotForm(request.POST, instance=_snapshot) _form = SnapshotForm(request.POST, request.FILES, instance=_snapshot)
if _form.is_valid(): if _form.is_valid():
_form.save() _form.save()
return redirect(snapshot, uuid=uuid)
context = { context = {
"snapshot": _snapshot, "snapshot": _snapshot,
"form": _form, "form": _form,

View file

@ -16,6 +16,7 @@ import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_ROOT = Path(os.environ.get("NUMMI_MEDIA_ROOT", "/var/lib/nummi")) MEDIA_ROOT = Path(os.environ.get("NUMMI_MEDIA_ROOT", "/var/lib/nummi"))
MEDIA_URL = "files/"
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production

View file

@ -17,10 +17,12 @@ from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = i18n_patterns( urlpatterns = i18n_patterns(
path("", include("main.urls")), path("", include("main.urls")),
path("plot/", include("plot.urls")), path("plot/", include("plot.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
prefix_default_language=False, prefix_default_language=False,
) ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)