添加上传图片
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import random
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from django.contrib.auth import authenticate, login, logout
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
from ninja.errors import HttpError
|
|
||||||
from ninja import NinjaAPI
|
from ninja import NinjaAPI
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from typing import Callable, List, Any
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||||
from .models import User, RoleChoices
|
from .models import User, RoleChoices
|
||||||
|
|
||||||
api = NinjaAPI()
|
api = NinjaAPI()
|
||||||
|
|
||||||
|
|
||||||
def _require(roles):
|
def _require(roles: List[RoleChoices]) -> Callable:
|
||||||
def decorator(func):
|
def check_role(user: User) -> bool:
|
||||||
|
return user.is_authenticated and hasattr(user, "role") and user.role in roles
|
||||||
|
|
||||||
|
def decorator(func: Callable) -> Callable:
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(request, *args, **kwargs):
|
@login_required
|
||||||
if not request.user.is_authenticated:
|
@user_passes_test(check_role, login_url=None)
|
||||||
raise HttpError(401, "用户未登录")
|
def wrapper(request: HttpRequest, *args: Any, **kwargs: Any) -> Any:
|
||||||
try:
|
|
||||||
if request.user.role not in roles:
|
|
||||||
raise HttpError(403, "你没有权限")
|
|
||||||
except User.DoesNotExist:
|
|
||||||
raise HttpError(404, "用户不存在")
|
|
||||||
return func(request, *args, **kwargs)
|
return func(request, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
admin_required = _require([RoleChoices.ADMIN, RoleChoices.SUPER])
|
|
||||||
|
|
||||||
|
admin_required = _require([RoleChoices.ADMIN, RoleChoices.SUPER])
|
||||||
super_required = _require([RoleChoices.SUPER])
|
super_required = _require([RoleChoices.SUPER])
|
||||||
|
|||||||
@@ -183,3 +183,7 @@ CORS_ALLOW_CREDENTIALS = True
|
|||||||
NINJA_PAGINATION_CLASS = "ninja.pagination.PageNumberPagination"
|
NINJA_PAGINATION_CLASS = "ninja.pagination.PageNumberPagination"
|
||||||
|
|
||||||
NINJA_PAGINATION_PER_PAGE = 10
|
NINJA_PAGINATION_PER_PAGE = 10
|
||||||
|
|
||||||
|
# Media files
|
||||||
|
MEDIA_URL = "/media/"
|
||||||
|
MEDIA_ROOT = BASE_DIR.parent / "media"
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ Including another URLconf
|
|||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls.static import static
|
||||||
from ninja import NinjaAPI
|
from ninja import NinjaAPI
|
||||||
|
|
||||||
api = NinjaAPI()
|
api = NinjaAPI()
|
||||||
@@ -24,8 +26,12 @@ api = NinjaAPI()
|
|||||||
api.add_router("account/", "account.api.router")
|
api.add_router("account/", "account.api.router")
|
||||||
api.add_router("tutorial/", "task.tutorial.router")
|
api.add_router("tutorial/", "task.tutorial.router")
|
||||||
api.add_router("submission/", "submission.api.router")
|
api.add_router("submission/", "submission.api.router")
|
||||||
|
api.add_router("upload/", "utils.upload.router")
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
|
apis = [
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("api/", api.urls),
|
path("api/", api.urls),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
urlpatterns = apis + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|||||||
Submodule data/hitokoto deleted from b503a98f23
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
29
utils/upload.py
Normal file
29
utils/upload.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from ninja import Router, File
|
||||||
|
from ninja.files import UploadedFile
|
||||||
|
from pathlib import Path
|
||||||
|
from django.conf import settings
|
||||||
|
import uuid
|
||||||
|
from account.decorators import super_required
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("")
|
||||||
|
@super_required
|
||||||
|
def upload_to_media(request, image: File[UploadedFile]):
|
||||||
|
# 生成唯一的文件名
|
||||||
|
ext = Path(image.name).suffix
|
||||||
|
filename = f"{uuid.uuid4()}{ext}"
|
||||||
|
|
||||||
|
# 确保 media 目录存在
|
||||||
|
media_root = Path(settings.MEDIA_ROOT)
|
||||||
|
media_root.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# 保存文件
|
||||||
|
file_path = media_root / filename
|
||||||
|
with open(file_path, "wb+") as f:
|
||||||
|
for chunk in image.chunks():
|
||||||
|
f.write(chunk)
|
||||||
|
|
||||||
|
# 返回文件URL
|
||||||
|
return {"url": f"{settings.MEDIA_URL}{filename}"}
|
||||||
Reference in New Issue
Block a user