Saleor产品目录与促销引擎技术实现
Saleor作为高性能Headless电商平台,其产品目录系统采用高度模块化和可配置的设计理念,支持灵活的产品数据模型、多语言支持、强大的搜索索引和变体管理系统。促销引擎则提供了复杂的规则引擎、优惠券系统和礼品卡管理,支持多种折扣类型和精细化的促销策略。
灵活的产品数据模型设计
Saleor作为一款高性能的Headless电商平台,其产品数据模型设计充分体现了现代电商系统的灵活性和可扩展性。通过深入分析Saleor的代码架构,我们可以发现其产品模型采用了高度模块化和可配置的设计理念,能够满足各种复杂的电商业务需求。
核心实体关系模型
Saleor的产品数据模型基于几个核心实体构建,它们之间通过精心设计的关系相互连接:
产品类型系统的灵活性
Saleor的产品类型系统是其灵活性的核心所在。每个产品类型可以定义自己的属性集和行为特征:
| 产品类型配置项 | 说明 | 可选值 |
|---|---|---|
| kind | 产品类型种类 | NORMAL, GIFT_CARD |
| has_variants | 是否支持变体 | true/false |
| is_shipping_required | 是否需要配送 | true/false |
| is_digital | 是否为数字产品 | true/false |
# 产品类型定义示例
class ProductType(ModelWithMetadata):
name = models.CharField(max_length=250)
slug = models.SlugField(max_length=255, unique=True, allow_unicode=True)
kind = models.CharField(max_length=32, choices=ProductTypeKind.CHOICES)
has_variants = models.BooleanField(default=True)
is_shipping_required = models.BooleanField(default=True)
is_digital = models.BooleanField(default=False)
weight = MeasurementField(measurement=Weight, default=zero_weight)
tax_class = models.ForeignKey(TaxClass, on_delete=models.SET_NULL, null=True)
属性系统的强大扩展能力
Saleor的属性系统支持多种输入类型和数据类型,为产品数据的多样性提供了坚实基础:
属性系统支持的数据类型配置:
| 输入类型 | 数据类型 | 存储方式 | 应用场景 |
|---|---|---|---|
| DROPDOWN | 字符串 | AttributeValue.value | 颜色、尺寸等固定选项 |
| MULTISELECT | 字符串数组 | 多个AttributeValue | 标签、特性等多选场景 |
| FILE | 文件URL | AttributeValue.file_url | 产品说明书、证书等 |
| NUMERIC | 数值 | AttributeValue.numeric | 重量、长度等数值属性 |
| BOOLEAN | 布尔值 | AttributeValue.value | 是否支持、是否包含等 |
| DATE | 日期 | AttributeValue.value | 生产日期、有效期等 |
多语言和元数据支持
Saleor的产品模型内置了完善的多语言支持和元数据机制:
# 产品翻译模型
class ProductTranslation(SeoModelTranslationWithSlug):
product = models.ForeignKey(Product, related_name="translations", on_delete=models.CASCADE)
name = models.CharField(max_length=250, blank=True, null=True)
description = SanitizedJSONField(blank=True, null=True, sanitizer=clean_editor_js)
# 元数据支持
class Product(SeoModel, ModelWithMetadata, ModelWithExternalReference):
# 继承ModelWithMetadata获得元数据支持
# 继承ModelWithExternalReference获得外部引用支持
搜索和索引优化
为了支持高效的产品搜索,Saleor实现了强大的搜索向量机制:
class Product(SeoModel, ModelWithMetadata, ModelWithExternalReference):
search_document = models.TextField(blank=True, default="")
search_vector = SearchVectorField(blank=True, null=True)
search_index_dirty = models.BooleanField(default=False, db_index=True)
class Meta:
indexes = [
GinIndex(name="product_search_gin", fields=["search_document"]),
GinIndex(name="product_tsearch", fields=["search_vector"]),
GinIndex(name="product_gin", fields=["name", "slug"]),
]
搜索系统会自动索引以下内容:
- 产品名称和slug
- 产品描述文本
- 属性值内容
- 变体信息
- 分类和标签信息
变体系统的灵活性
产品变体系统支持复杂的库存管理和定价策略:
class ProductVariantChannelListing(models.Model):
variant = models.ForeignKey(ProductVariant, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, on_delete=models.CASCADE)
price = MoneyField(amount_field="price_amount", currency_field="currency")
cost_price = MoneyField(amount_field="cost_price_amount", currency_field="currency", null=True)
preorder_quantity_threshold = models.IntegerField(null=True)
prior_price_amount = models.DecimalField(max_digits=12, decimal_places=3, null=True)
变体系统支持的功能包括:
- 多渠道差异化定价
- 成本价格跟踪
- 预售数量阈值控制
- 原价记录(用于折扣显示)
- 库存跟踪和管理
分类系统的层次结构
Saleor使用MPTT(Modified Preorder Tree Traversal)模型实现高效的分类层次结构:
class Category(ModelWithMetadata, MPTTModel, SeoModel):
name = models.CharField(max_length=250)
slug = models.SlugField(max_length=255, unique=True, allow_unicode=True)
description = SanitizedJSONField(blank=True, null=True, sanitizer=clean_editor_js)
parent = models.ForeignKey("self", null=True, blank=True, related_name="children", on_delete=models.CASCADE)
background_image = models.ImageField(upload_to="category-backgrounds", blank=True, null=True)
这种设计支持:
- 无限层级的分类结构
- 高效的树形查询操作
- 分类特定的SEO优化
- 多语言分类名称和描述
- 分类背景图像支持
通过这种灵活而强大的数据模型设计,Saleor能够支持从简单商品到复杂配置产品的各种电商场景,为开发者提供了极大的灵活性和扩展能力。
变体管理与属性系统架构
Saleor作为一款高性能的Headless电商平台,其变体管理与属性系统采用了高度灵活和可扩展的设计架构。该系统支持复杂的商品变体管理,能够满足从简单颜色尺寸变化到高度定制化产品的各种电商场景需求。
核心数据模型设计
Saleor的变体管理系统基于三个核心实体构建:产品(Product)、产品变体(ProductVariant)和属性(Attribute)。这种设计允许商家为同一产品创建多个变体,每个变体可以拥有不同的属性组合。
产品变体模型 (ProductVariant)
class ProductVariant(SortableModel, ModelWithMetadata, ModelWithExternalReference):
sku = models.CharField(max_length=255, unique=True, null=True, blank=True)
name = models.CharField(max_length=255, blank=True)
product = models.ForeignKey(
Product, related_name="variants", on_delete=models.CASCADE
)
track_inventory = models.BooleanField(default=True)
weight = MeasurementField(
measurement=Weight,
unit_choices=WeightUnits.CHOICES,
blank=True,
null=True,
)
# 其他字段...
产品变体模型包含以下关键特性:
- SKU管理:支持唯一库存单位标识符
- 库存跟踪:可配置的库存管理功能
- 重量规格:支持不同计量单位的重量管理
- 元数据支持:可扩展的元数据存储
- 外部引用:支持外部系统集成
属性系统架构
属性系统采用高度模块化设计,支持多种输入类型和复杂的属性关系:
属性输入类型支持
Saleor支持丰富的属性输入类型,满足各种商品属性需求:
| 输入类型 | 描述 | 使用场景 |
|---|---|---|
| DROPDOWN | 下拉选择 | 颜色、尺寸等固定选项 |
| MULTISELECT | 多选 | 支持多选的特性 |
| FILE | 文件上传 | 定制化文件需求 |
| REFERENCE | 引用类型 | 关联其他商品或页面 |
| NUMERIC | 数值输入 | 重量、长度等数值属性 |
| RICH_TEXT | 富文本 | 详细描述内容 |
| SWATCH | 色板选择 | 颜色可视化选择 |
| BOOLEAN | 布尔值 | 是/否类型属性 |
变体属性分配机制
变体属性通过中间表进行管理,确保数据的完整性和查询性能:
class AssignedVariantAttributeValue(SortableModel):
value = models.ForeignKey("AttributeValue", on_delete=models.CASCADE)
assignment = models.ForeignKey("AssignedVariantAttribute", on_delete=models.CASCADE)
class AssignedVariantAttribute(BaseAssignedAttribute):
variant = models.ForeignKey(ProductVariant, related_name="attributes", on_delete=models.CASCADE)
assignment = models.ForeignKey("AttributeVariant", on_delete=models.CASCADE)
values = models.ManyToManyField(AttributeValue, through=AssignedVariantAttributeValue)
多语言支持
系统为属性和属性值提供完整的国际化支持:
class AttributeTranslation(Translation):
attribute = models.ForeignKey(Attribute, related_name="translations", on_delete=models.CASCADE)
name = models.CharField(max_length=255)
class AttributeValueTranslation(Translation):
attribute_value = models.ForeignKey(AttributeValue, related_name="translations", on_delete=models.CASCADE)
name = models.CharField(max_length=250)
rich_text = SanitizedJSONField(blank=True, null=True)
plain_text = models.TextField(blank=True, null=True)
搜索优化与性能
系统为变体和属性数据建立了高效的搜索索引:
class Meta:
indexes = [
GinIndex(
name="variant_gin",
fields=["name", "sku"],
opclasses=["gin_trgm_ops"] * 2,
),
GinIndex(
name="attribute_gin",
fields=["slug", "name", "type", "input_type", "entity_type", "unit"],
opclasses=["gin_trgm_ops"] * 6,
),
]
变体选择与过滤
系统支持基于属性的高级变体筛选功能:
批量操作支持
属性系统提供高效的批量操作方法,确保大规模数据处理的性能:
def bulk_get_or_create(self, objects_data):
# 批量获取或创建属性值
results = []
query = self._prepare_query_for_bulk_operation(objects_data)
for record in query.iterator(chunk_size=1000):
for index, obj in objects_enumerated:
if self._is_correct_record(record, obj):
results.append((index, record))
break
return results
扩展性与自定义
系统设计允许通过以下方式进行扩展:
- 自定义属性类型:支持创建新的输入类型
- 属性验证规则:可配置的值验证逻辑
- 外部系统集成:通过外部引用字段连接第三方系统
- 元数据扩展:利用元数据字段存储自定义信息
这种架构设计使得Saleor能够处理从简单零售商品到复杂B2B定制产品的各种电商场景,同时保持良好的性能和可维护性。
促销规则引擎与优惠券系统
Saleor的促销系统是一个高度灵活且功能强大的引擎,支持多种折扣类型、复杂的促销规则和精细化的优惠券管理。该系统采用模块化设计,将促销逻辑与业务逻辑分离,提供了可扩展的API接口和强大的规则引擎。
核心架构设计
Saleor的促销系统基于Django模型构建,采用多对多关系和继承设计来实现复杂的促销规则。系统主要包含以下几个核心组件:
优惠券系统实现
Saleor的优惠券系统支持多种折扣类型和应用场景,包括:
优惠券类型定义
class VoucherType:
SHIPPING = "shipping" # 运费折扣
ENTIRE_ORDER = "entire_order" # 整单折扣
SPECIFIC_PRODUCT = "specific_product" # 特定商品折扣
class DiscountValueType:
FIXED = "fixed" # 固定金额折扣
PERCENTAGE = "percentage" # 百分比折扣
优惠券验证机制
系统实现了严格的优惠券验证机制,确保折扣的正确应用:
def validate_voucher(
voucher: Voucher,
total: Money,
quantity: int,
customer_email: str,
channel: Channel,
customer: Optional[User] = None,
):
# 验证渠道分配
voucher.validate_min_spent(total, channel)
# 验证最小购买数量
voucher.validate_min_checkout_items_quantity(quantity)
# 验证客户限制
if voucher.apply_once_per_customer:
voucher.validate_once_per_customer(customer_email)
# 验证员工专属
voucher.validate_only_for_staff(customer)
多渠道定价支持
每个优惠券可以在不同渠道设置不同的折扣值和最低消费要求:
class VoucherChannelListing(models.Model):
voucher = models.ForeignKey(Voucher, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, on_delete=models.CASCADE)
discount_value = models.DecimalField(max_digits=12, decimal_places=3)
currency = models.CharField(max_length=3)
min_spent_amount = models.DecimalField(max_digits=12, decimal_places=3, null=True)
促销规则引擎
Saleor的促销规则引擎支持复杂的条件匹配和折扣计算:
规则谓词系统
促销规则使用JSON格式的谓词来定义匹配条件:
catalogue_predicate = {
"productPredicate": {
"ids": ["UHJvZHVjdDox", "UHJvZHVjdDoy"]
},
"categoryPredicate": {
"ids": ["Q2F0ZWdvcnk6MQ=="]
},
"collectionPredicate": {
"ids": ["Q29sbGVjdGlvbjox"]
},
"variantPredicate": {
"ids": ["UHJvZHVjdFZhcmlhbnQ6MQ=="]
}
}
折扣计算逻辑
系统支持多种折扣计算方式:
def get_discount(self, channel: Channel):
"""根据渠道返回适当的折扣金额"""
if self.discount_value_type == DiscountValueType.FIXED:
discount_amount = Money(
voucher_channel_listing.discount_value,
voucher_channel_listing.currency
)
return partial(fixed_discount, discount=discount_amount)
if self.discount_value_type == DiscountValueType.PERCENTAGE:
return partial(
percentage_discount,
percentage=voucher_channel_listing.discount_value,
rounding=ROUND_HALF_UP,
)
高级功能特性
礼品促销规则
系统支持礼品类型的促销,可以设置购买特定商品赠送礼品:
class RewardType:
SUBTOTAL_DISCOUNT = "subtotal_discount" # 小计折扣
GIFT = "gift" # 礼品奖励
def create_gift_discount(checkout_info, checkout_lines_info, gift_promotion_rule):
"""创建礼品折扣"""
best_gift = get_best_gift_reward(gift_promotion_rule, channel, country)
if best_gift:
add_gift_line_to_checkout(checkout_info.checkout, best_gift.variant)
多促销规则冲突解决
当多个促销规则同时适用时,系统采用最优折扣策略:
def get_best_promotion_discount(price, rules_info_for_variant, channel):
"""获取最佳促销折扣"""
available_discounts = []
for rule_id, discount in get_product_promotion_discounts(
rules_info=rules_info_for_variant, channel=channel
):
available_discounts.append((rule_id, discount))
# 选择折扣金额最大的规则
return max(available_discounts, key=lambda x: (price - x[1](price)).amount)
国际化支持
促销系统完全支持多语言,包括促销名称和规则描述的翻译:
class PromotionTranslation(models.Model):
promotion = models.ForeignKey(Promotion, on_delete=models.CASCADE)
language_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
class PromotionRuleTranslation(models.Model):
promotion_rule = models.ForeignKey(PromotionRule, on_delete=models.CASCADE)
language_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
性能优化策略
Saleor采用了多种性能优化策略来确保促销系统的高效运行:
预计算折扣价格
class ProductVariantChannelListing(models.Model):
price_amount = models.DecimalField(max_digits=12, decimal_places=3)
discounted_price_amount = models.DecimalField(max_digits=12, decimal_places=3)
currency = models.CharField(max_length=3)
# 促销规则关联
variantlistingpromotionrule = models.ManyToManyField(
PromotionRule, through='VariantChannelListingPromotionRule'
)
批量处理优化
系统使用批量操作来减少数据库查询:
def update_rule_variant_relation(promotion_rule, variants):
"""批量更新规则与变体的关系"""
with transaction.atomic():
# 清除旧关系
promotion_rule.variants.clear()
# 批量创建新关系
promotion_rule.variants.add(*variants)
mark_promotion_rules_as_dirty([promotion_rule])
错误处理与异常管理
系统定义了专门的异常类来处理促销相关的错误:
class NotApplicable(ValueError):
"""当折扣不适用于购物车时引发的异常"""
def __init__(self, msg, min_spent=None, min_checkout_items_quantity=None):
super().__init__(msg)
self.min_spent = min_spent
self.min_checkout_items_quantity = min_checkout_items_quantity
使用示例
创建优惠券
# 创建整单折扣优惠券
voucher = Voucher.objects.create(
type=VoucherType.ENTIRE_ORDER,
name="夏季大促销",
discount_value_type=DiscountValueType.PERCENTAGE,
usage_limit=100,
apply_once_per_customer=True
)
# 设置渠道特定折扣
VoucherChannelListing.objects.create(
voucher=voucher,
channel=channel_usd,
discount_value=Decimal('20.00'), # 20% 折扣
currency="USD",
min_spent=Money(50, "USD")
)
# 生成优惠码
VoucherCode.objects.create(code="SUMMER2024", voucher=voucher)
应用促销规则
# 创建目录促销
promotion = Promotion.objects.create(
name="买一送一活动",
type=PromotionType.CATALOGUE,
start_date=timezone.now(),
end_date=timezone.now() + timedelta(days=30)
)
# 定义促销规则
rule = PromotionRule.objects.create(
promotion=promotion,
catalogue_predicate={
"productPredicate": {"ids": [product1_global_id]}
},
reward_type=RewardType.SUBTOTAL_DISCOUNT,
reward_value_type=RewardValueType.PERCENTAGE,
reward_value=Decimal('50.00') # 50% 折扣
)
Saleor的促销规则引擎与优惠券系统提供了一个完整、灵活且高性能的解决方案,能够满足各种复杂的电商促销需求。通过其模块化设计和丰富的API接口,开发者可以轻松扩展和定制促销功能,同时确保系统的稳定性和性能。
礼品卡与会员积分管理
在现代电商平台中,礼品卡和会员积分系统是提升客户忠诚度和促进重复购买的重要工具。Saleor作为一个高性能的headless电商平台,提供了完整的礼品卡管理解决方案,通过灵活的API设计和强大的后端架构,为企业级电商应用提供了可靠的礼品卡和会员积分功能。
礼品卡核心数据模型
Saleor的礼品卡系统建立在精心设计的数据模型之上,通过Django ORM实现了完整的礼品卡生命周期管理:
class GiftCard(ModelWithMetadata):
code = models.CharField(
max_length=16, unique=True, validators=[MinLengthValidator(8)], db_index=True
)
is_active = models.BooleanField(default=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL)
used_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="gift_cards")
expiry_date = models.DateField(null=True, blank=True)
currency = models.CharField(max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH)
initial_balance_amount = models.DecimalField(
max_digits=settings.DEFAULT_MAX_DIGITS,
decimal_places=settings.DEFAULT_DECIMAL_PLACES,
)
current_balance_amount = models.DecimalField(
max_digits=settings.DEFAULT_MAX_DIGITS,
decimal_places=settings.DEFAULT_DECIMAL_PLACES,
)
该模型支持多币种、余额管理、有效期控制等企业级功能,并通过ModelWithMetadata基类支持扩展元数据存储。
礼品卡生命周期管理
Saleor实现了完整的礼品卡生命周期管理,从创建、激活、使用到过期处理:
会员积分与礼品卡集成
虽然Saleor核心主要专注于礼品卡功能,但其架构设计为会员积分系统提供了良好的扩展基础。通过礼品卡的事件系统和余额管理机制,可以轻松实现积分累计和兑换功能:
def assign_user_gift_cards(user):
"""将未分配用户的礼品卡分配给指定用户"""
gift_cards = GiftCard.objects.filter(
used_by__isnull=True,
is_active=True,
current_balance_amount__gt=0
)
for gift_card in gift_cards:
gift_card.used_by = user
gift_card.save()
搜索与查询优化
Saleor为礼品卡提供了强大的搜索功能,支持全文搜索和标签过滤:
class GiftCardQueryset(models.QuerySet):
def active(self, date):
return self.filter(
Q(expiry_date__isnull=True) | Q(expiry_date__gte=date),
is_active=True,
)
def search_gift_cards(qs, value):
"""根据代码、标签或用户信息搜索礼品卡"""
return qs.filter(
Q(code__icontains=value) |
Q(tags__name__icontains=value) |
Q(used_by_email__icontains=value) |
Q(created_by_email__icontains=value)
).distinct()
事件追踪与审计
完整的审计追踪是企业级礼品卡系统的关键特性:
class GiftCardEvent(models.Model):
date = models.DateTimeField(default=timezone.now, editable=False)
type = models.CharField(max_length=255, choices=GiftCardEvents.CHOICES)
parameters = JSONField(blank=True, default=dict, encoder=CustomJsonEncoder)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL)
app = models.ForeignKey(App, on_delete=models.SET_NULL)
order = models.ForeignKey("order.Order", null=True, on_delete=models.SET_NULL)
gift_card = models.ForeignKey(GiftCard, related_name="events", on_delete=models.CASCADE)
支持的事件类型包括发放、发送、激活、停用、余额重置、有效期更新等完整操作记录。
自动化任务管理
Saleor通过Celery定时任务实现了礼品卡管理的自动化:
| 任务名称 | 执行频率 | 功能描述 |
|---|---|---|
deactivate_expired_cards_task | 每日 | 自动停用过期的礼品卡 |
update_gift_cards_search_vector_task | 按需 | 更新礼品卡搜索索引 |
| 余额检查任务 | 实时 | 在订单处理时验证礼品卡余额 |
GraphQL API集成
礼品卡功能通过GraphQL API完整暴露,支持前端应用的灵活集成:
mutation {
giftCardCreate(input: {
code: "GIFT2024XYZ"
initialBalance: {amount: 100, currency: USD}
expiryDate: "2024-12-31"
tags: ["birthday", "premium"]
}) {
giftCard {
id
code
currentBalance { amount currency }
isActive
expiryDate
}
}
}
安全性与权限控制
Saleor实现了细粒度的礼品卡权限管理:
class GiftcardPermissions(Permissions):
MANAGE_GIFT_CARD = Permission("manage_gift_card", "Manage gift cards.")
支持基于角色的访问控制,确保只有授权用户才能执行敏感操作。
性能优化策略
针对大规模礼品卡系统的性能优化:
- 数据库索引优化:为代码、有效期、余额等关键字段建立索引
- 搜索性能:使用PostgreSQL的全文搜索和GIN索引
- 缓存策略:对频繁查询的礼品卡信息进行缓存
- 批量处理:支持批量操作减少数据库交互
通过上述技术实现,Saleor提供了一个企业级的礼品卡管理系统,既保证了功能的完整性,又确保了系统的性能和可扩展性。其模块化设计和API优先的架构使得礼品卡功能可以轻松集成到任何前端应用中,为现代电商平台提供了强大的客户忠诚度管理工具。
总结
Saleor通过其灵活的产品数据模型、强大的变体管理系统、复杂的促销规则引擎和完整的礼品卡解决方案,为企业级电商应用提供了全面的技术基础。其模块化设计、API优先架构和性能优化策略确保了系统的高效运行和可扩展性,能够满足从简单零售到复杂B2B定制等各种电商场景的需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



