zoukankan      html  css  js  c++  java
  • 0007 Django工程配置(04 文件数据库fastDFS配置)

      fastDFS是由淘宝余庆开发的。开源,免费。主要用于大规模的文件存储。Django对文件的支持,默认是放在工程目录一起,如果文件量大,增加服务压力。所以,尽量把文件服务器分离开了,专门存储文件。

      本节主要介绍如何通过django的自定义存储,自动把文件存储到fastDFS上。

    01 安装客户端插件

      fastDFS客户端插件,网上代码基本上都是下载fdfs_client-py-master.zip,而fdfs_client-py-master.zip不能在线安装,必须单独下载文件,而且,有些文件还安装要报错。因此,我们采用py3Fdfs插件,在工程创建时已安装了。 

    02 下载fastDFS的client.conf配置文件。

      在fastDFS服务器上,下载client.conf文件,并保存在Configurations目录下。

    03 重写Storage类

      Storage主要功能是上传文件,重写该类,把文件自动上传到fastDFS服务器。

      有两点需要说明:

      前端把文件上传到django服务器,如果保存之后再上传到fastDFS服务器,会导致效率低下,而fastDFS提供了缓存文件上传。也就是说,当前端把文件传到Django服务器,直接就上传到fastDFS服务器,不需要再存为文件。但此时,fastDFS返回的文件名没有扩展名,如果浏览器访问,浏览器不认识的文件,不会自动打开,而是直接下载。所以,我们必须要告诉fastDFS返回文件的扩展名。如图片,txt等文件,直接浏览器就可以打开。同时,处理文件扩展名的时候,特别要注意文件本身中有多个点,而扩展名只是最后一个点后面的名字。

      另外,fdfs_client-py-master.zip和fastDFS函数名都相同,但使用方式不同,这段存储代码来自于网上,但已经过修改。能正常运行。

      在GeneralTools目录下创建文件FastDFSStorage.py文件,内容如下:

    from django.conf import settings
    from django.core.files.storage import Storage
    from django.utils.deconstruct import deconstructible
    from fdfs_client.client import Fdfs_client, get_tracker_conf
    import os
    
    
    @deconstructible
    class FastDFSStorage(Storage):
        def __init__(self, base_url=None, client_conf=None):
            """
            初始化
            :param base_url: 用于构造图片完整路径使用,图片服务器的域名
            :param client_conf: FastDFS客户端配置文件的路径
            """
            if base_url is None:
                base_url = settings.FDFS_URL
            self.base_url = base_url
            if client_conf is None:
                client_conf = settings.FDFS_CLIENT_CONF
            self.client_conf = client_conf
            self.tracker_obj = get_tracker_conf(self.client_conf)
    
        def _open(self, name, mode='rb'):
            """
            用不到打开文件,所以省略
            """
            pass
    
        def _save(self, name, content):
            """
            在FastDFS中保存文件
            :param name: 传入的文件名
            :param content: 文件内容
            :return: 保存到数据库中的FastDFS的文件名
            """
            client = Fdfs_client(self.tracker_obj)
            # 告诉fastDFS服务器,返回文件的扩展名。
            ext_name = os.path.splitext(name)[1][1:]
            ret = client.upload_by_buffer(content.read(), ext_name)
            if ret.get("Status") != "Upload successed.":
                raise Exception("upload file failed")
            file_name = bytes(ret.get("Remote file_id")).decode()
            # 必须替换路径中的分隔符,否则,查询不到上传的文件。
            return file_name
    
        def url(self, name):
            """
            返回文件的完整URL路径
            :param name: 数据库中保存的文件名
            :return: 完整的URL
            """
            if name.startswith('http'):
                return name
            else:
                return self.base_url + name
    
        def exists(self, name):
            """
            判断文件是否存在,FastDFS可以自行解决文件的重名问题
            所以此处返回False,告诉Django上传的都是新文件
            :param name:  文件名
            :return: False
            """
            return False

    04 在settings.py中配置fastDFS

    FDFS_SERVER = '49.235.156.156'
    DEFAULT_FILE_STORAGE = 'GeneralTools.FastDFSStorage.FastDFSStorage'
    # 自定义两个变量,分别表示client.conf文件的路径和fdfs的url
    FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'Configurations', 'client.conf')
    FDFS_URL = 'http://' + FDFS_SERVER + ':80/'
    

    05 创建模型

      在该模型中定义一个图片字段。我们改一下之前在Organizations/models.py中创建的UserInfo模型。并执行数据迁移。

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    from GeneralTools.BaseModel import BaseModel
    
    
    class UserInfo(AbstractUser, BaseModel):
        openid = models.CharField(max_length=30, unique=True, verbose_name='微信openID', help_text='微信openID')
        mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号', help_text='手机号')
        # 默认的username是有唯一约束的,暂存入手机号。另增一个name字段存放姓名(微信昵称)
        name = models.CharField(max_length=30, null=True, blank=True, verbose_name='姓名', help_text='姓名')
        photo_url = models.ImageField(upload_to='user', null=True, blank=True, verbose_name='头像', help_text='头像')
    
        def __str__(self):
            return self.name
    
        class Meta:
            db_table = 'UserInfo'
            verbose_name_plural = '001  用户信息表'

    06 创建视图

      在Organizations/views下创建UserSave.py文件。

    from rest_framework import serializers
    import re
    from rest_framework_jwt.settings import api_settings
    from django_redis import get_redis_connection
    import logging
    from rest_framework.generics import CreateAPIView
    from Applications.Organizations.models import UserInfo
    
    # 获取在配置文件中定义的logger,用来记录日志
    logger = logging.getLogger('Organizations')
    
    
    class UserRegisterSer(serializers.ModelSerializer):
        """
        用户注册序列化器
        """
    
        class Meta:
            model = UserInfo
            fields = ('id', 'name', 'photo_url', 'password', 'mobile', 'openid')
    
        def create(self, validated_data):
            """
            用户注册,向数据库保存用户
            """
    
            # 移除数据库模型类中不存在的属性
            validated_data['username'] = validated_data['mobile']
            try:
                user = super().create(validated_data)
                # 调用django的认证系统加密密码
                user.set_password(validated_data['password'])
                user.save()
                return user
            except Exception as e:
                logger.error(str(e))
            return validated_data
    
    
    class UserSave(CreateAPIView):
        """
        用户注册第三步:创建用户
        POST /OrgsAndUsers/user/register/create/
        """
    
        serializer_class = UserRegisterSer
    

    07 运行工程

      在浏览器访问url,注:在接口文档中访问,不能选择文件。

    08 查询数据库,我们看到的内容如下:

      我们看到,第一条记录的路径分隔符没改,后面的都改好了。

      但数据库中,只保存了相对路径,那么,查询的时候,是否需要自己手动去拼接完整路径呢?

      先看查询结果:

    09 编写查询接口

      在Applications/Organizations/views/UserSave.py文件中,增加一个查询接口,并配置url,查看返回的数据。

    class UserSaveList(ListAPIView):
        queryset = UserInfo.objects.all()
        serializer_class = UserRegisterSer

    10 访问接口,看到以下效果

       我们看到,真是太神奇了,居然自动拼接成了完整路径。

  • 相关阅读:
    webpack的最简单应用,只使用js与css的打包
    数据统计表插件,highcharts插件的简单应用
    C#中的特性 (Attribute) 入门 (二)
    C#中的特性 (Attribute) 入门 (一)
    SQLServer存储过程入门
    C#拖拽操作
    C#剪切板
    .Net中的IO
    Android四大组件-服务
    AlertDialog对话框
  • 原文地址:https://www.cnblogs.com/dorian/p/12404447.html
Copyright © 2011-2022 走看看