CKEditor富文本编辑器&数据库表设计--SPU&SKU

  • SPU = Standard Product Unit (标准产品单位)

    SPU是商品信息聚合的最小单位,是一组可服用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

    通俗的讲,属性值、特性相同的商品就可以称为一个SPU。

    例如:

    iPhone X 就是一个SPU,与商家、颜色、款式、规格、套餐等都无关。

  • SKU = Stock Keeping Unit (库存量单位)

    SKU即库存进出计量的单位,可以是以件、盒、托盘等为单位,是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。在服装、鞋类商品中使用最多最普遍。

    例如:

    iPhone X 全网通黑色256G 就是一个SKU,表示了具体的规格、颜色等信息。

表结构

商品数据表结构

首页广告数据表结构

数据库模型类

终端使用命令:python manage.py startapp goods 创建商品应用goods,商品数据模型类

from django.db import models

from meiduo_mall.utils.models import BaseModel

# Create your models here.


class GoodsCategory(BaseModel):
    """
    商品类别
    """
    name = models.CharField(max_length=10, verbose_name='名称')
    parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父类别')

    class Meta:
        db_table = 'tb_goods_category'
        verbose_name = '商品类别'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class GoodsChannel(BaseModel):
    """
    商品频道
    """
    group_id = models.IntegerField(verbose_name='组号')
    category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='顶级商品类别')
    url = models.CharField(max_length=50, verbose_name='频道页面链接')
    sequence = models.IntegerField(verbose_name='组内顺序')

    class Meta:
        db_table = 'tb_goods_channel'
        verbose_name = '商品频道'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.category.name


class Brand(BaseModel):
    """
    品牌
    """
    name = models.CharField(max_length=20, verbose_name='名称')
    logo = models.ImageField(verbose_name='Logo图片')
    first_letter = models.CharField(max_length=1, verbose_name='品牌首字母')

    class Meta:
        db_table = 'tb_brand'
        verbose_name = '品牌'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Goods(BaseModel):
    """
    商品SPU
    """
    name = models.CharField(max_length=50, verbose_name='名称')
    brand = models.ForeignKey(Brand, on_delete=models.PROTECT, verbose_name='品牌')
    category1 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat1_goods', verbose_name='一级类别')
    category2 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat2_goods', verbose_name='二级类别')
    category3 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat3_goods', verbose_name='三级类别')
    sales = models.IntegerField(default=0, verbose_name='销量')
    comments = models.IntegerField(default=0, verbose_name='评价数')

    class Meta:
        db_table = 'tb_goods'
        verbose_name = '商品'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class GoodsSpecification(BaseModel):
    """
    商品规格
    """
    goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
    name = models.CharField(max_length=20, verbose_name='规格名称')

    class Meta:
        db_table = 'tb_goods_specification'
        verbose_name = '商品规格'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s: %s' % (self.goods.name, self.name)


class SpecificationOption(BaseModel):
    """
    规格选项
    """
    spec = models.ForeignKey(GoodsSpecification, on_delete=models.CASCADE, verbose_name='规格')
    value = models.CharField(max_length=20, verbose_name='选项值')

    class Meta:
        db_table = 'tb_specification_option'
        verbose_name = '规格选项'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s - %s' % (self.spec, self.value)


class SKU(BaseModel):
    """
    商品SKU
    """
    name = models.CharField(max_length=50, verbose_name='名称')
    caption = models.CharField(max_length=100, verbose_name='副标题')
    goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
    category = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, verbose_name='从属类别')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')
    cost_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='进价')
    market_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='市场价')
    stock = models.IntegerField(default=0, verbose_name='库存')
    sales = models.IntegerField(default=0, verbose_name='销量')
    comments = models.IntegerField(default=0, verbose_name='评价数')
    is_launched = models.BooleanField(default=True, verbose_name='是否上架销售')
    default_image_url = models.CharField(max_length=200, default='', null=True, blank=True, verbose_name='默认图片')

    class Meta:
        db_table = 'tb_sku'
        verbose_name = '商品SKU'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s: %s' % (self.id, self.name)


class SKUImage(BaseModel):
    """
    SKU图片
    """
    sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')
    image = models.ImageField(verbose_name='图片')

    class Meta:
        db_table = 'tb_sku_image'
        verbose_name = 'SKU图片'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s %s' % (self.sku.name, self.id)


