Features: 1) Add Stock existence filters for has_price and has_stock annotations in queries; 2) Introduce personal_order_tail for improved ordering logic; 3) Support advanced filtering in DjangoFilterConnectionField with augmented filters and types.
Fixes: 1) Correct import order in multiple files; 2) Remove unnecessary migration file metadata changes. Extra: 1) Refactor ordering logic to streamline query annotations; 2) Improve code readability with explicit list annotations and consistent formatting adjustments.
This commit is contained in:
parent
0752221d22
commit
f646d5ab09
3 changed files with 39 additions and 49 deletions
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("blog", "0005_post_content_fa_ir_post_content_he_il_and_more"),
|
("blog", "0005_post_content_fa_ir_post_content_he_il_and_more"),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import uuid
|
||||||
from django.core.exceptions import BadRequest
|
from django.core.exceptions import BadRequest
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Avg,
|
Avg,
|
||||||
BooleanField,
|
|
||||||
Case,
|
Case,
|
||||||
Exists,
|
Exists,
|
||||||
FloatField,
|
FloatField,
|
||||||
|
IntegerField,
|
||||||
Max,
|
Max,
|
||||||
OuterRef,
|
OuterRef,
|
||||||
Prefetch,
|
Prefetch,
|
||||||
|
|
@ -33,7 +33,7 @@ from django_filters import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from core.elasticsearch import process_query
|
from core.elasticsearch import process_query
|
||||||
from core.models import Address, Brand, Category, Feedback, Order, Product, Wishlist
|
from core.models import Address, Brand, Category, Feedback, Order, Product, Stock, Wishlist
|
||||||
|
|
||||||
logger = logging.getLogger("django")
|
logger = logging.getLogger("django")
|
||||||
|
|
||||||
|
|
@ -276,41 +276,43 @@ class ProductFilter(FilterSet):
|
||||||
|
|
||||||
ordering_param = self.data.get("order_by", "")
|
ordering_param = self.data.get("order_by", "")
|
||||||
|
|
||||||
|
stock_with_price = Stock.objects.filter(product_uuid=OuterRef("pk"), price__gt=0)
|
||||||
|
stock_with_qty = Stock.objects.filter(product_uuid=OuterRef("pk"), quantity__gt=0)
|
||||||
|
|
||||||
qs = qs.annotate(
|
qs = qs.annotate(
|
||||||
has_stock=Case(
|
has_price=Exists(stock_with_price),
|
||||||
When(stocks__quantity__gt=0, then=Value(True)),
|
has_stock=Exists(stock_with_qty),
|
||||||
default=Value(False),
|
|
||||||
output_field=BooleanField(),
|
|
||||||
),
|
|
||||||
has_price=Case(
|
|
||||||
When(stocks__price__gt=0, then=Value(True)),
|
|
||||||
default=Value(False),
|
|
||||||
output_field=BooleanField(),
|
|
||||||
),
|
|
||||||
).annotate(
|
).annotate(
|
||||||
personal_orders_only=Case(
|
personal_order_tail=Case(
|
||||||
When(has_stock=False, has_price=False, then=Value(True)),
|
When(Q(has_price=False) | Q(has_stock=False), then=Value(1)),
|
||||||
default=Value(False),
|
default=Value(0),
|
||||||
output_field=BooleanField(),
|
output_field=IntegerField(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
requested = [part.strip() for part in ordering_param.split(",") if part.strip()] if ordering_param else []
|
requested = [part.strip() for part in ordering_param.split(",") if part.strip()] if ordering_param else []
|
||||||
mapped_requested = []
|
mapped_requested: list[str] = []
|
||||||
|
|
||||||
for part in requested:
|
for part in requested:
|
||||||
desc = part.startswith("-")
|
desc = part.startswith("-")
|
||||||
key = part.lstrip("-")
|
key = part.lstrip("-")
|
||||||
|
|
||||||
if key == "price":
|
if key == "price":
|
||||||
key = "price_order"
|
key = "price_order"
|
||||||
|
|
||||||
if key == "random":
|
if key == "random":
|
||||||
key = "?"
|
mapped_requested.append("?")
|
||||||
mapped_requested.append(key)
|
|
||||||
continue
|
continue
|
||||||
if key == "personal_orders_only":
|
|
||||||
|
if key in {"personal_orders_only", "personal_order_only", "personal_order_tail"}:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mapped_requested.append(f"-{key}" if desc else key)
|
mapped_requested.append(f"-{key}" if desc else key)
|
||||||
|
|
||||||
final_ordering = mapped_requested + ["personal_orders_only"]
|
if "?" in mapped_requested:
|
||||||
|
final_ordering = ["personal_order_tail", "?"]
|
||||||
|
else:
|
||||||
|
final_ordering = mapped_requested + ["personal_order_tail"]
|
||||||
|
|
||||||
if final_ordering:
|
if final_ordering:
|
||||||
qs = qs.order_by(*final_ordering)
|
qs = qs.order_by(*final_ordering)
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db.models import Max, Case, When, Value, IntegerField, BooleanField
|
|
||||||
from django.utils import timezone
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.db.models import Case, Exists, IntegerField, OuterRef, Q, Value, When
|
||||||
|
from django.utils import timezone
|
||||||
from graphene import Field, List, ObjectType, Schema
|
from graphene import Field, List, ObjectType, Schema
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
|
|
||||||
from blog.filters import PostFilter
|
from blog.filters import PostFilter
|
||||||
from blog.graphene.object_types import PostType
|
from blog.graphene.object_types import PostType
|
||||||
from core.filters import (
|
from core.filters import (
|
||||||
|
AddressFilter,
|
||||||
BrandFilter,
|
BrandFilter,
|
||||||
CategoryFilter,
|
CategoryFilter,
|
||||||
FeedbackFilter,
|
FeedbackFilter,
|
||||||
OrderFilter,
|
OrderFilter,
|
||||||
ProductFilter,
|
ProductFilter,
|
||||||
WishlistFilter,
|
WishlistFilter,
|
||||||
AddressFilter,
|
|
||||||
)
|
)
|
||||||
from core.graphene.mutations import (
|
from core.graphene.mutations import (
|
||||||
AddOrderProduct,
|
AddOrderProduct,
|
||||||
|
|
@ -44,6 +44,7 @@ from core.graphene.mutations import (
|
||||||
UpdateProduct,
|
UpdateProduct,
|
||||||
)
|
)
|
||||||
from core.graphene.object_types import (
|
from core.graphene.object_types import (
|
||||||
|
AddressType,
|
||||||
AttributeGroupType,
|
AttributeGroupType,
|
||||||
BrandType,
|
BrandType,
|
||||||
CategoryTagType,
|
CategoryTagType,
|
||||||
|
|
@ -61,9 +62,9 @@ from core.graphene.object_types import (
|
||||||
StockType,
|
StockType,
|
||||||
VendorType,
|
VendorType,
|
||||||
WishlistType,
|
WishlistType,
|
||||||
AddressType,
|
|
||||||
)
|
)
|
||||||
from core.models import (
|
from core.models import (
|
||||||
|
Address,
|
||||||
AttributeGroup,
|
AttributeGroup,
|
||||||
Brand,
|
Brand,
|
||||||
Category,
|
Category,
|
||||||
|
|
@ -79,7 +80,6 @@ from core.models import (
|
||||||
Stock,
|
Stock,
|
||||||
Vendor,
|
Vendor,
|
||||||
Wishlist,
|
Wishlist,
|
||||||
Address,
|
|
||||||
)
|
)
|
||||||
from core.utils import get_project_parameters
|
from core.utils import get_project_parameters
|
||||||
from core.utils.languages import get_flag_by_language
|
from core.utils.languages import get_flag_by_language
|
||||||
|
|
@ -163,35 +163,24 @@ class Query(ObjectType):
|
||||||
.prefetch_related("images", "stocks")
|
.prefetch_related("images", "stocks")
|
||||||
)
|
)
|
||||||
|
|
||||||
base_qs = (
|
stock_with_price = Stock.objects.filter(product_uuid=OuterRef("pk"), price__gt=0)
|
||||||
|
stock_with_qty = Stock.objects.filter(product_uuid=OuterRef("pk"), quantity__gt=0)
|
||||||
|
|
||||||
|
return (
|
||||||
base_qs.annotate(
|
base_qs.annotate(
|
||||||
has_stock=Max(
|
has_price=Exists(stock_with_price),
|
||||||
Case(
|
has_stock=Exists(stock_with_qty),
|
||||||
When(stocks__quantity__gt=0, then=Value(1)),
|
|
||||||
default=Value(0),
|
|
||||||
output_field=IntegerField(),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
has_price=Max(
|
|
||||||
Case(
|
|
||||||
When(stocks__price__gt=0, then=Value(1)),
|
|
||||||
default=Value(0),
|
|
||||||
output_field=IntegerField(),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.annotate(
|
.annotate(
|
||||||
personal_order_only=Case(
|
personal_order_tail=Case(
|
||||||
When(has_stock=0, has_price=1, then=Value(True)),
|
When(Q(has_price=False) | Q(has_stock=False), then=Value(1)),
|
||||||
default=Value(False),
|
default=Value(0),
|
||||||
output_field=BooleanField(),
|
output_field=IntegerField(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.order_by("personal_order_only")
|
.order_by("personal_order_tail")
|
||||||
)
|
)
|
||||||
|
|
||||||
return base_qs
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_orders(_parent, info, **kwargs):
|
def resolve_orders(_parent, info, **kwargs):
|
||||||
orders = Order.objects
|
orders = Order.objects
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue