Как создать GeneratedField с поиском из файла настроек?
Используя Django 5.1, я пытаюсь создать модель GeneratedField
, которая должна возвращать True или False в зависимости от того, какой файл был загружен. Модель будет принимать как изображения, так и видеофайлы. Я хочу сделать это для того, чтобы иметь возможность фильтровать, например, по CampMedia.objects.filter(is_image=True)
.
# models.py
from django.conf import settings
from django.db import models
from django.db.models import Case, Q, When
class CampMedia(models.Model):
media = models.FileField(upload_to="camps")
is_image = models.GeneratedField(
expression=Case(
When(
condition=Q([Q(media__endswith=ext) for ext in settings.VALID_IMAGE_FILETYPES], Q.OR),
then=True,
),
default=False,
),
output_field=models.BooleanField(),
db_persist=True,
)
# settings.py
VALID_IMAGE_FILETYPES = ["png", "jpg", "jpeg", "gif", "webp"]
Вот что генерируется в файле миграции:
# migrations/0007_image.py
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("camps", "0006_auto"),
]
operations = [
migrations.AddField(
model_name="campmedia",
name="image",
field=models.GeneratedField(
db_persist=True,
expression=models.Case(
models.When(
condition=models.Q(
[
models.Q(("media__endswith", "png")),
models.Q(("media__endswith", "jpg")),
models.Q(("media__endswith", "jpeg")),
models.Q(("media__endswith", "gif")),
models.Q(("media__endswith", "webp")),
],
"OR",
),
then=True,
),
default=False,
),
output_field=models.BooleanField(),
),
),
]
Однако при выполнении python manage.py migrations
возникает следующая ошибка:
Я попытался вручную отредактировать файл миграции так, чтобы он не содержал вложенных кортежей, но это привело к той же ошибке:
condition=models.Q(
[
models.Q("media__endswith", "png"),
models.Q("media__endswith", "jpg"),
models.Q("media__endswith", "jpeg"),
models.Q("media__endswith", "gif"),
models.Q("media__endswith", "webp"),
],
"OR",
),
Хотя я знаю, что можно добиться желаемого результата с помощью сигналов post_save
, это быстро становится довольно грязным, имхо.
TYIA!
Условие построено неверно, должно быть:
class CampMedia(models.Model):
media = models.FileField(upload_to='camps')
is_image = models.GeneratedField(
expression=Case(
When(
condition=Q(
*[
Q(media__endswith=ext)
for ext in settings.VALID_IMAGE_FILETYPES
],
_connector=Q.OR
),
then=True,
),
default=False,
),
output_field=models.BooleanField(),
db_persist=True,
)