Files
oximg/app/upload/models.py
2025-08-31 00:29:53 +02:00

173 lines
5.0 KiB
Python

from django.utils import timezone
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
import uuid
from pathlib import Path
from nanoid import generate
def generate_unique_slug_for_upload(size=10):
while True:
slug = generate(size=size)
if not Upload.objects.filter(slug=slug).exists():
return slug
def upload_to(instance, filename):
today = timezone.now().date()
dest_path = Path(f"uploads/{str(today.year)}/{str(today.month)}/{str(today.day)}")
if not dest_path.exists():
dest_path.mkdir(parents=True)
uid = uuid.uuid4().hex
file_path = Path(filename)
return str(dest_path / f"{uid}{file_path.suffix}")
class Upload(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4)
created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey('user.User', on_delete=models.CASCADE, null=True, blank=True)
filename = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True, default=generate_unique_slug_for_upload, editable=False)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True, blank=True)
object_id = models.UUIDField(null=True, blank=True)
content_object = GenericForeignKey('content_type', 'object_id')
class AbstractFile(models.Model):
file = models.FileField(upload_to=upload_to)
content_type = models.CharField(max_length=255)
size = models.PositiveBigIntegerField()
name = models.CharField(max_length=255)
class Meta:
abstract = True
def save(self, *args, **kwargs):
if self.file:
from utils import get_mimetype
self.size = self.file.size
self.content_type = get_mimetype(self.file)
self.name = self.file.name
class Image(AbstractFile):
allowed_mimetypes = [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/bmp",
"image/svg+xml",
"image/tiff",
"image/x-icon", # favicon
"image/vnd.microsoft.icon"
]
pass
class Video(AbstractFile):
allowed_mimetypes = [
"video/mp4",
"video/quicktime", # .mov
"video/x-msvideo", # .avi
"video/x-matroska", # .mkv
"video/webm",
"video/mpeg",
"video/ogg"
]
pass
class Audio(AbstractFile):
allowed_mimetypes = [
"audio/mpeg", # .mp3
"audio/wav", # .wav
"audio/x-wav",
"audio/ogg", # .ogg
"audio/webm", # .webm audio
"audio/aac",
"audio/flac",
"audio/x-flac"
]
pass
class Document(AbstractFile):
allowed_mimetypes = [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", # .docx
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # .xlsx
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation", # .pptx
"application/rtf",
"text/plain",
"text/csv"
]
pass
class Archive(AbstractFile):
allowed_mimetypes = [
"application/zip",
"application/x-tar",
"application/x-gzip",
"application/x-bzip2",
"application/x-7z-compressed",
"application/x-rar-compressed"
]
class Text(AbstractFile):
allowed_mimetypes = [
"text/plain", # .txt, .log
]
pass
class Code(AbstractFile):
allowed_mimetypes = [
"text/x-python", # .py
"text/x-shellscript", # .sh, .bash
"text/x-csrc", # .c
"text/x-c++src", # .cpp, .cc
"text/x-java-source", # .java
"text/x-go", # .go
"text/x-rustsrc", # .rs
"text/x-sql", # .sql
"text/x-markdown", # .md
"text/markdown", # .md (alternative)
"text/x-makefile", # Makefile
"text/x-php", # .php
"application/javascript", # .js (modern)
"text/javascript", # .js (legacy)
"text/css", # .css
"application/x-perl", # .pl
"application/x-ruby", # .rb
"application/x-lua", # .lua
]
class StructuredData(AbstractFile):
allowed_mimetypes = [
"application/json", # .json
"application/xml", # .xml
"text/xml", # .xml alternative
"text/csv", # .csv
"text/tab-separated-values", # .tsv
"application/x-yaml", # .yaml (rare)
"text/x-yaml", # .yaml, .yml (le plus courant)
"application/vnd.ms-excel", # .xls (Excel legacy)
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # .xlsx
"application/x-hdf", # .hdf, .h5
"application/x-parquet", # .parquet
"application/x-ndjson", # .ndjson (newline-delimited JSON)
"application/x-netcdf", # .nc
]
class Other(AbstractFile):
allowed_extensions = []
pass