做一个Django项目(2.4、商品和首页广告模块并对接fastdfs用于保存文件)

  1. 创建子应用
    1. goods 商品模块
      python ../../manage.py startapp goods

       

    2. contents 首页广告模块
      python ../../manage.py startapp contents
  2. 模型类创建并迁移
    1. goods模型类
      from django.db import models
      
      from md.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)
      

       

    2. contents模型类
      from django.db import models
      
      from md.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
      
    3. 注册应用
      INSTALLED_APPS = [
          """"""
          'contents.apps.ContentsConfig', # 主页模块
          'goods.apps.GoodsConfig', # 商品模块
      ]
      

       

    4. 实现迁移
      python manage.py makemigrations
      python manage.py migrate

       

  3. 对接fastdfs
    1. 导入模块fdfs_client-py github地址
      """
      fdfs_client-py 使用源码安装直接从 github 下载 
      
      """
      
      pip install fdfs_client-py-master.zip
      pip install mutagen
      pip isntall requests

       

    2. 在utils下创建fastdfs目录(python package)然后添加client.conf配置文件
    3. 更改django配置
      # FastDFS配置信息
      FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'utils/fastdfs/client.conf')

       

    4. 更改client.conf配置
      # FastDFS客户端存放日志文件的目录
      base_path=/home/python/Downloads
      
      # tracker的ip和端口
      
      tracker_server=192.168.1.102:22122
  4. 自定义文件存储系统
    1. 在fastdfs创建file_storage.py 实现官方文档django自定义文件存储中文翻译
    2. 实现
      from django.core.files.storage import Storage
      from fdfs_client.client import Fdfs_client
      from django.conf import settings
      
      
      class FastDFSStorage(Storage):
          """自定义文件存储系统"""
      
          def __init__(self, client_conf=None, base_url=None):
              """初始化文件存储对象的构造方法"""
              # if client_conf == None:
              #     self.client_conf = settings.FDFS_CLIENT_CONF
      
              # 如果client_conf参数为None,就读取or后面的值
              self.client_conf = client_conf or settings.FDFS_CLIENT_CONF
              self.base_url = base_url or settings.FDFS_BASE_URL
      
          def _open(self, name, mode='rb'):
              """
              储存类用于打开文件:因为必须实现,但是此处是文件存储不需要打开文件,所以重写没用到,所以pass
              :param name: 要打开的文件的名字
              :param mode: 打开的模式,read bytes
              :return: None
              """
              pass
      
          def _save(self, name, content):
              """
              实现文件存储:在这个方法里面将文件转存到FastDFS服务器
              :param name: 要存储的文件的名字
              :param content: 要存储的文件对象,File类型的对象,将来使用content.read()读取对象中的文件二进制
              :return: file_id
              """
              # 创建对接fdfs的客户端对象
              # client = Fdfs_client('md/utils/fastdfs/client.conf')
              # client = Fdfs_client(settings.FDFS_CLIENT_CONF)
              client = Fdfs_client(self.client_conf)
      
              # 将文件转存到fdfs
              # ret = client.upload_by_filename('/Users/zhangjie/Desktop/01.jpeg')
              ret = client.upload_by_buffer(content.read())
      
              # 判断文件上传是否成功
              if ret.get('Status') != 'Upload successed.':
                  raise Exception('upload file failed')
      
              # 能够执行到这里说明上传成功
              file_id = ret.get('Remote file_id')
              # 在自定义了文件存储系统之后,我们只需要返回file_id即可
              # 将来文件存储系统会"自动的"将file_id存储到对应的ImageFiled字段中
              # file_id == 'group1/M00/00/00/wKhnhluSuYeAIc39AAC4j90Tziw56.jpeg'
              return file_id
      
          def exists(self, name):
              """
              判断文件是否存在,判断本地是否存储了该文件,如果存储了就不会再存储,如果没有存储就调用_save()
              :param name: 要判断的文件的名字
              :return: True(文件存在) / False(文件不存在)
              """
              return False
      
          def url(self, name):
              """
              返回文件的绝对路径的,下载图片时使用的
              :param name: 是要读取的文件的名字,name==file_id
              :return: 文件绝对路径 http://192.168.1.102:8888/group1/M00/00/00/wKhnhluTuniAezl6AAC4j90Tziw02.jpeg
              """
              # return 'http://192.168.1.102:8888/' +  name
              return self.base_url + name
      
      
              """
              {
               'Group name': 'group1',
               'Remote file_id': 'group1/M00/00/00/wKhnhluSuYeAIc39AAC4j90Tziw56.jpeg',
               'Status': 'Upload successed.',
               'Local file name': '****/Desktop/01.jpeg',
               'Uploaded size': '46.00KB',
               'Storage IP': '192.168.1.102'
               }
              """

       

    3.  添加配置
      # django文件存储
      DEFAULT_FILE_STORAGE = 'meiduo_mall.utils.fastdfs.file_storage.FastDFSStorage'
      
      # FastDFS配置信息
      FDFS_BASE_URL = 'http://192.168.1.102:8888/'
      FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'utils/fastdfs/client.conf')

       

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值