Features: 1) Add is_digital field to ProductAdmin for filtering and display; 2) Extend admin search fields to include slug for products; 3) Introduce slug field in readonly and form layout sections for products.
Fixes: 1) Add `# type: ignore` comments for ForeignKey fields to resolve type-checking warnings in models. Extra: 1) Refactor admin field formatting for better readability; 2) Add `# noinspection PyProtectedMember` annotation in `rebuild_slugs` management command; 3) Clean up spacing and alignment in various files.
This commit is contained in:
parent
30144c5b6a
commit
b15df3b72a
4 changed files with 44 additions and 13 deletions
|
|
@ -169,10 +169,20 @@ class StockInline(TabularInline):
|
||||||
|
|
||||||
@admin.register(Product)
|
@admin.register(Product)
|
||||||
class ProductAdmin(BasicModelAdmin, TabbedTranslationAdmin):
|
class ProductAdmin(BasicModelAdmin, TabbedTranslationAdmin):
|
||||||
list_display = ("name", "partnumber", "is_active", "category", "brand", "price", "rating", "modified")
|
list_display = (
|
||||||
|
"name",
|
||||||
|
"partnumber",
|
||||||
|
"is_active",
|
||||||
|
"category",
|
||||||
|
"brand",
|
||||||
|
"price",
|
||||||
|
"rating",
|
||||||
|
"modified",
|
||||||
|
)
|
||||||
|
|
||||||
list_filter = (
|
list_filter = (
|
||||||
"is_active",
|
"is_active",
|
||||||
|
"is_digital",
|
||||||
("tags", admin.RelatedOnlyFieldListFilter),
|
("tags", admin.RelatedOnlyFieldListFilter),
|
||||||
("stocks__vendor", admin.RelatedOnlyFieldListFilter),
|
("stocks__vendor", admin.RelatedOnlyFieldListFilter),
|
||||||
"created",
|
"created",
|
||||||
|
|
@ -185,9 +195,10 @@ class ProductAdmin(BasicModelAdmin, TabbedTranslationAdmin):
|
||||||
"brand__name",
|
"brand__name",
|
||||||
"category__name",
|
"category__name",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"slug",
|
||||||
)
|
)
|
||||||
|
|
||||||
readonly_fields = ("created", "modified", "uuid", "rating", "price")
|
readonly_fields = ("created", "modified", "uuid", "rating", "price", "slug")
|
||||||
autocomplete_fields = ("category", "brand", "tags")
|
autocomplete_fields = ("category", "brand", "tags")
|
||||||
|
|
||||||
def price(self, obj):
|
def price(self, obj):
|
||||||
|
|
@ -206,8 +217,10 @@ class ProductAdmin(BasicModelAdmin, TabbedTranslationAdmin):
|
||||||
{
|
{
|
||||||
"fields": (
|
"fields": (
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"slug",
|
||||||
"partnumber",
|
"partnumber",
|
||||||
"is_active",
|
"is_active",
|
||||||
|
"is_digital",
|
||||||
"name",
|
"name",
|
||||||
"category",
|
"category",
|
||||||
"brand",
|
"brand",
|
||||||
|
|
@ -270,7 +283,15 @@ class OrderProductInline(admin.TabularInline):
|
||||||
|
|
||||||
@admin.register(Order)
|
@admin.register(Order)
|
||||||
class OrderAdmin(BasicModelAdmin):
|
class OrderAdmin(BasicModelAdmin):
|
||||||
list_display = ("human_readable_id", "user", "is_business", "status", "total_price", "buy_time", "modified")
|
list_display = (
|
||||||
|
"human_readable_id",
|
||||||
|
"user",
|
||||||
|
"is_business",
|
||||||
|
"status",
|
||||||
|
"total_price",
|
||||||
|
"buy_time",
|
||||||
|
"modified",
|
||||||
|
)
|
||||||
list_filter = ("status", "buy_time", "modified", "created")
|
list_filter = ("status", "buy_time", "modified", "created")
|
||||||
search_fields = ("user__email", "status", "uuid", "human_readable_id")
|
search_fields = ("user__email", "status", "uuid", "human_readable_id")
|
||||||
inlines = [OrderProductInline]
|
inlines = [OrderProductInline]
|
||||||
|
|
@ -374,7 +395,14 @@ class ProductImageAdmin(BasicModelAdmin):
|
||||||
class AddressAdmin(GISModelAdmin):
|
class AddressAdmin(GISModelAdmin):
|
||||||
list_display = ("street", "city", "region", "country", "user")
|
list_display = ("street", "city", "region", "country", "user")
|
||||||
list_filter = ("country", "region")
|
list_filter = ("country", "region")
|
||||||
search_fields = ("raw_data", "street", "city", "postal_code", "user__email", "address_line")
|
search_fields = (
|
||||||
|
"raw_data",
|
||||||
|
"street",
|
||||||
|
"city",
|
||||||
|
"postal_code",
|
||||||
|
"user__email",
|
||||||
|
"address_line",
|
||||||
|
)
|
||||||
|
|
||||||
gis_widget_kwargs = {
|
gis_widget_kwargs = {
|
||||||
"attrs": {
|
"attrs": {
|
||||||
|
|
@ -394,7 +422,9 @@ class ConstanceAdmin(BaseConstanceAdmin):
|
||||||
self.admin_site.admin_view(self.changelist_view),
|
self.admin_site.admin_view(self.changelist_view),
|
||||||
name=f"{info}_changelist",
|
name=f"{info}_changelist",
|
||||||
),
|
),
|
||||||
path("", self.admin_site.admin_view(self.changelist_view), name=f"{info}_add"),
|
path(
|
||||||
|
"", self.admin_site.admin_view(self.changelist_view), name=f"{info}_add"
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ def process_query(query: str = "", request: Request | None = None):
|
||||||
obj_name = (
|
obj_name = (
|
||||||
getattr(hit, "name", None) or getattr(hit, "title", None) or "N/A"
|
getattr(hit, "name", None) or getattr(hit, "title", None) or "N/A"
|
||||||
)
|
)
|
||||||
|
obj_slug = ""
|
||||||
raw_slug = getattr(hit, "slug", None)
|
raw_slug = getattr(hit, "slug", None)
|
||||||
if raw_slug:
|
if raw_slug:
|
||||||
obj_slug = raw_slug
|
obj_slug = raw_slug
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from django.utils.crypto import get_random_string
|
||||||
from core.models import Brand, Category, Product
|
from core.models import Brand, Category, Product
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyProtectedMember
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Rebuild slug field for all slugified instances"
|
help = "Rebuild slug field for all slugified instances"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -300,14 +300,14 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel):
|
||||||
class Product(ExportModelOperationsMixin("product"), NiceModel):
|
class Product(ExportModelOperationsMixin("product"), NiceModel):
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
category: Category = ForeignKey(
|
category: Category = ForeignKey( # type: ignore
|
||||||
"core.Category",
|
"core.Category",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
help_text=_("category this product belongs to"),
|
help_text=_("category this product belongs to"),
|
||||||
verbose_name=_("category"),
|
verbose_name=_("category"),
|
||||||
related_name="products",
|
related_name="products",
|
||||||
)
|
)
|
||||||
brand: Brand = ForeignKey(
|
brand: Brand = ForeignKey( # type: ignore
|
||||||
"core.Brand",
|
"core.Brand",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
|
@ -454,14 +454,14 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel):
|
||||||
class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel):
|
class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel):
|
||||||
is_publicly_visible = True
|
is_publicly_visible = True
|
||||||
|
|
||||||
attribute: Attribute = ForeignKey(
|
attribute: Attribute = ForeignKey( # type: ignore
|
||||||
"core.Attribute",
|
"core.Attribute",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
related_name="values",
|
related_name="values",
|
||||||
help_text=_("attribute of this value"),
|
help_text=_("attribute of this value"),
|
||||||
verbose_name=_("attribute"),
|
verbose_name=_("attribute"),
|
||||||
)
|
)
|
||||||
product: Product = ForeignKey(
|
product: Product = ForeignKey( # type: ignore
|
||||||
"core.Product",
|
"core.Product",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=False,
|
blank=False,
|
||||||
|
|
@ -852,7 +852,7 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel):
|
||||||
class Order(ExportModelOperationsMixin("order"), NiceModel):
|
class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
is_publicly_visible = False
|
is_publicly_visible = False
|
||||||
|
|
||||||
billing_address: Address = ForeignKey(
|
billing_address: Address = ForeignKey( # type: ignore
|
||||||
"core.Address",
|
"core.Address",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
|
@ -861,7 +861,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
help_text=_("the billing address used for this order"),
|
help_text=_("the billing address used for this order"),
|
||||||
verbose_name=_("billing address"),
|
verbose_name=_("billing address"),
|
||||||
)
|
)
|
||||||
promo_code: PromoCode = ForeignKey(
|
promo_code: PromoCode = ForeignKey( # type: ignore
|
||||||
"core.PromoCode",
|
"core.PromoCode",
|
||||||
on_delete=PROTECT,
|
on_delete=PROTECT,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
|
@ -869,7 +869,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel):
|
||||||
help_text=_("optional promo code applied to this order"),
|
help_text=_("optional promo code applied to this order"),
|
||||||
verbose_name=_("applied promo code"),
|
verbose_name=_("applied promo code"),
|
||||||
)
|
)
|
||||||
shipping_address: Address = ForeignKey(
|
shipping_address: Address = ForeignKey( # type: ignore
|
||||||
"core.Address",
|
"core.Address",
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue