编写自定义存储系统
通过定义一个自定义的储存类来实现。你需要遵循以下步骤:
1-你的自定义储存类必须是django.core.files.storage.Storage的子类:
2-Django必须能够不带任何参数来实例化你的储存类。意味着任何设置都应该从django.conf.settings中获取。
3-储存类必须实现 _open() 和 _save()实例方法。
打开文件的时候调用的---存储文件的时候调用的
4-存储类必须要实现 def exists(self, name):
判断文件是否已经在本地存储, 返回True表示文件已经存储在本地/django不会再去存储该文件
返回False, 告诉Django这是一个新的文件,请你存储。
只有返回False, django才会积极的存储文件到fdfs
5-存储类要实现 def url(self, name):
返回文件的全路径
该方法是提供给模型类中ImageField字段对应的属性调用的(file_id被存储到ImageField字段种中)
6-优化代码:
"http://192.168.219.128:8888/"不要写死
return "http://192.168.219.128:8888/" + name
修改后:return self.base_url + name
# 创建fdfs客户端,和tracker进行交互 meiduo_all/utils/fastdfs/client.conf 不要写死
client = Fdfs_client(‘meiduo_all/utils/fastdfs/client.conf ’)
修改后:
client = Fdfs_client(self.client_conf)
然后将__init__方法中进行初始化
7-在settings中完成配置:
# django文件存储--告诉django文件的存储位置修改为下面的默认值
DEFAULT_FILE_STORAGE = 'meiduo_all.utils.fastdfs.fdfs_storage.FastDFSStorage'
# FastDFS
FDFS_BASE_URL = 'http://192.168.219.128:8888/'
FDFS_CLIENT_CONF = os.path.join(BASE_DIR, 'utils/fastdfs/client.conf')
8-代码如下:
from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client
from django.conf import settings
class FdfsDFSStorage(Storage):
"""自定义文件存储系统:实现文件被转存到fdfs"""
def __init__(self, client_conf=None, base_url=None):
"""
构造方法
当在存储数据的时候,django会自动调用构造方法,但是不会传参进来,
"""
self.client_conf = client_conf or settings.FDFS_CLIENT_CONF
self.base_url = base_url or settings.FDFS_BASE_URL
def _open(self, name, mod='rb'):
"""
打开文件的时候调用的
因为此时,只需要进行文件的上传,不需要进行文件的下载,但是又必须要进行定义,
只能在需要用到的时候,再使用,在此之前只好pass
"""
pass
def _save(self, name, content):
"""
存储文件的时候调用的
:param name:要存储的文件的名字
:param content:要存储的文件的对象--File类型对象--需要调用read()读取出要上传的文件的内容
:return file_id
"""
# 创建fdfs客户端,和tracker进行交互 meiduo_all/utils/fastdfs/client.conf 不要写死
client = Fdfs_client(self.client_conf)
# 调用上传的方法: 根据文件的内容上传的
ret = client.upload_by_buffer(content.read())
# 判断上传是否成功
if ret.get('Status') != 'Upload successed.':
raise Exception("upload file failed")
# 返回file_id:模型类会自动的读取这个file_id, 存储到模型类中ImageField字段中
file_id = ret.get("Remote file_id")
return file_id
def exists(self, name):
"""
判断文件是否已经在本地存储, 返回True表示文件已经存储在本地/django不会再去存储该文件
返回False, 告诉Django这是一个新的文件,请你存储。
只有返回False, django才会积极的存储文件到fdfs
:param name: 要上传的文件的名字
:return:False
"""
return False
def url(self, name):
"""
返回文件的全路径
该方法是提供给模型类中ImageField字段对应的属性调用的(file_id被存储到ImageField字段种中)
:param name: 要返回全路径的文件的名字
:return: "http://192.168.219.128:8888/group1/M00/00/02/sdgfhehbgegrsgsd.jpg" 也就是name
"http://192.168.219.128:8888/"不要写死
"""
return self.base_url + name