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:
Egor Pavlovich Gorbunov 2025-04-30 16:31:54 +03:00
parent bbde0a4654
commit 3ec0991aa6
9 changed files with 58 additions and 4 deletions

View file

@ -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",

View file

@ -329,6 +329,7 @@ class ProductType(DjangoObjectType):
"brand",
"tags",
"name",
"slug",
"description",
"feedbacks",
"images",

View 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),
),
]

View file

@ -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:

View file

@ -306,6 +306,7 @@ class ProductDetailSerializer(ModelSerializer):
"feedbacks_count",
"quantity",
"tags",
"slug",
"images",
"attributes",
"rating",

View file

@ -168,6 +168,7 @@ class ProductSimpleSerializer(ModelSerializer):
"uuid",
"name",
"is_digital",
"slug",
"description",
"partnumber",
"brand",

View file

@ -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):

View file

@ -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

View 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),
),
]