Features: 1) Optimize retrieval of filterable attributes by grouping attribute values and reducing query overhead;

Fixes: 1) Handle `user` lookup more robustly using `getattr`; 2) Prevent redundant list creation in distinct value processing;

Extra: 1) Use consistent cache key variable; 2) Improve code readability with `defaultdict` for grouping; 3) Minor cleanup and formatting enhancements; 4) Remove unnecessary attribute redefinitions.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-07-18 09:06:22 +03:00
parent 82a11dfc7e
commit 67c18fc8d2

View file

@ -75,42 +75,46 @@ class CategoryDetailSerializer(ModelSerializer):
return None
def get_filterable_attributes(self, obj: Category) -> list[dict]:
filterable_results = cache.get(f"{obj.uuid}_filterable_results", [])
cache_key = f"{obj.uuid}_filterable_results"
filterable_results = cache.get(cache_key)
if filterable_results:
return filterable_results
request: Request | None = self.context.get("request")
user: User | AnonymousUser | None = getattr(request, "user") # noqa: B009
request = self.context.get("request")
user = getattr(request, "user", AnonymousUser())
attrs_qs = obj.attributes.all() if user.has_perm("view_attribute") else obj.attributes.filter(is_active=True)
attributes = list(attrs_qs)
if user is None:
user = AnonymousUser()
attributes = obj.attributes.all() if user.has_perm("view_attribute") else obj.attributes.filter(is_active=True)
for attr in attributes:
distinct_vals = (
AttributeValue.objects.annotate(value_length=Length("value"))
.filter(attribute=attr, product__category=obj, value_length__lte=30)
.values_list("value", flat=True)
.distinct()
attr_ids = [a.id for a in attributes]
raw_vals = (
AttributeValue.objects.annotate(value_length=Length("value"))
.filter(
attribute_id__in=attr_ids,
product__category=obj,
value_length__lte=30,
)
.values_list("attribute_id", "value")
.distinct()
)
distinct_vals_list = list(distinct_vals)[0:128] if len(list(distinct_vals)) > 128 else list(distinct_vals)
grouped = defaultdict(list)
for attr_id, val in raw_vals:
grouped[attr_id].append(val)
filterable_results = []
for attr in attributes:
vals = grouped.get(attr.id, [])
slice_vals = vals[:128] if len(vals) > 128 else vals
filterable_results.append(
{
"attribute_name": attr.name,
"possible_values": distinct_vals_list,
"possible_values": slice_vals,
"value_type": attr.value_type,
}
)
if user is None:
user = AnonymousUser()
if not user.has_perm("view_attribute"):
cache.set(f"{obj.uuid}_filterable_results", filterable_results, 86400)
cache.set(cache_key, filterable_results, 86400)
return filterable_results