from enum import unique import os, re from simple_history.models import HistoricalRecords from django.core.validators import FileExtensionValidator, RegexValidator from django.core.exceptions import ValidationError from django.db import models from django.conf import settings from versionfield import VersionField version_pattern = r'\d{1,2}\.\d{1,2}\.\d{1,2}' version_validator = RegexValidator(regex=version_pattern) extension_validator = FileExtensionValidator(allowed_extensions=['apk']) def minimum_version_validator(value, uploaded_version): try: latest_version = FlutterRelease.objects.latest('version').version if (value > latest_version) and (value != uploaded_version): raise ValidationError( (f'Minimum version ({value}) cannot be less than latest version ({latest_version}) or uploaded version ({uploaded_version})!'), params={'value': value}, ) except: if value != uploaded_version: raise ValidationError( (f'Minimum version ({value}) cannot be less than uploaded version ({uploaded_version})!'), params={'value': value}, ) def set_apk_filename_with_version(instance, filename): name = filename.split('.')[0] ext = filename.split('.')[-1] version = re.search(version_pattern, filename) if not version: filename = f'{name}-v{instance.version}.{ext}' return os.path.join('./flutter-releases/', filename) def get_minimum_version(): try: minimum_version = FlutterRelease.objects.latest('version').minimum_version return minimum_version except: return '' class FlutterRelease(models.Model): version = VersionField(unique=True, blank=False, null=False, validators=[version_validator] ) version.help_text='Set version if filename not annotated with version, eg "app-release-v.1.0.1.apk"' minimum_version = VersionField(blank=False, null=False, default=get_minimum_version, ) file = models.FileField(null=False, upload_to=set_apk_filename_with_version, validators=[extension_validator], ) update_notes = models.TextField(max_length=1000, blank=True, null=False, default='' ) release_date = models.DateTimeField(auto_now_add=True) history = HistoricalRecords() actions = ['delete_selected'] def save(self, *args, **kwargs): version = re.search(r'\d+.\d+.\d+', self.file.name) if version: self.version = version[0] minimum_version_validator(self.minimum_version, self.version) super(FlutterRelease, self).save(*args, **kwargs) def delete(self, *args, **kwargs): file = os.path.join(settings.MEDIA_ROOT, self.file.path) os.remove(file) super(FlutterRelease, self).delete(*args, **kwargs) class Meta: ordering = ["-version"] def __str__(self): formatted_datetime = self.release_date.strftime("%d.%m.%Y") return f'v.{self.version} from {formatted_datetime}'