diff --git a/.gitignore b/.gitignore index 71b805a..7f37e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,5 @@ cython_debug/ # 忽略媒体上传目录 */media/* +staticfiles/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..fb6c78e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,66 @@ +# AGENTS.md — blog (六桂流芳的com) + +## Tech stack + +- Python 3.12.7, Django 5.1, SQLite (dev) / PostgreSQL (prod via `psycopg2-binary`) +- `zh-Hans` locale, `Asia/Shanghai` timezone + +## Key commands + +Run from `myblog/`: + +```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/ +``` + +## Package management + +```bash +pip install -r requirements.txt # sync deps (no lockfile) +``` + +`uv` (v0.8.3) is in requirements.txt but not the primary workflow. + +## 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) +``` + +## Key models + +- `Post` — `title`, `content` (MDEditor), `category` (FK), `status` (draft/published), `publish_date` +- `Category` — `name`, `description` +- `SiteSettings` — singleton: `summary_length`, contact fields + +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`. + +## Git workflow + +``` +feature/* or bugfix/* → develop → main +``` + +Remote: `ssh://git@git.yuangyaa.com:222/yuangyaa/blog.git` + +## What's NOT configured + +- **No tests** (tests.py is blank) +- **No linting, formatting, or type checking** +- **No CI/CD** +- **No pre-commit hooks** +- **No Docker** diff --git a/myblog/blog/feeds.py b/myblog/blog/feeds.py index 478b2a9..4b2d02d 100644 --- a/myblog/blog/feeds.py +++ b/myblog/blog/feeds.py @@ -12,7 +12,7 @@ class LatestPostsFeed(Feed): content_type = 'application/xml; charset=utf-8' def items(self): - return Post.objects.order_by('-publish_date')[:10] + return Post.objects.filter(status=Post.PUBLISHED).order_by('-publish_date')[:10] def item_title(self, item): return item.title @@ -42,7 +42,7 @@ class CategoryPostsFeed(Feed): return f"{obj.name}分类的最新博客文章" def items(self, obj): - return Post.objects.filter(category=obj).order_by('-publish_date')[:10] + return Post.objects.filter(category=obj, status=Post.PUBLISHED).order_by('-publish_date')[:10] def item_title(self, item): return item.title @@ -63,7 +63,7 @@ class RecentPostsFeed(Feed): content_type = 'application/xml; charset=utf-8' def items(self): - return Post.objects.order_by('-publish_date')[:20] + return Post.objects.filter(status=Post.PUBLISHED).order_by('-publish_date')[:20] def item_title(self, item): return item.title @@ -84,7 +84,7 @@ class AllPostsFeed(Feed): content_type = 'application/xml; charset=utf-8' def items(self): - return Post.objects.order_by('-publish_date') + return Post.objects.filter(status=Post.PUBLISHED).order_by('-publish_date') def item_title(self, item): return item.title diff --git a/myblog/blog/static/blog/style.css b/myblog/blog/static/blog/style.css new file mode 100644 index 0000000..e4f2f9e --- /dev/null +++ b/myblog/blog/static/blog/style.css @@ -0,0 +1,340 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; +} + +.top-nav { + background-color: #007cba; + padding: 10px 0; + margin-bottom: 20px; +} + +.nav-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +.nav-links { + list-style: none; + padding: 0; + margin: 0; + display: flex; +} + +.nav-links li { + margin-right: 20px; +} + +.nav-links li a { + color: white; + text-decoration: none; + padding: 8px 12px; + border-radius: 4px; + transition: background-color 0.3s; +} + +.nav-links li a:hover { + background-color: rgba(255, 255, 255, 0.2); +} + +.container { + display: flex; + max-width: 1200px; + margin: 0 auto; + padding: 20px; + min-height: 100vh; +} + +.sidebar { + width: 250px; + padding-right: 20px; + border-right: 1px solid #eee; + position: -webkit-sticky; + position: sticky; + top: 20px; + align-self: flex-start; + height: fit-content; +} + +.sidebar h3 { + color: #333; + border-bottom: 2px solid #007cba; + padding-bottom: 10px; +} + +.sidebar ul { + list-style: none; + padding: 0; +} + +.sidebar ul li { + margin: 10px 0; +} + +.sidebar ul li a { + text-decoration: none; + color: #666; + display: block; + padding: 8px 12px; + border-radius: 4px; + transition: all 0.3s; +} + +.sidebar ul li a:hover, +.sidebar ul li a.active { + background-color: #007cba; + color: white; +} + +.search-box { + margin-bottom: 20px; +} + +.search-box input[type="text"] { + width: 100%; + padding: 8px; + border: 1px solid #ddd; + border-radius: 4px; + box-sizing: border-box; +} + +.search-box input[type="submit"] { + width: 100%; + padding: 8px; + background-color: #007cba; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + margin-top: 5px; +} + +.search-box input[type="submit"]:hover { + background-color: #005a87; +} + +.search-type { + margin: 10px 0; +} + +.search-type label { + display: block; + margin: 5px 0; + font-size: 14px; + color: #666; +} + +.search-type input[type="radio"] { + margin-right: 5px; +} + +.main-content { + flex: 1; + padding-left: 20px; +} + +.main-content h1 { + color: #333; + border-bottom: 2px solid #eee; + padding-bottom: 10px; +} + +footer { + position: fixed; + bottom: 0; + width: 100%; + text-align: center; + font-size: 12px; + color: #999; + background-color: white; + padding: 5px 0; +} + +.posts-list { + list-style: none; + padding: 0; +} + +.posts-list li { + padding: 15px 0; + border-bottom: 1px solid #eee; +} + +.posts-list li:last-child { + border-bottom: none; +} + +.post-title { + font-size: 18px; + font-weight: bold; + margin-bottom: 8px; +} + +.post-title a { + text-decoration: none; + color: #007cba; +} + +.post-meta { + font-size: 14px; + color: #999; +} + +.post-category { + display: inline-block; + background-color: #f0f0f0; + padding: 2px 6px; + border-radius: 3px; + font-size: 12px; + margin-top: 5px; +} + +.post-summary { + margin: 10px 0; + line-height: 1.6; + color: #666; +} + +.pagination { + margin-top: 20px; + text-align: center; +} + +.pagination a { + display: inline-block; + padding: 8px 12px; + margin: 0 4px; + border: 1px solid #ddd; + border-radius: 4px; + text-decoration: none; + color: #007cba; +} + +.pagination a:hover { + background-color: #007cba; + color: white; +} + +.pagination .current { + display: inline-block; + padding: 8px 12px; + margin: 0 4px; + background-color: #007cba; + color: white; + border-radius: 4px; +} + +.post-content img { + max-width: 100%; + height: auto; + display: block; + margin: 10px 0; +} + +.post-content pre { + background-color: #f4f4f4; + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + overflow-x: auto; + margin: 10px 0; +} + +.post-content code { + font-family: 'Courier New', Courier, monospace; + background-color: #f4f4f4; + padding: 2px 4px; + border-radius: 3px; + font-size: 0.9em; +} + +.post-content pre code { + background-color: transparent; + padding: 0; + border-radius: 0; + font-size: 0.9em; +} + +.contact-main, +.rss-main { + background-color: #f9f9f9; + padding: 20px; + border-radius: 5px; + border: 1px solid #eee; +} + +.contact-main h2, +.rss-main h2 { + color: #333; + border-bottom: 2px solid #007cba; + padding-bottom: 10px; +} + +.rss-main h2 { + border-bottom-color: #ff6600; +} + +.contact-description, +.rss-description { + margin: 15px 0; + line-height: 1.6; + color: #666; +} + +.contact-details { + list-style: none; + padding: 0; +} + +.contact-details li { + padding: 10px 0; + border-bottom: 1px solid #eee; +} + +.contact-details li:last-child { + border-bottom: none; +} + +.contact-label { + font-weight: bold; + color: #333; + display: inline-block; + width: 80px; +} + +.contact-value { + color: #666; +} + +.rss-feed-list { + list-style: none; + padding: 0; +} + +.rss-feed-list li { + padding: 10px 0; + border-bottom: 1px solid #eee; +} + +.rss-feed-list li:last-child { + border-bottom: none; +} + +.rss-feed-link { + font-size: 16px; + font-weight: bold; + color: #007cba; + text-decoration: none; +} + +.rss-feed-link:hover { + text-decoration: underline; +} + +.rss-feed-description { + font-size: 14px; + color: #999; + margin-top: 5px; +} diff --git a/myblog/blog/templates/blog/base.html b/myblog/blog/templates/blog/base.html new file mode 100644 index 0000000..eecf9a6 --- /dev/null +++ b/myblog/blog/templates/blog/base.html @@ -0,0 +1,72 @@ +{% load static %} + + + + + {% block title %}六桂流芳的com{% endblock %} + + + +
+ +
+ +
+ + +
+ {% block content %}{% endblock %} +
+
+ + + + diff --git a/myblog/blog/templates/blog/contact.html b/myblog/blog/templates/blog/contact.html index e3af3de..0538065 100644 --- a/myblog/blog/templates/blog/contact.html +++ b/myblog/blog/templates/blog/contact.html @@ -1,325 +1,37 @@ - - - - - 联系我 - 六桂流芳的com - - - - -
-