Обогатить Django QuerySet разные результаты - PullRequest
0 голосов
/ 13 февраля 2019

Цель

Запрос всех продуктов, нарезка их на части, возвращение подмножества этих продуктов с добавлением key:value, другими словами, обогащенного.

Код, который работает, но я не могу использовать

Я не могу использовать этот код, потому что я использую paginator, paginator получает доступ к count из QuerySet.Если я передам нарезанный QuerySet , то это число будет только для этой нарезанной части, а не для общего QuerySet, поэтому я не могу его использовать.

products_qs = final_qs[paginator.get_offset(request):
                       paginator.get_offset(request) + paginator.get_limit(request)]
for product in products_qs:
    product.raw['super_cool_new_key'] = ms_response.get('results').get(product.id)

Это прекрасно работает, когда я печатаю данные, я вижу, что super_cool_new_key обогащение в каждом продукте.Потрясающие.Проблема?Ну, мне пришлось нарезать его, и теперь метод count больше не верен.Конечно, я могу сделать что-то вроде:

products_qs.count = final_qs.count

и продолжить свою жизнь, но это кажется ... хаком, а может и нет?

Код, который я хотел бычтобы он работал, но не

for i in range(paginator.get_offset(request),
               paginator.get_offset(request) + paginator.get_limit(request)):
    product = final_qs[i]
    product.raw['super_cool_new_key'] = ms_response.get('results').get(product.id)

Когда я вижу вывод данных, super_cool_new_key там нет.Я не могу понять, почему?

Возможно, у меня тяжелый день, и я не понимаю, как получить доступ по ссылке, поэтому я удаляю среднюю обезьяну.

final_qs = final_qs.all()
for i in range(paginator.get_offset(request),
               paginator.get_offset(request) + paginator.get_limit(request)):
    final_qs[i].raw['super_cool_new_key'] = ms_response.get('results').get(final_qs[i].id, '')

Подозрения

Очевидно, что разница в коде заключается в том, что один из способов работает, а другой - нет.Мой доллар следующий:

  • Срез
  • Итерация

Просмотр Django Docs для QuerySet :

Итерация.QuerySet является итеративным, и он выполняет свой запрос к базе данных при первой итерации по нему.

Затем о нарезке:

Slicing.Как объясняется в разделе Ограничение QuerySets, QuerySet может быть нарезан с использованием синтаксиса Python для нарезки массивов.Нарезка неоцененного QuerySet обычно возвращает другой неоцененный QuerySet, но Django выполнит запрос к базе данных, если вы используете параметр «step» синтаксиса слайса, и вернет список

Я не могу быть нарезкойтогда, потому что я не делаю срез с параметром "шаг".Поскольку он возвращает неоцененный QuerySet код, который я хочу работать, теоретически должен работать.(Разве это не всегда так? Ха-ха)

Хорошо, так что проясняется тот факт, что, когда в первом варианте кодирования я выполнил итерацию for x in x_container, QuerySet был выполнен.Может ли это быть ответом?Поэтому я изменил код:

Оповещение о спойлере: все еще не работает

final_qs = final_qs.all()
for i in range(paginator.get_offset(request),
               paginator.get_offset(request) + paginator.get_limit(request)):
    product = final_qs[i]
    product.raw['super_cool_new_key'] = ms_response.get('results').get(product.id)

Эммм ... помогите?

Aпредложил ответ, что, спойлер оповещения, не работал

from django.db.models import When, Case, Value, CharField
when = [ When(id=k, then=Value(v)) for k,v in ms_response.get('results').items()]
p = final_qs[paginator.get_offset(request)
             :paginator.get_offset(request) + paginator.get_limit(request)]
p = p.annotate(super_cool_new_key=Case(
            *when,
            default=Value(''),
            output_field=CharField()
        )
    )

Я также пробовал без нарезки , но с .all().annotate().Все еще не работал.Это не работает, не из-за возникновения Исключения, а потому, что когда я вижу вывод, этого super_cool_new_key нет, то есть он не обогатил объекты, а в этом весь смысл.

1 Ответ

0 голосов
/ 13 февраля 2019

Похоже, то, что вы ищете, похоже на ответ здесь , который использует Когда и Случай .Для вашего использования это будет что-то вроде следующего:

from django.db.models import When, Case, Value, CharField

ms_response = {5458: 'abc', 9900: 'def'}
whens = [
    When(id=k, then=Value(v)) for k, v in ms_response.items()
]
qs = YourModelName.objects.all().annotate(
    super_cool_key=Case(
        *whens,
        default=Value('xyz'),
        output_field=CharField()
    )
)

, когда вы тогда позвоните qs.get(id=5458).super_cool_key, тогда он вернет 'abc'

...