Джанго - как сделать сложную математическую аннотацию

У меня есть эта модель:

class Image(models.Model):
    title = models.CharField(max_length=200)
    image = models.ImageField(upload_to='img/')
    signature = models.TextField(null = True)

Сигнатура представляет собой однослойный мономерный вектор, закодированный в json. Чтобы выполнить мой запрос, я должен декодировать каждую сигнатуру объекта в nparray и создавать точечное произведение между сигнатурой каждого объекта и данным вектором, а затем аннотировать как поле с плавающей точкой (с именем "Score") рядом с каждым необработанным. Наконец, я должен сделать заказ от макс до мин.

Я попробовал это в view.py

def image_sorted(request):
    query_signature = extract_feat(settings.MEDIA_ROOT + "/cache" + "/003_ant_image_0003.jpg") # a NParray object

    image_list = Image.objects.annotate(score=np.dot(
        JSONVectConverter.json_to_vect(F('signature')), query_signature.T
    ).astype(float)).order_by('score') #JSONVectConverter is a class of mine
    return render(request, 'images/sorted.html', {'image_sorted': image_list})

конечно это не работает. Я думаю, что оператор "F()" находится вне области видимости...

Если вам интересно, я пишу веб-приложение для поиска изображений для своей университетской диссертации.

Спасибо.

РЕДАКТИРОВАТЬ: я обнаружил, что это та же проблема (он использует Postgres вместо MySQL)

2 ответа

Решение

Я не был близок к тому, чтобы попробовать что-то такое сложное, однако я решил похожую проблему здесь: объединение Django F, Value и диктата для аннотирования набора запросов.

Я не пробовал это, но вы могли бы попробовать:

    from django.db.models import Case, When, FloatField
    query_signature = extract_feat(settings.MEDIA_ROOT + "/cache" + "/003_ant_image_0003.jpg") # a NParray object

    value_dict = {}
    for image in Image.objects.all():
        value_dict[image.signature] = np.dot(
            JSONVectConverter.json_to_vect(image.signature),
                query_signature.T
            ).astype(float) 
    whens = [
        When(signature=k, then=v) for k, v in value_dict.items()
    ]
    qs = Image.objects.all().annotate(
        score=Case(
            *whens,
            default=0,
            output_field=FloatField()
        )
    ).order_by('score')

Надеюсь, поможет

Итак, это последний рабочий код:

def image_sorted(request):
    query_signature = extract_feat(settings.MEDIA_ROOT + "/cache" + "/001_accordion_image_0001.jpg")  # a NParray object
    #query_signature = extract_feat(settings.MEDIA_ROOT + "/cache" + "/003_ant_image_0003.jpg")  # a NParray object


    value_dict = {}
    for image in Image.objects.all():
        S = image.signature
        value_dict[image.signature] = np.dot(
            JSONVectConverter.json_to_vect(S),
            query_signature.T
        ).astype(float)
    whens = [
        When(signature=k, then=v) for k, v in value_dict.items()
    ]
    qs = Image.objects.all().annotate(
        score=Case(
            *whens,
            default=0,
            output_field=FloatField()
        )
    ).order_by('-score')

    for image in qs:
        print(image.score)

    return render(request, 'images/sorted.html', {'image_sorted': qs})

Спасибо Омару за помощь! Конечно, я все еще здесь, если есть более тонкие решения.

Другие вопросы по тегам