diff --git a/videodinges/admin.py b/videodinges/admin.py index 2c3a133..21431d5 100644 --- a/videodinges/admin.py +++ b/videodinges/admin.py @@ -1,10 +1,26 @@ +from django import forms from django.contrib import admin +from django.core.exceptions import ValidationError from . import models -class TranscodingsInline(admin.TabularInline): +class TranscodingsForm(forms.ModelForm): + def clean(self): + cleaned_data = super().clean() + if not cleaned_data['url'] and not cleaned_data['upload']: + validation_error = ValidationError('Either url or upload must be given', code='invalid') + self.add_error('url', validation_error) + self.add_error('upload', validation_error) + if cleaned_data['url'] and cleaned_data['upload']: + validation_error = ValidationError('Cannot fill both url and upload', code='invalid') + self.add_error('url', validation_error) + self.add_error('upload', validation_error) + return cleaned_data + +class TranscodingsInline(admin.StackedInline): model = models.Transcoding - fields = ['quality', 'file'] + form = TranscodingsForm + fields = ['quality', 'url', 'upload'] extra = 0 class VideoAdmin(admin.ModelAdmin): @@ -12,4 +28,5 @@ class VideoAdmin(admin.ModelAdmin): fields = ['title', 'description', 'slug'] inlines = [TranscodingsInline] -admin.site.register(models.Video, VideoAdmin) \ No newline at end of file +admin.site.register(models.Video, VideoAdmin) +admin.site.register(models.Upload) diff --git a/videodinges/models.py b/videodinges/models.py index 82b907c..4bd2779 100644 --- a/videodinges/models.py +++ b/videodinges/models.py @@ -1,7 +1,10 @@ +import os from datetime import datetime from typing import NamedTuple, Optional from django.db import models +from django.db.models import constraints +from django.db.models.query_utils import Q class Quality(NamedTuple): name: str @@ -32,12 +35,19 @@ class Video(models.Model): def __str__(self): return self.title +class Upload(models.Model): + id = models.AutoField(primary_key=True) + file = models.FileField() + + def __str__(self): + return os.path.basename(self.file.path) class Transcoding(models.Model): id = models.AutoField(primary_key=True) video = models.ForeignKey(Video, on_delete=models.CASCADE, related_name='transcodings') quality = models.CharField(choices=((quality.name, quality.name) for quality in qualities), max_length=128) - file = models.FileField() + upload = models.OneToOneField(Upload, on_delete=models.PROTECT, blank=True, null=True) + url = models.CharField(max_length=256, null=True, blank=True, unique=True) def __str__(self): return self.quality @@ -48,6 +58,11 @@ class Transcoding(models.Model): class Meta: unique_together = ('video', 'quality') + constraints = [constraints.CheckConstraint(check=Q(upload__isnull=False) | Q(url__isnull=False), + name='upload_or_url_is_filled'), + constraints.CheckConstraint(check=~(Q(upload__isnull=False) & Q(url__isnull=False)), + name='upload_and_url_cannot_both_be_filled'), + ] def get_quality_by_name(name: str) -> Optional[Quality]: for quality in qualities: