use UUID for manual item media_id generation to prevent casting errors #1285

This commit is contained in:
FuzzyGrim
2026-04-02 16:46:00 +02:00
parent 4bf4ced28f
commit 10cf944b58
4 changed files with 32 additions and 22 deletions

View File

@@ -184,7 +184,7 @@ class ManualItemForm(forms.ModelForm):
instance.media_id = parent_season.item.media_id
instance.season_number = parent_season.item.season_number
else:
instance.media_id = Item.generate_manual_id(instance.media_type)
instance.media_id = Item.generate_manual_id()
if commit:
instance.save()

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.12 on 2026-04-02 14:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0055_alter_item_media_type'),
]
operations = [
migrations.AlterField(
model_name='item',
name='media_id',
field=models.CharField(max_length=36),
),
]

View File

@@ -1,4 +1,5 @@
import logging
import uuid
from django.apps import apps
from django.conf import settings
@@ -12,14 +13,13 @@ from django.db.models import (
CheckConstraint,
Count,
F,
IntegerField,
Max,
Prefetch,
Q,
UniqueConstraint,
Window,
)
from django.db.models.functions import Cast, RowNumber
from django.db.models.functions import RowNumber
from django.utils import timezone
from model_utils import FieldTracker
from model_utils.fields import MonitorField
@@ -67,7 +67,8 @@ class MediaTypes(models.TextChoices):
class Item(CalendarTriggerMixin, models.Model):
"""Model to store basic information about media items."""
media_id = models.CharField(max_length=20)
# limited by uuid for manual entries
media_id = models.CharField(max_length=36)
source = models.CharField(
max_length=20,
choices=Sources,
@@ -168,21 +169,12 @@ class Item(CalendarTriggerMixin, models.Model):
return name
@classmethod
def generate_manual_id(cls, media_type):
"""Generate a new ID for manual items."""
latest_item = (
cls.objects.filter(source=Sources.MANUAL.value, media_type=media_type)
.annotate(
media_id_int=Cast("media_id", IntegerField()),
)
.order_by("-media_id_int")
.first()
)
def generate_manual_id(cls):
"""Generate a new ID for manual items.
if latest_item is None:
return "1"
return str(int(latest_item.media_id) + 1)
Uses a UUID to ensure uniqueness.
"""
return str(uuid.uuid4())
def fetch_releases(self, delay):
"""Fetch releases for the item."""

View File

@@ -279,7 +279,7 @@ class ManualItemFormTest(TestCase):
# Save and verify
item = form.save()
self.assertEqual(item.source, Sources.MANUAL.value)
self.assertEqual(item.media_id, "1")
self.assertTrue(item.media_id)
self.assertIsNone(item.season_number)
self.assertIsNone(item.episode_number)
@@ -377,7 +377,7 @@ class ManualItemFormTest(TestCase):
self.assertTrue(form2.is_valid())
item2 = form2.save()
# IDs should be different but follow the pattern
# IDs should be different
self.assertNotEqual(item1.media_id, item2.media_id)
self.assertEqual(item1.media_id, "1")
self.assertEqual(item2.media_id, "2")
self.assertTrue(item1.media_id)
self.assertTrue(item2.media_id)