Django query set filter reverse startswith on charfield
Представьте себе некий продукт-правило, у которого есть 2 условия:
- имена одинаковые
- sku's имеют частичное совпадение, начинается с.
Модель правила выглядит следующим образом:
class CreateAndAssignRule(models.Model):
name_equals = models.CharField(max_length=100)
sku_starts_with = models.CharField(max_length=100
Теперь я хочу получить все правила с именем Product 1
и соответствовать sku sku-b-292
class CreateAndAssignRuleQuerySet(QuerySet):
def filter_by_name_and_sku(self, name, sku):
# We're looking which of the rules have a matching name, and where the rule have a string which is the string of the sku provided.
rules = self.filter(name_equals=name)
approved_ids = []
for rule in rules:
# We're looping through the rules to find out which of them has the beginnings of the sku.
# a sku_starts_with field would contains value eg: 'sku-a' where as the search string would be the full sku 'sku-a-111'. We want to match 'sku-a-111' but not 'sku-b-222'.
if sku.startswith(rule.sku_starts_with):
approved.append(rule.id)
return self.filter(id__in=approved_ids)
Хотя вышеописанное работает, это вряд ли эффективно, особенно когда количество правил начинает сильно расти.
Как я могу решить эту проблему с помощью набора запросов? Фильтрация по __startswith
не помогает, как и в обратном случае.
Фильтр с:
from django.db.models import F, Value
class CreateAndAssignRuleQuerySet(QuerySet):
def filter_by_name_and_sku(self, name, sku):
return self.alias(
sku=Value(sku)
).filter(
name_equals=name,
sku__startswith=F('sku_starts_with')
)
Здесь мы вводим sku
в кверисет, а затем используем его для работы с __startswith
поиском [Django-doc].