class SKUSpecification(BaseModel):
    """
    SKU具体规格
    """
    sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')
    spec = models.ForeignKey(GoodsSpecification, on_delete=models.PROTECT, verbose_name='规格名称')
    option = models.ForeignKey(SpecificationOption, on_delete=models.PROTECT, verbose_name='规格值')

    class Meta:
        db_table = 'tb_sku_specification'
        verbose_name = 'SKU规格'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s: %s - %s' % (self.sku, self.spec.name, self.option.value)

终端命令:python manage.py startapp contents 创建广告内容应用contents,广告数据模型类

from django.db import models

from meiduo_mall.utils.models import BaseModel
# Create your models here.


class ContentCategory(BaseModel):
    """
    广告内容类别
    """
    name = models.CharField(max_length=50, verbose_name='名称')
    key = models.CharField(max_length=50, verbose_name='类别键名')

    class Meta:
        db_table = 'tb_content_category'
        verbose_name = '广告内容类别'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Content(BaseModel):
    """
    广告内容
    """
    category = models.ForeignKey(ContentCategory, on_delete=models.PROTECT, verbose_name='类别')
    title = models.CharField(max_length=100, verbose_name='标题')
    url = models.CharField(max_length=300, verbose_name='内容链接')
    image = models.ImageField(null=True, blank=True, verbose_name='图片')
    text = models.TextField(null=True, blank=True, verbose_name='内容')
    sequence = models.IntegerField(verbose_name='排序')
    status = models.BooleanField(default=True, verbose_name='是否展示')

    class Meta:
        db_table = 'tb_content'
        verbose_name = '广告内容'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.category.name + ': ' + self.title

settings.py配置文件中,添加安装应用:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'contents.apps.ContentsConfig',#主页广告内容
    'goods.apps.GoodsConfig',#商品信息

]

终端使用迁移命令:python manage.py makemigrations

         python manage.py migrate

CKEditor富文本编辑器

在运营后台,运营人员需要录入商品并编辑商品的详情信息,而商品的详情信息不是普通的文本,可以是包含了HTML语法格式的字符串。为了快速简单的让用户能够在页面中编辑带格式的文本,我们引入富文本编辑器。富文本即具备丰富样式格式的文本。

我们使用功能强大的CKEditor富文本编辑器。

1. 安装

pip install django-ckeditor

2. settings.py文件中添加应用

INSTALLED_APPS = [
    ........
    'ckeditor',  # 富文本编辑器
    'ckeditor_uploader',  # 富文本编辑器上传图片模块
    ........
]

3.settings.py文件中添加CKEditor设置

# 富文本编辑器ckeditor配置
CKEDITOR_CONFIGS = {
    'default': {
        'toolbar': 'full',  # 工具条功能
        'height': 300,  # 编辑器高度
        # 'width': 300,  # 编辑器宽
    },
}
CKEDITOR_UPLOAD_PATH = ''  # 上传图片保存路径,使用了FastDFS,所以此处设为''

4. 添加ckeditor路由

在总路由urls.py中添加ckeditor路由信息

urlpatterns = [
   .........
    # CKEditor
    url(r'^ckeditor/', include('ckeditor_uploader.urls')),
]

5. 为模型类添加字段

ckeditor提供了两种类型的Django模型类字段

  • ckeditor.fields.RichTextField 不支持上传文件的富文本字段
  • ckeditor_uploader.fields.RichTextUploadingField 支持上传文件的富文本字段

在商品模型类(SPU)中,要保存商品的详细介绍、包装信息、售后服务,这三个字段需要作为富文本字段

from ckeditor.fields import RichTextField
from ckeditor_uploader.fields import RichTextUploadingField


class Goods(BaseModel):
    """
    商品SPU
    """
    ...
    desc_detail = RichTextUploadingField(default='', verbose_name='详细介绍')
    desc_pack = RichTextField(default='', verbose_name='包装信息')
    desc_service = RichTextUploadingField(default='', verbose_name='售后服务')

终端使用迁移命令:python manage.py makemigrations

         python manage.py migrate

6. 修改Bug

我们将通过Django上传的图片保存到了FastDFS中,而保存在FastDFS中的文件名没有后缀名,ckeditor在处理上传后的文件名按照有后缀名来处理,所以会出现bug错误,

修正方法

找到虚拟环境目录中的ckeditor_uploader/views.py文件,如

~/.virtualenvs/meiduo/lib/python3.5/site-packages/ckeditor_uploader/views.py

将第95行代码修改如下:

 
 

猜你喜欢

转载自www.cnblogs.com/cl-python/p/9268168.html