Add slug field to Product and update related functionalities
Introduce a unique, auto-generated slug field to the Product model, populated from category, brand, and name. Update core filters, serializers, sitemaps, and GraphQL object types to support the new slug functionality. Also, enforce HTTP-only cookies for session, CSRF, and language for improved security.
This commit is contained in:
parent
bbde0a4654
commit
3ec0991aa6
9 changed files with 58 additions and 4 deletions
|
|
@ -34,12 +34,15 @@ class ProductFilter(FilterSet):
|
|||
brand = CharFilter(field_name="brand__name", lookup_expr="iexact", label="Brand")
|
||||
attributes = CharFilter(method="filter_attributes", label="Attributes")
|
||||
quantity = NumberFilter(field_name="stocks__quantity", lookup_expr="gt", label="Quantity")
|
||||
slug = CharFilter(field_name="slug", lookup_expr="exact", label="Slug")
|
||||
is_digital = BooleanFilter(field_name="is_digital", label="Is Digital")
|
||||
|
||||
order_by = OrderingFilter(
|
||||
fields=(
|
||||
("uuid", "uuid"),
|
||||
("rating", "rating"),
|
||||
("name", "name"),
|
||||
("slug", "slug"),
|
||||
("created", "created"),
|
||||
("modified", "modified"),
|
||||
("stocks__price", "price"),
|
||||
|
|
@ -61,6 +64,7 @@ class ProductFilter(FilterSet):
|
|||
"is_digital",
|
||||
"is_active",
|
||||
"tags",
|
||||
"slug",
|
||||
"min_price",
|
||||
"max_price",
|
||||
"brand",
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ class ProductType(DjangoObjectType):
|
|||
"brand",
|
||||
"tags",
|
||||
"name",
|
||||
"slug",
|
||||
"description",
|
||||
"feedbacks",
|
||||
"images",
|
||||
|
|
|
|||
19
core/migrations/0013_product_slug.py
Normal file
19
core/migrations/0013_product_slug.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 5.1.8 on 2025-04-30 13:29
|
||||
|
||||
import django_extensions.db.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0012_alter_order_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='product',
|
||||
name='slug',
|
||||
field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, populate_from=('category.name', 'brand.name', 'name'), unique=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -33,6 +33,7 @@ from django.utils import timezone
|
|||
from django.utils.encoding import force_bytes
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_extensions.db.fields import AutoSlugField
|
||||
from mptt.fields import TreeForeignKey
|
||||
from mptt.models import MPTTModel
|
||||
|
||||
|
|
@ -300,7 +301,13 @@ class Product(NiceModel):
|
|||
blank=False,
|
||||
null=True,
|
||||
help_text=_("part number for this product"),
|
||||
verbose_name=_("part number")
|
||||
verbose_name=_("part number"),
|
||||
)
|
||||
slug = AutoSlugField(
|
||||
populate_from=("category.name", "brand.name", "name"),
|
||||
allow_unicode=True,
|
||||
unique=True,
|
||||
editable=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ class ProductDetailSerializer(ModelSerializer):
|
|||
"feedbacks_count",
|
||||
"quantity",
|
||||
"tags",
|
||||
"slug",
|
||||
"images",
|
||||
"attributes",
|
||||
"rating",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ class ProductSimpleSerializer(ModelSerializer):
|
|||
"uuid",
|
||||
"name",
|
||||
"is_digital",
|
||||
"slug",
|
||||
"description",
|
||||
"partnumber",
|
||||
"brand",
|
||||
|
|
|
|||
|
|
@ -16,14 +16,13 @@ class ProductSitemap(Sitemap):
|
|||
is_active=True,
|
||||
brand__is_active=True,
|
||||
category__is_active=True,
|
||||
).only("uuid", "name", "modified").order_by("-modified")
|
||||
).only("uuid", "name", "modified", "slug").order_by("-modified")
|
||||
|
||||
def lastmod(self, obj):
|
||||
return obj.modified
|
||||
|
||||
def location(self, obj):
|
||||
slug = slugify(obj.name)
|
||||
return f"/{LANGUAGE_CODE}/product/{obj.uuid}/{slug}"
|
||||
return f"/{LANGUAGE_CODE}/product/{obj.uuid}/{obj.slug}"
|
||||
|
||||
|
||||
class CategorySitemap(Sitemap):
|
||||
|
|
|
|||
|
|
@ -299,4 +299,8 @@ if getenv("SENTRY_DSN"):
|
|||
],
|
||||
)
|
||||
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
CSRF_COOKIE_HTTPONLY = True
|
||||
LANGUAGE_COOKIE_HTTPONLY = True
|
||||
|
||||
DATA_UPLOAD_MAX_NUMBER_FIELDS = 8888
|
||||
|
|
|
|||
18
payments/migrations/0004_alter_transaction_payment_method.py
Normal file
18
payments/migrations/0004_alter_transaction_payment_method.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.1.8 on 2025-04-30 13:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('payments', '0003_alter_transaction_balance'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='transaction',
|
||||
name='payment_method',
|
||||
field=models.CharField(blank=True, max_length=20, null=True),
|
||||
),
|
||||
]
|
||||
Loading…
Reference in a new issue