我来为您详细介绍如何在Django中使用MinIO作为存储,并修改xadmin的文件上传部分。
1. 安装必要的依赖
bash
pip install django-storages boto3 minio
2. 配置Django设置
在settings.py
中添加以下配置:
python
# settings.py
INSTALLED_APPS = [
# ...
'storages',
]
# MinIO配置
MINIO_ACCESS_KEY = 'your-access-key'
MINIO_SECRET_KEY = 'your-secret-key'
MINIO_BUCKET_NAME = 'your-bucket-name'
MINIO_ENDPOINT = 'your-minio-server:9000' # MinIO服务器地址
MINIO_USE_HTTPS = False # 根据你的MinIO配置调整
MINIO_EXTERNAL_ENDPOINT = None # 可选,用于生成外部URL
# Django存储后端配置
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID = MINIO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY = MINIO_SECRET_KEY
AWS_STORAGE_BUCKET_NAME = MINIO_BUCKET_NAME
AWS_S3_ENDPOINT_URL = f'http://{MINIO_ENDPOINT}' # 或 https
AWS_S3_USE_SSL = MINIO_USE_HTTPS
AWS_S3_FILE_OVERWRITE = False # 同名文件不覆盖
AWS_DEFAULT_ACL = None # 根据需求设置ACL
AWS_QUERYSTRING_AUTH = True # URL是否需要认证
3. 自定义存储类(可选,用于更好的MinIO集成)
python
# storage_backends.py
from storages.backends.s3boto3 import S3Boto3Storage
from django.conf import settings
class MinioStorage(S3Boto3Storage):
def __init__(self, *args, **kwargs):
kwargs['bucket_name'] = settings.MINIO_BUCKET_NAME
kwargs['access_key'] = settings.MINIO_ACCESS_KEY
kwargs['secret_key'] = settings.MINIO_SECRET_KEY
kwargs['endpoint_url'] = f"http://{settings.MINIO_ENDPOINT}"
kwargs['use_ssl'] = settings.MINIO_USE_HTTPS
super().__init__(*args, **kwargs)
# 然后在settings.py中使用自定义存储类
# DEFAULT_FILE_STORAGE = 'your_app.storage_backends.MinioStorage'
4. 修改xadmin的文件上传
方法一:全局替换存储后端
由于xadmin使用Django的FileField,配置了DEFAULT_FILE_STORAGE
后,xadmin会自动使用MinIO。
方法二:自定义xadmin的FileWidget
python
# adminx.py
import xadmin
from xadmin.views import BaseAdminView
from django import forms
from django.db import models
class MinioFileInput(forms.ClearableFileInput):
"""自定义文件输入组件,显示MinIO文件信息"""
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
if value and hasattr(value, 'url'):
# 显示文件的MinIO URL
context['file_url'] = value.url
return context
class GlobalSettings(BaseAdminView):
# 全局设置,让xadmin使用自定义的文件widget
global_models_icon = {
# 你的模型图标配置
}
def get_media(self):
media = super().get_media()
media.add_css({'screen': [
# 自定义CSS
]})
return media
# 注册全局设置
xadmin.site.register(BaseAdminView, GlobalSettings)
方法三:为特定模型自定义表单
python
# adminx.py
import xadmin
from django import forms
from .models import YourModel
class YourModelForm(forms.ModelForm):
class Meta:
model = YourModel
fields = '__all__'
widgets = {
'file_field': MinioFileInput(), # 使用自定义的文件输入组件
}
class YourModelAdmin(object):
form = YourModelForm
list_display = ['name', 'file_field']
# 自定义文件上传的字段显示
def file_field_display(self, obj):
if obj.file_field:
return f'<a href="{obj.file_field.url}" target="_blank">下载文件</a>'
return '无文件'
file_field_display.short_description = '文件'
file_field_display.allow_tags = True
xadmin.site.register(YourModel, YourModelAdmin)
5. 完整的配置示例
python
# settings.py 完整配置
# MinIO配置
MINIO_ACCESS_KEY = 'minioadmin'
MINIO_SECRET_KEY = 'minioadmin'
MINIO_BUCKET_NAME = 'django-media'
MINIO_ENDPOINT = 'localhost:9000'
MINIO_USE_HTTPS = False
# AWS S3兼容配置(MinIO兼容S3 API)
AWS_ACCESS_KEY_ID = MINIO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY = MINIO_SECRET_KEY
AWS_STORAGE_BUCKET_NAME = MINIO_BUCKET_NAME
AWS_S3_ENDPOINT_URL = f'http://{MINIO_ENDPOINT}'
AWS_S3_USE_SSL = MINIO_USE_HTTPS
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = 'public-read' # 或者 'private'
AWS_QUERYSTRING_AUTH = False # 如果希望文件URL可以直接访问
AWS_S3_SIGNATURE_VERSION = 's3v4'
# 媒体文件配置
MEDIA_URL = f'{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
6. 创建MinIO桶的初始化脚本
python
# minio_init.py
from minio import Minio
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
def create_minio_bucket():
"""创建MinIO桶(如果不存在)"""
try:
client = Minio(
settings.MINIO_ENDPOINT,
access_key=settings.MINIO_ACCESS_KEY,
secret_key=settings.MINIO_SECRET_KEY,
secure=settings.MINIO_USE_HTTPS
)
if not client.bucket_exists(settings.MINIO_BUCKET_NAME):
client.make_bucket(settings.MINIO_BUCKET_NAME)
logger.info(f"MinIO桶 {settings.MINIO_BUCKET_NAME} 创建成功")
else:
logger.info(f"MinIO桶 {settings.MINIO_BUCKET_NAME} 已存在")
except Exception as e:
logger.error(f"MinIO桶创建失败: {e}")
# 在Django启动时运行
# 可以在AppConfig.ready()中调用
7. 验证配置
创建一个测试视图来验证配置:
python
# views.py
from django.http import JsonResponse
from django.core.files.storage import default_storage
def test_minio(request):
"""测试MinIO连接"""
try:
# 测试文件操作
test_content = b"Hello MinIO from Django"
file_name = "test.txt"
# 保存文件
default_storage.save(file_name, test_content)
# 检查文件是否存在
exists = default_storage.exists(file_name)
# 获取文件URL
file_url = default_storage.url(file_name)
return JsonResponse({
'status': 'success',
'file_exists': exists,
'file_url': file_url
})
except Exception as e:
return JsonResponse({
'status': 'error',
'message': str(e)
})
注意事项
- 权限配置:确保MinIO的访问策略正确设置
- CORS设置:如果前端需要直接上传到MinIO,需要配置CORS
- URL生成 :根据需求调整
AWS_QUERYSTRING_AUTH
设置 - 备份策略:制定MinIO数据的备份策略
这样配置后,xadmin的文件上传功能就会自动使用MinIO作为存储后端,所有通过FileField和ImageField上传的文件都会保存到MinIO中。