feat: Assign upload groups to existing and news v1 uploads

merge-requests/2666/merge^2
Georg Krause 2024-01-15 12:11:35 +00:00
rodzic c0282b850d
commit d6418ff016
8 zmienionych plików z 151 dodań i 1 usunięć

Wyświetl plik

@ -57,6 +57,7 @@ class UploadAdmin(admin.ModelAdmin):
"size",
"bitrate",
"import_status",
"upload_group",
]
list_select_related = ["track"]
search_fields = [
@ -69,6 +70,11 @@ class UploadAdmin(admin.ModelAdmin):
list_filter = ["mimetype", "import_status", "library__privacy_level"]
@admin.register(models.UploadGroup)
class UploadGroupAdmin(admin.ModelAdmin):
pass
@admin.register(models.UploadVersion)
class UploadVersionAdmin(admin.ModelAdmin):
list_display = [

Wyświetl plik

@ -164,6 +164,14 @@ class TrackFactory(
license = factory.PostGeneration(_license_post_generation)
@registry.register
class UploadGroupFactory(factory.django.DjangoModelFactory):
name = factory.Faker("name")
class Meta:
model = "music.UploadGroup"
@registry.register
class UploadFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory):
fid = factory.Faker("federation_url")
@ -172,6 +180,7 @@ class UploadFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory):
audio_file = factory.django.FileField(
from_path=os.path.join(SAMPLES_PATH, "test.ogg")
)
upload_group = factory.SubFactory(UploadGroupFactory)
bitrate = None
size = None

Wyświetl plik

@ -0,0 +1,23 @@
# Generated by Django 3.2.23 on 2024-01-15 10:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("music", "0058_uploadgroup"),
]
operations = [
migrations.AddField(
model_name="upload",
name="upload_group",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="uploads",
to="music.uploadgroup",
),
),
]

Wyświetl plik

@ -0,0 +1,20 @@
# Generated by Django 3.2.23 on 2024-01-15 10:55
from django.db import migrations
def populate_upload_groups(apps, schema_editor):
upload = apps.get_model("music", "Upload")
upload_group = apps.get_model("music", "UploadGroup")
for upload in upload.objects.all():
group, _ = upload_group.objects.get_or_create(name=upload.import_reference)
upload.upload_group = group
upload.save()
class Migration(migrations.Migration):
dependencies = [
("music", "0059_upload_upload_group"),
]
operations = [migrations.RunPython(populate_upload_groups)]

Wyświetl plik

@ -0,0 +1,22 @@
# Generated by Django 3.2.23 on 2024-01-15 11:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("music", "0060_auto_20240115_1055"),
]
operations = [
migrations.AlterField(
model_name="upload",
name="upload_group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="uploads",
to="music.uploadgroup",
),
),
]

Wyświetl plik

@ -738,6 +738,9 @@ class Upload(models.Model):
related_name="uploads",
on_delete=models.CASCADE,
)
upload_group = models.ForeignKey(
"UploadGroup", related_name="uploads", on_delete=models.CASCADE
)
# metadata from federation
metadata = JSONField(
@ -754,6 +757,7 @@ class Upload(models.Model):
)
# a short reference provided by the client to group multiple files
# in the same import
# TODO DEPRECATED This can be removed when APIv1 gets removed or fully replace by import_group.name
import_reference = models.CharField(max_length=50, default=get_import_reference)
# optional metadata about import results (error messages, etc.)
@ -1434,5 +1438,17 @@ def update_request_status(sender, instance, created, **kwargs):
class UploadGroup(models.Model):
"""
Upload groups are supposed to bundle uploads in order to make it easier to keep an overview
Attributes
----------
name A name that can be selected by the user
guid A globally unique identifier to reference the group
"""
name = models.CharField(max_length=255, default=datetime.datetime.now)
guid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
def __str__(self):
return self.name

Wyświetl plik

@ -790,7 +790,11 @@ class UploadViewSet(
return context
def perform_create(self, serializer):
upload = serializer.save()
group_name = serializer.validated_data.get("import_reference") or str(
datetime.datetime.date(datetime.datetime.now())
)
upload_group, _ = models.UploadGroup.objects.get_or_create(name=group_name)
upload = serializer.save(upload_group=upload_group)
if upload.import_status == "pending":
common_utils.on_commit(tasks.process_upload.delay, upload_id=upload.pk)

Wyświetl plik

@ -810,6 +810,56 @@ def test_user_can_create_upload(logged_in_api_client, factories, mocker, audio_f
m.assert_called_once_with(tasks.process_upload.delay, upload_id=upload.pk)
def test_upload_creates_implicit_upload_group(
logged_in_api_client, factories, mocker, audio_file
):
library = factories["music.Library"](actor__user=logged_in_api_client.user)
url = reverse("api:v1:uploads-list")
upload_group_count = models.UploadGroup.objects.count()
response = logged_in_api_client.post(
url,
{
"audio_file": audio_file,
"source": "upload://test",
"library": library.uuid,
"import_metadata": '{"title": "foo"}',
},
)
assert response.status_code == 201
assert upload_group_count + 1 == models.UploadGroup.objects.count()
assert (
models.UploadGroup.objects.filter(
name=str(datetime.datetime.date(datetime.datetime.now()))
).count()
== 1
)
def test_upload_creates_named_upload_group(
logged_in_api_client, factories, mocker, audio_file
):
library = factories["music.Library"](actor__user=logged_in_api_client.user)
url = reverse("api:v1:uploads-list")
upload_group_count = models.UploadGroup.objects.count()
response = logged_in_api_client.post(
url,
{
"audio_file": audio_file,
"source": "upload://test",
"import_reference": "test",
"library": library.uuid,
"import_metadata": '{"title": "foo"}',
},
)
assert response.status_code == 201
assert upload_group_count + 1 == models.UploadGroup.objects.count()
assert models.UploadGroup.objects.filter(name="test").count() == 1
def test_user_can_create_upload_in_channel(
logged_in_api_client, factories, mocker, audio_file
):