diff --git a/.gitignore b/.gitignore index 7f37e8b..df7d442 100644 --- a/.gitignore +++ b/.gitignore @@ -174,7 +174,10 @@ cython_debug/ # PyPI configuration file .pypirc -# 忽略媒体上传目录 -*/media/* -staticfiles/ +# data/ directory for logs, static, media +data/logs/* +data/media/* +data/static/* +!data/logs/.gitkeep +!data/media/.gitkeep diff --git a/AGENTS.md b/AGENTS.md index fb6c78e..f06d1ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,14 +7,14 @@ ## Key commands -Run from `myblog/`: +Run from project root: ```bash python manage.py runserver # dev server python manage.py makemigrations # after model changes python manage.py migrate # apply migrations python manage.py createsuperuser # admin login -python manage.py collectstatic # prod: gather static files to staticfiles/ +python manage.py collectstatic # prod: gather static files to data/static/ ``` ## Package management @@ -28,13 +28,17 @@ pip install -r requirements.txt # sync deps (no lockfile) ## Project layout ``` -myblog/ -├── blog/ # main app (models, views, templates, admin) -│ └── static/blog/ # shared CSS (single style.css) -├── myblog/ # Django project settings/settings.py -├── manage.py -├── db.sqlite3 # dev DB (gitignored) -└── media/ # user uploads (gitignored) +apps/ # 所有 Django 应用 +└── blog/ # 博客应用 (models, views, templates, admin) + └── static/blog/ # 共享 CSS (style.css) +config/ # Django 项目配置 (settings.py, urls.py, wsgi.py 等) +manage.py +db.sqlite3 # dev DB (gitignored) + +data/ # 运行时数据 +├── logs/ # Django logs (rotating, gitignored) +├── static/ # collectstatic output (gitignored) +└── media/ # user uploads (gitignored) ``` ## Key models @@ -47,7 +51,7 @@ Admin at `/admin/` with MDEditor on Post content field. ## Local overrides -Create `myblog/myblog/local_settings.py` to override any setting. Imported at the bottom of `settings.py`. +Create `config/local_settings.py` to override any setting. Imported at the bottom of `settings.py`. ## Git workflow diff --git a/myblog/blog/__init__.py b/apps/__init__.py similarity index 100% rename from myblog/blog/__init__.py rename to apps/__init__.py diff --git a/myblog/blog/migrations/__init__.py b/apps/blog/__init__.py similarity index 100% rename from myblog/blog/migrations/__init__.py rename to apps/blog/__init__.py diff --git a/myblog/blog/admin.py b/apps/blog/admin.py similarity index 86% rename from myblog/blog/admin.py rename to apps/blog/admin.py index 86f4d15..cb8f09f 100644 --- a/myblog/blog/admin.py +++ b/apps/blog/admin.py @@ -11,7 +11,9 @@ class PostAdmin(admin.ModelAdmin): } # 设置列表显示字段 - list_display = ('title', 'publish_date', 'created_at', 'updated_at') + list_display = ('title', 'category', 'status', 'publish_date', 'created_at', 'updated_at') + # 设置过滤器 + list_filter = ('status', 'category', 'publish_date') # 设置搜索字段 search_fields = ('title', 'content') diff --git a/myblog/blog/apps.py b/apps/blog/apps.py similarity index 100% rename from myblog/blog/apps.py rename to apps/blog/apps.py diff --git a/myblog/blog/feeds.py b/apps/blog/feeds.py similarity index 100% rename from myblog/blog/feeds.py rename to apps/blog/feeds.py diff --git a/myblog/blog/migrations/0001_initial.py b/apps/blog/migrations/0001_initial.py similarity index 100% rename from myblog/blog/migrations/0001_initial.py rename to apps/blog/migrations/0001_initial.py diff --git a/myblog/blog/migrations/0002_post_publish_date.py b/apps/blog/migrations/0002_post_publish_date.py similarity index 100% rename from myblog/blog/migrations/0002_post_publish_date.py rename to apps/blog/migrations/0002_post_publish_date.py diff --git a/myblog/blog/migrations/0003_post_image.py b/apps/blog/migrations/0003_post_image.py similarity index 100% rename from myblog/blog/migrations/0003_post_image.py rename to apps/blog/migrations/0003_post_image.py diff --git a/myblog/blog/migrations/0004_alter_post_content.py b/apps/blog/migrations/0004_alter_post_content.py similarity index 100% rename from myblog/blog/migrations/0004_alter_post_content.py rename to apps/blog/migrations/0004_alter_post_content.py diff --git a/myblog/blog/migrations/0005_remove_post_image.py b/apps/blog/migrations/0005_remove_post_image.py similarity index 100% rename from myblog/blog/migrations/0005_remove_post_image.py rename to apps/blog/migrations/0005_remove_post_image.py diff --git a/myblog/blog/migrations/0006_category.py b/apps/blog/migrations/0006_category.py similarity index 100% rename from myblog/blog/migrations/0006_category.py rename to apps/blog/migrations/0006_category.py diff --git a/myblog/blog/migrations/0007_post_category.py b/apps/blog/migrations/0007_post_category.py similarity index 100% rename from myblog/blog/migrations/0007_post_category.py rename to apps/blog/migrations/0007_post_category.py diff --git a/myblog/blog/migrations/0008_sitesettings.py b/apps/blog/migrations/0008_sitesettings.py similarity index 100% rename from myblog/blog/migrations/0008_sitesettings.py rename to apps/blog/migrations/0008_sitesettings.py diff --git a/myblog/blog/migrations/0009_sitesettings_contact_email_and_more.py b/apps/blog/migrations/0009_sitesettings_contact_email_and_more.py similarity index 100% rename from myblog/blog/migrations/0009_sitesettings_contact_email_and_more.py rename to apps/blog/migrations/0009_sitesettings_contact_email_and_more.py diff --git a/myblog/blog/migrations/0010_post_status.py b/apps/blog/migrations/0010_post_status.py similarity index 100% rename from myblog/blog/migrations/0010_post_status.py rename to apps/blog/migrations/0010_post_status.py diff --git a/apps/blog/migrations/0011_alter_post_status.py b/apps/blog/migrations/0011_alter_post_status.py new file mode 100644 index 0000000..8dca38e --- /dev/null +++ b/apps/blog/migrations/0011_alter_post_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1 on 2026-08-25 10:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0010_post_status'), + ] + + operations = [ + migrations.AlterField( + model_name='post', + name='status', + field=models.CharField(choices=[('draft', '草稿'), ('published', '已发布')], default='published', max_length=10), + ), + ] diff --git a/myblog/myblog/__init__.py b/apps/blog/migrations/__init__.py similarity index 100% rename from myblog/myblog/__init__.py rename to apps/blog/migrations/__init__.py diff --git a/myblog/blog/models.py b/apps/blog/models.py similarity index 98% rename from myblog/blog/models.py rename to apps/blog/models.py index 8b41429..154188b 100644 --- a/myblog/blog/models.py +++ b/apps/blog/models.py @@ -1,6 +1,8 @@ from django.conf import settings from django.db import models from django.utils import timezone +import re +import emoji import markdown from django.utils.safestring import mark_safe from mdeditor.fields import MDTextField @@ -52,14 +54,12 @@ class Post(models.Model): # 添加分类字段,建立外键关系 category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True, related_name='posts') # 添加状态字段 - status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=DRAFT) + status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=PUBLISHED) def __str__(self): return f"{self.title}" def get_markdown_content(self): - import re - import emoji content = self.content media_url = settings.MEDIA_URL.rstrip('/') diff --git a/myblog/blog/static/blog/style.css b/apps/blog/static/blog/style.css similarity index 100% rename from myblog/blog/static/blog/style.css rename to apps/blog/static/blog/style.css diff --git a/myblog/blog/templates/blog/base.html b/apps/blog/templates/blog/base.html similarity index 100% rename from myblog/blog/templates/blog/base.html rename to apps/blog/templates/blog/base.html diff --git a/myblog/blog/templates/blog/contact.html b/apps/blog/templates/blog/contact.html similarity index 100% rename from myblog/blog/templates/blog/contact.html rename to apps/blog/templates/blog/contact.html diff --git a/myblog/blog/templates/blog/detail.html b/apps/blog/templates/blog/detail.html similarity index 100% rename from myblog/blog/templates/blog/detail.html rename to apps/blog/templates/blog/detail.html diff --git a/myblog/blog/templates/blog/index.html b/apps/blog/templates/blog/index.html similarity index 100% rename from myblog/blog/templates/blog/index.html rename to apps/blog/templates/blog/index.html diff --git a/myblog/blog/templates/blog/rss.html b/apps/blog/templates/blog/rss.html similarity index 100% rename from myblog/blog/templates/blog/rss.html rename to apps/blog/templates/blog/rss.html diff --git a/myblog/blog/tests.py b/apps/blog/tests.py similarity index 100% rename from myblog/blog/tests.py rename to apps/blog/tests.py diff --git a/myblog/blog/urls.py b/apps/blog/urls.py similarity index 100% rename from myblog/blog/urls.py rename to apps/blog/urls.py diff --git a/myblog/blog/views.py b/apps/blog/views.py similarity index 100% rename from myblog/blog/views.py rename to apps/blog/views.py diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000..473a0f4 diff --git a/myblog/myblog/asgi.py b/config/asgi.py similarity index 62% rename from myblog/myblog/asgi.py rename to config/asgi.py index 2a9c503..79872a9 100644 --- a/myblog/myblog/asgi.py +++ b/config/asgi.py @@ -8,8 +8,11 @@ https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/ """ import os +import sys from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myblog.settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') +# 将 apps/ 加入 Python 路径 +sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'apps')) application = get_asgi_application() diff --git a/config/local_settings.example.py b/config/local_settings.example.py new file mode 100644 index 0000000..49edb46 --- /dev/null +++ b/config/local_settings.example.py @@ -0,0 +1,25 @@ +""" +本地设置示例文件 +使用方法:复制为 local_settings.py 并按需修改 + cp local_settings.example.py local_settings.py +""" + +# 生产环境请设置 +# import os +# SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'your-secret-key') + +# DEBUG = False + +# ALLOWED_HOSTS = ['www.yuangyaa.com', 'yuangyaa.com'] + +# 生产环境数据库(PostgreSQL) +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.postgresql', +# 'NAME': 'blog', +# 'USER': 'blog_user', +# 'PASSWORD': 'your_password', +# 'HOST': 'localhost', +# 'PORT': '5432', +# } +# } diff --git a/myblog/myblog/settings.py b/config/settings.py similarity index 95% rename from myblog/myblog/settings.py rename to config/settings.py index 9352515..6a7143e 100644 --- a/myblog/myblog/settings.py +++ b/config/settings.py @@ -11,16 +11,20 @@ https://docs.djangoproject.com/en/5.2/ref/settings/ """ from pathlib import Path +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent -DATA_DIR = BASE_DIR.parent / 'data' +DATA_DIR = BASE_DIR / 'data' # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-g224%sp()h))26kj26pnnfoayu-knah+!)h9uzgqeece&6*clp' +SECRET_KEY = os.environ.get( + 'DJANGO_SECRET_KEY', + 'django-insecure-g224%sp()h))26kj26pnnfoayu-knah+!)h9uzgqeece&6*clp' +) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -50,7 +54,7 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] -ROOT_URLCONF = 'myblog.urls' +ROOT_URLCONF = 'config.urls' TEMPLATES = [ { @@ -67,7 +71,7 @@ TEMPLATES = [ }, ] -WSGI_APPLICATION = 'myblog.wsgi.application' +WSGI_APPLICATION = 'config.wsgi.application' # Database # https://docs.djangoproject.com/en/5.2/ref/settings/#databases diff --git a/myblog/myblog/urls.py b/config/urls.py similarity index 100% rename from myblog/myblog/urls.py rename to config/urls.py diff --git a/myblog/myblog/wsgi.py b/config/wsgi.py similarity index 62% rename from myblog/myblog/wsgi.py rename to config/wsgi.py index 9acfbbc..3813acf 100644 --- a/myblog/myblog/wsgi.py +++ b/config/wsgi.py @@ -8,8 +8,11 @@ https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ """ import os +import sys from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myblog.settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') +# 将 apps/ 加入 Python 路径 +sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'apps')) application = get_wsgi_application() diff --git a/data/logs/.gitkeep b/data/logs/.gitkeep new file mode 100644 index 0000000..473a0f4 diff --git a/data/media/.gitkeep b/data/media/.gitkeep new file mode 100644 index 0000000..473a0f4 diff --git a/identifier.sqlite b/identifier.sqlite new file mode 100644 index 0000000..473a0f4 diff --git a/myblog/manage.py b/manage.py similarity index 74% rename from myblog/manage.py rename to manage.py index 72c936e..00c3433 100755 --- a/myblog/manage.py +++ b/manage.py @@ -6,7 +6,9 @@ import sys def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myblog.settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + # 将 apps/ 加入 Python 路径,使 Django 能找到各应用 + sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'apps')) try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/requirements.txt b/requirements.txt index 51bb383..67b7923 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,11 +16,8 @@ ipython==9.4.0 ipython_pygments_lexers==1.1.1 jedi==0.19.2 Markdown==3.5.2 -martor==1.6.45 matplotlib-inline==0.1.7 -numpy==2.3.2 packaging==25.0 -pandas==2.3.1 parso==0.8.4 pexpect==4.9.0 pillow==11.3.0 @@ -38,7 +35,6 @@ stack-data==0.6.3 traitlets==5.14.3 tzdata==2025.2 urllib3==2.5.0 -uv==0.8.3 uvicorn==0.35.0 wcwidth==0.2.13 webencodings==0.5.1