This commit is contained in:
relikd
2023-10-02 23:39:20 +02:00
commit 8629b01da3
47 changed files with 1412 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
from .organization import Organization # noqa: F401
from .member import Member # noqa: F401

View File

@@ -0,0 +1,97 @@
from pathlib import PosixPath
from django.conf import settings
from django.db import models
from app.form.file_with_img_preview import FileWithImagePreview, ImageValidator
from app.utils import encrypt, overwrite_upload, random_secret
import os
import uuid
import json
import base64
class Member(models.Model):
# auto-generated ids
uuid = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False)
secret = models.CharField(
max_length=20, default=random_secret, editable=False)
# member info
organization = models.ForeignKey(
'Organization', on_delete=models.CASCADE, related_name='members')
member_id = models.CharField('Mitglieder-Nr.', max_length=20)
name = models.CharField('Name', max_length=100)
valid_since = models.DateField('Mitglied seit')
valid_until = models.DateField('Mitglied bis', blank=True, null=True)
image = FileWithImagePreview(
'Bild', blank=True, null=True,
upload_to=overwrite_upload, validators=[ImageValidator.validate],
help_text=ImageValidator.help_text)
additional = models.JSONField(
'Zusätzliche Daten (JSON)', blank=True, null=True)
class Meta:
verbose_name = 'Mitglied'
verbose_name_plural = 'Mitglieder'
def __str__(self) -> str:
return self.name
@property
def export_url(self) -> str:
return self.organization.exportBaseUrl + \
f"#{self.organization.slug}/{self.uuid}/{self.secret}"
@property
def export_os_path(self) -> PosixPath:
return settings.EXPORT_PATH / self.organization.slug / str(self.uuid)
@property
def image_save_url(self) -> str:
return f'{self.organization.slug}/{self.uuid}'
@property
def image_os_path(self) -> PosixPath:
return settings.MEDIA_ROOT / self.organization.slug / str(self.uuid)
@property
def json(self):
return json.dumps({
'name': self.name,
'org': self.organization.name,
'id': self.member_id,
'valid_since': str(self.valid_since or ''),
'valid_until': str(self.valid_until or ''),
'data': self.additional or '',
'img': base64.b64encode(self.image.read()).decode(
'utf-8') if self.image else None,
})
@property
def json_encrypted(self) -> bytes:
return encrypt(self.json, self.secret)
def export(self):
os.makedirs(self.export_os_path.parent, exist_ok=True)
with open(self.export_os_path, 'wb') as fp:
fp.write(self.json_encrypted)
def save(self, *args, **kwargs):
if self.pk:
try:
prev = Member.objects.get(pk=self.pk)
if prev.image != self.image:
prev.image.delete(save=False)
except Member.DoesNotExist:
pass
self.export()
return super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
if self.image:
self.image.delete(save=False)
if os.path.isfile(self.export_os_path):
os.remove(self.export_os_path)
return super().delete(*args, **kwargs)

View File

@@ -0,0 +1,53 @@
from django.conf import settings
from django.db import models
import os
import shutil
import typing
if typing.TYPE_CHECKING:
from app.models.member import Member
class Organization(models.Model):
name = models.CharField('Name', max_length=100)
slug = models.SlugField('URL Slug', unique=True, max_length=50)
exportBaseUrl = models.URLField('Export Base-URL', max_length=200)
members: 'models.QuerySet[Member]'
class Meta:
verbose_name = 'Organisation'
verbose_name_plural = 'Organisationen'
def __str__(self) -> str:
return self.name
def save(self, *args, **kwargs):
if self.pk:
try:
prev = Organization.objects.get(pk=self.pk)
if prev.slug != self.slug:
renameSlug(prev.slug, self.slug)
except Organization.DoesNotExist:
pass
return super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
deleteSlug(self.slug)
return super().delete(*args, **kwargs)
def renameSlug(oldSlug: str, newSlug: str):
if newSlug == oldSlug:
return
oldExportPath = settings.EXPORT_PATH / oldSlug
oldMediaPath = settings.MEDIA_ROOT / oldSlug
if os.path.exists(oldExportPath):
os.rename(oldExportPath, settings.EXPORT_PATH / newSlug)
if os.path.exists(oldMediaPath):
os.rename(oldMediaPath, settings.MEDIA_ROOT / newSlug)
def deleteSlug(oldSlug: str):
shutil.rmtree(settings.EXPORT_PATH / oldSlug, ignore_errors=True)
shutil.rmtree(settings.MEDIA_ROOT / oldSlug, ignore_errors=True)