Namespace API routes by app and flatten package layout.
Move Django apps out of apps/ and mount them under auth/, common/, content/, and cms/ so endpoint paths map directly to the owning app. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
9f9c5f814f
commit
13b1ca2b9b
14
README.md
14
README.md
@ -18,10 +18,16 @@ Default local DB is SQLite via `config/local_settings.py`. For PostgreSQL, overr
|
||||
|
||||
## API
|
||||
|
||||
- Public & staff CRUD: `/api/articles/`, `/api/organizes/`, `/api/subjects/`, `/api/organize-categories/`, `/api/magazine-categories/`, `/api/work-groups/`, `/api/work-group-terms/`, `/api/columns/`, …
|
||||
- Auth: `POST /api/auth/login/`, `GET /api/auth/me/`
|
||||
- Django admin: `/django-admin/`
|
||||
- Search: `GET /api/search/?q=`
|
||||
路由按 app 划分前缀(网关再统一挂 `/api`):
|
||||
|
||||
| 前缀 | App | 示例 |
|
||||
|------|-----|------|
|
||||
| `/api/auth/` | `accounts` | `POST /api/auth/login/`、`GET /api/auth/me/` |
|
||||
| `/api/common/` | `common` | `POST /api/common/uploads/` |
|
||||
| `/api/content/` | `content` | `/api/content/articles/`、`/api/content/columns/`、… |
|
||||
| `/api/cms/` | `cms` | `/api/cms/news/`、`GET /api/cms/search/?q=` |
|
||||
|
||||
Django admin: `/django-admin/`
|
||||
|
||||
Staff write operations require `Authorization: Token <key>` and `is_staff=True`.
|
||||
|
||||
|
||||
@ -3,6 +3,6 @@ from django.apps import AppConfig
|
||||
|
||||
class AccountsConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "apps.accounts"
|
||||
name = "accounts"
|
||||
label = "accounts"
|
||||
verbose_name = "账号"
|
||||
@ -2,7 +2,7 @@ from decimal import Decimal
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from apps.cms.models import (
|
||||
from cms.models import (
|
||||
AboutInfo,
|
||||
ContactUs,
|
||||
CopyrightInfo,
|
||||
@ -12,8 +12,8 @@ from apps.cms.models import (
|
||||
News,
|
||||
Publication,
|
||||
)
|
||||
from apps.accounts.models import Member
|
||||
from apps.content.models import (
|
||||
from accounts.models import Member
|
||||
from content.models import (
|
||||
Article,
|
||||
ArticleComment,
|
||||
Column,
|
||||
@ -478,7 +478,7 @@ class Command(BaseCommand):
|
||||
return created, updated
|
||||
|
||||
def _ensure_demo_comments(self):
|
||||
from apps.accounts.serializers import MemberSerializer
|
||||
from accounts.serializers import MemberSerializer
|
||||
|
||||
# 国际格式;同时兼容旧的 11 位国内号演示数据
|
||||
member = (
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from apps.content.models import Column, NavPosition
|
||||
from content.models import Column, NavPosition
|
||||
|
||||
|
||||
# 与 ui/src/config/nav.js 对齐
|
||||
@ -1,7 +1,7 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
|
||||
from apps.common.models import SoftDeleteModel
|
||||
from common.models import SoftDeleteModel
|
||||
|
||||
|
||||
class Member(SoftDeleteModel):
|
||||
@ -3,6 +3,6 @@ from django.apps import AppConfig
|
||||
|
||||
class CmsConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "apps.cms"
|
||||
name = "cms"
|
||||
label = "cms"
|
||||
verbose_name = "站点内容"
|
||||
@ -1,6 +1,6 @@
|
||||
from django.db import models
|
||||
|
||||
from apps.common.models import SoftDeleteModel
|
||||
from common.models import SoftDeleteModel
|
||||
|
||||
|
||||
class News(SoftDeleteModel):
|
||||
@ -9,13 +9,13 @@ from rest_framework.decorators import action
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
|
||||
from apps.content.models import Article, Organize, Professor
|
||||
from apps.content.serializers import (
|
||||
from content.models import Article, Organize, Professor
|
||||
from content.serializers import (
|
||||
ArticleListSerializer,
|
||||
OrganizeListSerializer,
|
||||
ProfessorSerializer,
|
||||
)
|
||||
from apps.content.views import IsAdminOrReadOnly, PublicMixin
|
||||
from content.views import IsAdminOrReadOnly, PublicMixin
|
||||
|
||||
ALLOWED_IMAGE_EXT = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"}
|
||||
MAX_UPLOAD_BYTES = 8 * 1024 * 1024
|
||||
@ -3,6 +3,6 @@ from django.apps import AppConfig
|
||||
|
||||
class CommonConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "apps.common"
|
||||
name = "common"
|
||||
label = "common"
|
||||
verbose_name = "公共"
|
||||
@ -32,7 +32,7 @@ CATEGORY_RE = re.compile(r"^[a-zA-Z0-9_-]{1,32}$")
|
||||
|
||||
|
||||
class MediaUploadView(APIView):
|
||||
"""POST /api/uploads/ 表单字段: file, category(可选), kind=image|file(可选)"""
|
||||
"""POST /uploads/ 表单字段: file, category(可选), kind=image|file(可选)"""
|
||||
|
||||
permission_classes = [permissions.IsAdminUser]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
@ -45,10 +45,10 @@ INSTALLED_APPS = [
|
||||
"django_extensions",
|
||||
"simple_history",
|
||||
"corsheaders",
|
||||
"apps.common",
|
||||
"apps.content",
|
||||
"apps.cms",
|
||||
"apps.accounts",
|
||||
"common",
|
||||
"content",
|
||||
"cms",
|
||||
"accounts",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
||||
@ -5,10 +5,10 @@ from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("django-admin/", admin.site.urls),
|
||||
path("api/auth/", include("apps.accounts.urls")),
|
||||
path("api/", include("apps.common.urls")),
|
||||
path("api/", include("apps.content.urls")),
|
||||
path("api/", include("apps.cms.urls")),
|
||||
path("auth/", include("accounts.urls")),
|
||||
path("common/", include("common.urls")),
|
||||
path("content/", include("content.urls")),
|
||||
path("cms/", include("cms.urls")),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
||||
@ -3,6 +3,6 @@ from django.apps import AppConfig
|
||||
|
||||
class ContentConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "apps.content"
|
||||
name = "content"
|
||||
label = "content"
|
||||
verbose_name = "内容"
|
||||
@ -1,6 +1,6 @@
|
||||
from django.db import models
|
||||
|
||||
from apps.common.models import SoftDeleteModel, TimeStampedModel
|
||||
from common.models import SoftDeleteModel, TimeStampedModel
|
||||
|
||||
|
||||
class NavPosition(models.IntegerChoices):
|
||||
Loading…
x
Reference in New Issue
Block a user