# Django TOS Uploader
一个用于 Django 的火山引擎 TOS(Tinder Object Storage)文件上传组件。
## 功能特性
- 🚀 支持大文件分片上传
- 🔒 使用 STS 临时凭证,安全可靠
- 🎨 现代化 UI 设计,支持响应式布局
- 📱 支持拖拽上传和点击选择
- 🔍 实时预览(图片、视频等)
- 📊 上传进度显示
- 🛡️ 支持只读模式
- 🎯 动态上传路径配置
- ⚡ 懒加载预览,节省资源
## 安装
```bash
pip install django-tos-uploader
```
## 快速开始
### 依赖
```bash
pip install volcengine
```
### 1. 添加到 INSTALLED_APPS
```python
INSTALLED_APPS = [
# ... 其他应用
'tos_uploader',
]
```
### 2. 配置设置
```python
# settings.py
# 火山引擎配置
VOLCENGINE_ACCESS_KEY = 'your-access-key'
VOLCENGINE_SECRET_KEY = 'your-secret-key'
VOLCENGINE_REGION = 'cn-beijing' # 或其他区域
VOLCENGINE_ENDPOINT = 'tos-cn-beijing.volces.com'
VOLCENGINE_BUCKET = 'your-bucket-name'
VOLCENGINE_ACCOUNT_ID = 'your-account-id'
VOLCENGINE_STS_ROLE_NAME = 'your-sts-role-name'
```
### 3. 实现 STS Token 视图
```python
# views.py
from django.conf import settings
from volcengine.sts.StsService import StsService
from rest_framework import serializers
class StsTokenSerializer(serializers.Serializer):
access_key = serializers.CharField(help_text="临时访问密钥ID")
secret_key = serializers.CharField(help_text="临时访问密钥")
security_token = serializers.CharField(help_text="安全令牌")
expiration = serializers.DateTimeField(help_text="凭证过期时间")
endpoint = serializers.CharField(help_text="Endpoint")
bucket = serializers.CharField(help_text="Bucket")
region = serializers.CharField(help_text="Region")
class GetStsTokenAPIView(APIView):
# permission_classes = [IsAuthenticated]
@extend_schema(
tags=["服务"],
summary="获取火山引擎STS临时访问凭证",
responses={
status.HTTP_200_OK: StsTokenSerializer,
status.HTTP_500_INTERNAL_SERVER_ERROR: OpenApiTypes.OBJECT,
},
)
def get(self, request, *args, **kwargs):
try:
# 初始化 STS 服务
sts_service = StsService()
sts_service.set_ak(settings.VOLCENGINE_ACCESS_KEY)
sts_service.set_sk(settings.VOLCENGINE_SECRET_KEY)
# 获取 STS 临时凭证
params = {
"DurationSeconds": 3600, # 1小时有效期
"RoleTrn": f"trn:iam::{settings.VOLCENGINE_ACCOUNT_ID}:role/{settings.VOLCENGINE_STS_ROLE_NAME}",
"RoleSessionName": f"renlib_user_{request.user.id}",
}
resp = sts_service.assume_role(params)
credentials = resp["Result"]["Credentials"]
data = {
"access_key": credentials["AccessKeyId"],
"secret_key": credentials["SecretAccessKey"],
"security_token": credentials["SessionToken"],
"expiration": credentials["ExpiredTime"],
"endpoint": settings.VOLCENGINE_ENDPOINT,
"bucket": settings.VOLCENGINE_BUCKET,
"region": settings.VOLCENGINE_REGION,
}
serializer = StsTokenSerializer(data=data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
except Exception as e:
return Response(
{"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
```
### 4. 配置 URL 路由
```python
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<your url>/', views.GetStsTokenAPIView.as_view(), name='get_sts_token'),
# ... 其他URL
]
```
### 5. 在模型中使用
```python
from tos_uploader.fields import TOSFileField
from django.db import models
class MyModel(models.Model):
# 其他字段...
tos_file = TOSFileField(
upload_path="my-uploads/",
get_sts_token_url=reverse_lazy('get_sts_token'), # 替换为你的视图名
file_types=["image/*", "video/*"], # 可选,文件类型限制
readonly=False, # 可选,是否只读
)
```
Raw data
{
"_id": null,
"home_page": "https://github.com/ren000thomas/django-tos-uploader",
"name": "django-tos-uploader",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "django, volcengine, tos, upload, widget, file-upload",
"author": "Your Name",
"author_email": "Ren Thomas <ren000thomas@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/84/19/a548254502a86ffcf86bc34b9410e2f216645c3fe6fe1563d949e73805a5/django_tos_uploader-1.1.1.tar.gz",
"platform": null,
"description": "# Django TOS Uploader\r\n\r\n\u4e00\u4e2a\u7528\u4e8e Django \u7684\u706b\u5c71\u5f15\u64ce TOS\uff08Tinder Object Storage\uff09\u6587\u4ef6\u4e0a\u4f20\u7ec4\u4ef6\u3002\r\n\r\n## \u529f\u80fd\u7279\u6027\r\n\r\n- \ud83d\ude80 \u652f\u6301\u5927\u6587\u4ef6\u5206\u7247\u4e0a\u4f20\r\n- \ud83d\udd12 \u4f7f\u7528 STS \u4e34\u65f6\u51ed\u8bc1\uff0c\u5b89\u5168\u53ef\u9760\r\n- \ud83c\udfa8 \u73b0\u4ee3\u5316 UI \u8bbe\u8ba1\uff0c\u652f\u6301\u54cd\u5e94\u5f0f\u5e03\u5c40\r\n- \ud83d\udcf1 \u652f\u6301\u62d6\u62fd\u4e0a\u4f20\u548c\u70b9\u51fb\u9009\u62e9\r\n- \ud83d\udd0d \u5b9e\u65f6\u9884\u89c8\uff08\u56fe\u7247\u3001\u89c6\u9891\u7b49\uff09\r\n- \ud83d\udcca \u4e0a\u4f20\u8fdb\u5ea6\u663e\u793a\r\n- \ud83d\udee1\ufe0f \u652f\u6301\u53ea\u8bfb\u6a21\u5f0f\r\n- \ud83c\udfaf \u52a8\u6001\u4e0a\u4f20\u8def\u5f84\u914d\u7f6e\r\n- \u26a1 \u61d2\u52a0\u8f7d\u9884\u89c8\uff0c\u8282\u7701\u8d44\u6e90\r\n\r\n## \u5b89\u88c5\r\n\r\n```bash\r\npip install django-tos-uploader\r\n```\r\n\r\n## \u5feb\u901f\u5f00\u59cb\r\n\r\n### \u4f9d\u8d56\r\n\r\n```bash\r\npip install volcengine\r\n```\r\n\r\n### 1. \u6dfb\u52a0\u5230 INSTALLED_APPS\r\n\r\n```python\r\nINSTALLED_APPS = [\r\n # ... \u5176\u4ed6\u5e94\u7528\r\n 'tos_uploader',\r\n]\r\n```\r\n\r\n### 2. \u914d\u7f6e\u8bbe\u7f6e\r\n\r\n```python\r\n# settings.py\r\n\r\n# \u706b\u5c71\u5f15\u64ce\u914d\u7f6e\r\nVOLCENGINE_ACCESS_KEY = 'your-access-key'\r\nVOLCENGINE_SECRET_KEY = 'your-secret-key'\r\nVOLCENGINE_REGION = 'cn-beijing' # \u6216\u5176\u4ed6\u533a\u57df\r\nVOLCENGINE_ENDPOINT = 'tos-cn-beijing.volces.com'\r\nVOLCENGINE_BUCKET = 'your-bucket-name'\r\nVOLCENGINE_ACCOUNT_ID = 'your-account-id'\r\nVOLCENGINE_STS_ROLE_NAME = 'your-sts-role-name'\r\n```\r\n\r\n### 3. \u5b9e\u73b0 STS Token \u89c6\u56fe\r\n\r\n```python\r\n# views.py\r\nfrom django.conf import settings\r\nfrom volcengine.sts.StsService import StsService\r\n\r\nfrom rest_framework import serializers\r\n\r\n\r\nclass StsTokenSerializer(serializers.Serializer):\r\n access_key = serializers.CharField(help_text=\"\u4e34\u65f6\u8bbf\u95ee\u5bc6\u94a5ID\")\r\n secret_key = serializers.CharField(help_text=\"\u4e34\u65f6\u8bbf\u95ee\u5bc6\u94a5\")\r\n security_token = serializers.CharField(help_text=\"\u5b89\u5168\u4ee4\u724c\")\r\n expiration = serializers.DateTimeField(help_text=\"\u51ed\u8bc1\u8fc7\u671f\u65f6\u95f4\")\r\n endpoint = serializers.CharField(help_text=\"Endpoint\")\r\n bucket = serializers.CharField(help_text=\"Bucket\")\r\n region = serializers.CharField(help_text=\"Region\")\r\n\r\nclass GetStsTokenAPIView(APIView):\r\n # permission_classes = [IsAuthenticated]\r\n\r\n @extend_schema(\r\n tags=[\"\u670d\u52a1\"],\r\n summary=\"\u83b7\u53d6\u706b\u5c71\u5f15\u64ceSTS\u4e34\u65f6\u8bbf\u95ee\u51ed\u8bc1\",\r\n responses={\r\n status.HTTP_200_OK: StsTokenSerializer,\r\n status.HTTP_500_INTERNAL_SERVER_ERROR: OpenApiTypes.OBJECT,\r\n },\r\n )\r\n def get(self, request, *args, **kwargs):\r\n try:\r\n # \u521d\u59cb\u5316 STS \u670d\u52a1\r\n sts_service = StsService()\r\n sts_service.set_ak(settings.VOLCENGINE_ACCESS_KEY)\r\n sts_service.set_sk(settings.VOLCENGINE_SECRET_KEY)\r\n\r\n # \u83b7\u53d6 STS \u4e34\u65f6\u51ed\u8bc1\r\n params = {\r\n \"DurationSeconds\": 3600, # 1\u5c0f\u65f6\u6709\u6548\u671f\r\n \"RoleTrn\": f\"trn:iam::{settings.VOLCENGINE_ACCOUNT_ID}:role/{settings.VOLCENGINE_STS_ROLE_NAME}\",\r\n \"RoleSessionName\": f\"renlib_user_{request.user.id}\",\r\n }\r\n resp = sts_service.assume_role(params)\r\n credentials = resp[\"Result\"][\"Credentials\"]\r\n\r\n data = {\r\n \"access_key\": credentials[\"AccessKeyId\"],\r\n \"secret_key\": credentials[\"SecretAccessKey\"],\r\n \"security_token\": credentials[\"SessionToken\"],\r\n \"expiration\": credentials[\"ExpiredTime\"],\r\n \"endpoint\": settings.VOLCENGINE_ENDPOINT,\r\n \"bucket\": settings.VOLCENGINE_BUCKET,\r\n \"region\": settings.VOLCENGINE_REGION,\r\n }\r\n serializer = StsTokenSerializer(data=data)\r\n serializer.is_valid(raise_exception=True)\r\n return Response(serializer.data)\r\n\r\n except Exception as e:\r\n return Response(\r\n {\"error\": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR\r\n )\r\n\r\n```\r\n\r\n### 4. \u914d\u7f6e URL \u8def\u7531\r\n\r\n```python\r\n# urls.py\r\nfrom django.urls import path\r\nfrom . import views\r\n\r\nurlpatterns = [\r\n path('<your url>/', views.GetStsTokenAPIView.as_view(), name='get_sts_token'),\r\n # ... \u5176\u4ed6URL\r\n]\r\n\r\n```\r\n\r\n### 5. \u5728\u6a21\u578b\u4e2d\u4f7f\u7528\r\n\r\n```python\r\nfrom tos_uploader.fields import TOSFileField\r\nfrom django.db import models\r\n\r\nclass MyModel(models.Model):\r\n # \u5176\u4ed6\u5b57\u6bb5...\r\n tos_file = TOSFileField(\r\n upload_path=\"my-uploads/\",\r\n get_sts_token_url=reverse_lazy('get_sts_token'), # \u66ff\u6362\u4e3a\u4f60\u7684\u89c6\u56fe\u540d\r\n file_types=[\"image/*\", \"video/*\"], # \u53ef\u9009\uff0c\u6587\u4ef6\u7c7b\u578b\u9650\u5236\r\n readonly=False, # \u53ef\u9009\uff0c\u662f\u5426\u53ea\u8bfb\r\n )\r\n```\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Django widget for uploading files to Volcengine TOS (Tinder Object Storage)",
"version": "1.1.1",
"project_urls": {
"Bug Reports": "https://github.com/ren000thomas/django-tos-uploader/issues",
"Documentation": "https://github.com/ren000thomas/django-tos-uploader#readme",
"Homepage": "https://github.com/ren000thomas/django-tos-uploader",
"Source": "https://github.com/ren000thomas/django-tos-uploader"
},
"split_keywords": [
"django",
" volcengine",
" tos",
" upload",
" widget",
" file-upload"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f84a28ba32c7723f2f5b6ac32979abf6df1147217917f73608033d84701c9dd7",
"md5": "fa8e39af8df128b1fbae892ffcd9c514",
"sha256": "6d148e700c29d0a93420a2a2b4def99928be8afa3404434cdd1286fc2bf0d5c0"
},
"downloads": -1,
"filename": "django_tos_uploader-1.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fa8e39af8df128b1fbae892ffcd9c514",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 18094,
"upload_time": "2025-10-23T12:48:22",
"upload_time_iso_8601": "2025-10-23T12:48:22.500800Z",
"url": "https://files.pythonhosted.org/packages/f8/4a/28ba32c7723f2f5b6ac32979abf6df1147217917f73608033d84701c9dd7/django_tos_uploader-1.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8419a548254502a86ffcf86bc34b9410e2f216645c3fe6fe1563d949e73805a5",
"md5": "cffff1d5da0740c4520b02579be5e99e",
"sha256": "c87fbb5e3cd425463743e90102617434a51289a00aa193524a869a4b871d0e7b"
},
"downloads": -1,
"filename": "django_tos_uploader-1.1.1.tar.gz",
"has_sig": false,
"md5_digest": "cffff1d5da0740c4520b02579be5e99e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 17621,
"upload_time": "2025-10-23T12:48:24",
"upload_time_iso_8601": "2025-10-23T12:48:24.693558Z",
"url": "https://files.pythonhosted.org/packages/84/19/a548254502a86ffcf86bc34b9410e2f216645c3fe6fe1563d949e73805a5/django_tos_uploader-1.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-23 12:48:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ren000thomas",
"github_project": "django-tos-uploader",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "Django",
"specs": [
[
"==",
"5.2.3"
]
]
},
{
"name": "volcengine",
"specs": [
[
"==",
"1.0.191"
]
]
}
],
"lcname": "django-tos-uploader"
}