Условно изменить значение поля для поиска в Django ORM - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь условно изменить значение поля во время поиска - у меня есть какой-то определенный порядок, и я не хочу перезаписывать значение поля, просто отсортировать его по-своему. Допустим, у меня есть класс Product, и у каждого объекта класса есть поле product_code. Теперь я хочу получить меньше или равно, но это не тривиально - product_code в большинстве случаев похож на A01, B02 и так далее, и Django lookup lte будет работать. Но теперь у меня есть поля 0001C01, которые я бы хотел иметь наибольшее значение. Поэтому во время поиска я хотел бы добавить 0000 в начале каждой строки, у которой нет этого префикса, чтобы она выглядела как 0001C01, 0000B02, 0000A01.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вы можете условно аннотировать ваш набор запросов, чтобы получить новое поле с желаемым значением, а затем использовать это поле в предложении filter или order_by.Например, вы можете сделать следующее:

from django.db.models import CharField, Value as V, F, Q, Case, When
from django.db.models.functions import Concat

Product.objects.annotate(
    new_product_code=Case(
        When(product_code__iregex=r'^[A-Z]+.*',  # If it starts with letters  
             then=Concat(V('0000'), 'product_code', output_field=CharField())  # Then prepend four 0's
        ), 
        default=F('product_code')  # Else, the original value
    )
).filter(new_product_code__lte='whatever you like')  # Now filter by using your new value

Соответствующими частями документации являются условные выражения , функции базы данных и Справочник по API QuerySet

0 голосов
/ 19 ноября 2018

Это звучит довольно просто. Выберите нужные Product объекты, и для каждого из них добавьте 0000 к product_code, если он не начинается с этой строки.

products = Product.objects.filter(some_query_expression)
for product in products:
    if not product.product_code.startswith('0000'):
        product.product_code = '0000' + product.product_code

Непонятно, хотите ли вы сохранить это значение обратно в базу данных или просто использовать его для временных сравнений. Если вы хотите сохранить его, звоните product.save().

...