Add file selector to snapshots
This commit is contained in:
parent
996f6a9f18
commit
e11749f187
6 changed files with 76 additions and 5 deletions
|
@ -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"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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"]
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue