添加上传图片

This commit is contained in:
2025-06-15 21:52:26 +08:00
parent 5aaf86b3ee
commit f30dfac02b
7 changed files with 52 additions and 15 deletions

View File

@@ -1,4 +1,3 @@
import random
from typing import List
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

View File

@@ -1,28 +1,28 @@
from ninja.errors import HttpError
from ninja import NinjaAPI
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
api = NinjaAPI()
def _require(roles):
def decorator(func):
def _require(roles: List[RoleChoices]) -> Callable:
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)
def wrapper(request, *args, **kwargs):
if not request.user.is_authenticated:
raise HttpError(401, "用户未登录")
try:
if request.user.role not in roles:
raise HttpError(403, "你没有权限")
except User.DoesNotExist:
raise HttpError(404, "用户不存在")
@login_required
@user_passes_test(check_role, login_url=None)
def wrapper(request: HttpRequest, *args: Any, **kwargs: Any) -> Any:
return func(request, *args, **kwargs)
return wrapper
return decorator
admin_required = _require([RoleChoices.ADMIN, RoleChoices.SUPER])
admin_required = _require([RoleChoices.ADMIN, RoleChoices.SUPER])
super_required = _require([RoleChoices.SUPER])

View File

@@ -183,3 +183,7 @@ CORS_ALLOW_CREDENTIALS = True
NINJA_PAGINATION_CLASS = "ninja.pagination.PageNumberPagination"
NINJA_PAGINATION_PER_PAGE = 10
# Media files
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR.parent / "media"

View File

@@ -17,6 +17,8 @@ Including another URLconf
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from ninja import NinjaAPI
api = NinjaAPI()
@@ -24,8 +26,12 @@ api = NinjaAPI()
api.add_router("account/", "account.api.router")
api.add_router("tutorial/", "task.tutorial.router")
api.add_router("submission/", "submission.api.router")
api.add_router("upload/", "utils.upload.router")
urlpatterns = [
apis = [
path("admin/", admin.site.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
View File

29
utils/upload.py Normal file
View 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}"}