Files
ai_web/backend/apps/products/models.py
2026-01-29 13:18:59 +08:00

167 lines
5.5 KiB
Python

"""
Product models for categories, websites, products and prices.
"""
from django.db import models
from django.conf import settings
class Category(models.Model):
"""Product categories for navigation."""
id = models.AutoField(primary_key=True)
name = models.CharField('分类名称', max_length=100)
slug = models.CharField('Slug', max_length=100, unique=True)
description = models.TextField('描述', blank=True, null=True)
icon = models.CharField('图标', max_length=100, blank=True, null=True)
parent = models.ForeignKey(
'self',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='children',
verbose_name='父分类'
)
sort_order = models.IntegerField('排序', default=0)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
class Meta:
db_table = 'categories'
verbose_name = '分类'
verbose_name_plural = '分类'
ordering = ['sort_order', 'id']
indexes = [
models.Index(fields=["parent", "sort_order"]),
]
def __str__(self):
return self.name
class Website(models.Model):
"""External shopping/card websites."""
id = models.AutoField(primary_key=True)
name = models.CharField('网站名称', max_length=200)
url = models.CharField('网址', max_length=500)
logo = models.TextField('Logo', blank=True, null=True)
description = models.TextField('描述', blank=True, null=True)
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
related_name='websites',
verbose_name='分类'
)
rating = models.DecimalField('评分', max_digits=2, decimal_places=1, default=0)
is_verified = models.BooleanField('是否认证', default=False)
sort_order = models.IntegerField('排序', default=0)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
db_table = 'websites'
verbose_name = '网站'
verbose_name_plural = '网站'
ordering = ['sort_order', 'id']
indexes = [
models.Index(fields=["category", "is_verified"]),
]
def __str__(self):
return self.name
class Product(models.Model):
"""Products for price comparison."""
class Status(models.TextChoices):
PENDING = 'pending', '待审核'
APPROVED = 'approved', '已通过'
REJECTED = 'rejected', '已拒绝'
id = models.AutoField(primary_key=True)
name = models.CharField('商品名称', max_length=300)
description = models.TextField('描述', blank=True, null=True)
image = models.TextField('图片', blank=True, null=True)
images = models.JSONField('图片列表', default=list, blank=True)
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
related_name='products',
verbose_name='分类'
)
status = models.CharField(
'审核状态',
max_length=20,
choices=Status.choices,
default=Status.PENDING
)
submitted_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='submitted_products',
verbose_name='提交者'
)
reject_reason = models.TextField('拒绝原因', blank=True, null=True)
reviewed_at = models.DateTimeField('审核时间', blank=True, null=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
db_table = 'products'
verbose_name = '商品'
verbose_name_plural = '商品'
indexes = [
models.Index(fields=["category", "created_at"]),
models.Index(fields=["status", "created_at"]),
models.Index(fields=["submitted_by", "status"]),
]
def __str__(self):
return self.name
class ProductPrice(models.Model):
"""Product prices from different websites."""
id = models.AutoField(primary_key=True)
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name='prices',
verbose_name='商品'
)
website = models.ForeignKey(
Website,
on_delete=models.CASCADE,
related_name='product_prices',
verbose_name='网站'
)
price = models.DecimalField('价格', max_digits=10, decimal_places=2)
original_price = models.DecimalField(
'原价',
max_digits=10,
decimal_places=2,
blank=True,
null=True
)
currency = models.CharField('货币', max_length=10, default='CNY')
url = models.CharField('商品链接', max_length=500)
in_stock = models.BooleanField('是否有货', default=True)
last_checked = models.DateTimeField('最后检查时间', auto_now=True)
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
db_table = 'productPrices'
verbose_name = '商品价格'
verbose_name_plural = '商品价格'
unique_together = ['product', 'website']
indexes = [
models.Index(fields=["product", "website", "last_checked"]),
]
def __str__(self):
return f"{self.product.name} - {self.website.name}: {self.price}"