1

Тема: І ще один weirdo в django-oscar

В oscar використовується наступна модель бази даних для товарів:

Product(model)
    pass

ProductClass(model)
    pass

ProductAttribute(model)
    foreign_key to ProductClass
    product = foreign_key to product

ProductAttributeValue(model)
    attribute = foreign_key to ProductAttribute

І для покращення швидкодії все індексується в django-haystack.

Так виглядає цей індекс:

class ProductIndex(indexes.SearchIndex, indexes.Indexable):
    ... other fields here ...
    attributes = indexes.MultiValueField()
    attribute_codes = indexes.MultiValueField()
    attribute_values = indexes.MultiValueField()

А так ми запихаєм туди значення:

    def prepare_attributes(self, obj): # тут тільки назви атрибутів
        return [attribute.name for attribute in obj.attributes.all()]

    def prepare_attribute_codes(self, obj): # тут їхні коди
        return [attribute.code for attribute in obj.attributes.all()]

    def prepare_attribute_values(self, obj): #  !!!!!!!!!! А тут вже всі значення !!!!!!!!!!
        return [val.value for val in obj.attribute_values.all()]

І от тут саме криється проблема! Напр. в нас є 3 продукти з 2 атрибутами: висота і ширина.

1. Foo висота=100 ширина=200
2. Bar висота=200 ширина=100
3. Rab висота=150 ширина 120

І на сайті в мене є потреба зробити пошук товарів за висотою в проміжку від 100 до 120. Потрапити сюди має тільки товар 1 Foo. Але! Приблизно отак ми фільтруємо по індексу:

SearchQuerySet().filter(attribute_values__in=[100, 101, 102 ... 120]) 

Що в нас в результаті? В нас пошук віддасть товари 1 Foo, 2 Bar і 3 Rab !!!!!!!!!!!
Чому? Тому що, дані зберігаються в списку:

    def prepare_attribute_values(self, obj): #  !!!!!!!!!! А тут вже всі значення !!!!!!!!!!
        return [val.value for val in obj.attribute_values.all()]

# [100, 200] - результат для першого товару
# [200, 100] - результат для другого товару
# [150, 120] - результат для третього товару

Так, я додавав в запит:

SearchQuerySet().filter(attribute_codes='height', attribute_values__in=[100, 101, 102 ... 120]) 

Але воно ж не поможе! Оскільки, 'height' так само буде в списку від prepare_attribute_codes.

І я також пробував зберегти значення в словник:

    def prepare_attribute_values(self, obj):
        return {val.attribute.code: val.value for val in obj.attribute_values.all()}

Але це викликає помилку при оновленні індексу.

Хоча б зрозуміли про що я  :) ?

Баг в django-oscar?  Чи як можу обійти?

Навчаюсь вчитись, щоб навчатись.

2

Re: І ще один weirdo в django-oscar

зберегти значення в словник

може в кортеж з двох елементів або список ?

взагалі не зрозуміло - який толк з тих prepare_attribute_values, якщо не встановлене ніяке відношення з prepare_attribute_codes ?

Подякували: Q-bart1

3

Re: І ще один weirdo в django-oscar

ping написав:

зберегти значення в словник

може в кортеж з двох елементів або список ?

Так потім не можна буде фільтрувати по цьому. І по словнику, ні по кортежу. Я це даремно

ping написав:

взагалі не зрозуміло - який толк з тих prepare_attribute_values, якщо не встановлене ніяке відношення з prepare_attribute_codes ?

Так ото ж бо й. Я ось тільки що й зрозумів це. Це ж баг не в oscar), а в коді проекту) Код для індексу, не я писав, от і відразу подумав, що то так має бути (по оскарівськи).

Як порадите? Створити ще один індекс для AttributeValue моделі і там зберігати value і code. А в Індексі товару зберігати id'шки до values? Знову ж таки не ясно чи вийде фільтрувати по такому) Але спробую.

Навчаюсь вчитись, щоб навчатись.

4

Re: І ще один weirdo в django-oscar

так а може хай видає швидкий результат по prepare_attribute_values а далі результат  ще раз фільтрувати ?

5

Re: І ще один weirdo в django-oscar

Ой, а це не буде дуже бидлокодом? Там проект не надто звісно ж, але все таки)

+ я ж без запитів в базу не профільтрую нормально з цим індексом

Навчаюсь вчитись, щоб навчатись.

6

Re: І ще один weirdo в django-oscar

Q-bart написав:

Ой, а це не буде дуже бидлокодом? Там проект не надто звісно ж, але все таки)

+ я ж без запитів в базу не профільтрую нормально з цим індексом

мабуть буде )

але я ще з оскаром не стикався.
дивно що нема в пошуку нічого про це питання - воно ж не вперше виникло

7

Re: І ще один weirdo в django-oscar

угу.

Спробую я зробити ще один індекс, Може вийде)

Навчаюсь вчитись, щоб навчатись.