+
+---
+> 如果本项目帮助到了你,请在[这里](https://github.com/liangliangyy/DjangoBlog/issues/214)留下你的网址,让更多的人看到。您的回复将会是我继续更新维护下去的动力。
diff --git a/blog/models.py b/blog/models.py
index 17f2fb8..083788b 100644
--- a/blog/models.py
+++ b/blog/models.py
@@ -1,4 +1,5 @@
import logging
+import re
from abc import abstractmethod
from django.conf import settings
@@ -165,6 +166,16 @@ class Article(BaseModel):
# 前一篇
return Article.objects.filter(id__lt=self.id, status='p').first()
+ def get_first_image_url(self):
+ """
+ Get the first image url from article.body.
+ :return:
+ """
+ match = re.search(r'!\[.*?\]\((.+?)\)', self.body)
+ if match:
+ return match.group(1)
+ return ""
+
class Category(BaseModel):
"""文章分类"""
diff --git a/blog/templatetags/blog_tags.py b/blog/templatetags/blog_tags.py
index 110b22b..d6cd5d5 100644
--- a/blog/templatetags/blog_tags.py
+++ b/blog/templatetags/blog_tags.py
@@ -18,12 +18,18 @@ from djangoblog.utils import CommonMarkdown, sanitize_html
from djangoblog.utils import cache
from djangoblog.utils import get_current_site
from oauth.models import OAuthUser
+from djangoblog.plugin_manage import hooks
logger = logging.getLogger(__name__)
register = template.Library()
+@register.simple_tag(takes_context=True)
+def head_meta(context):
+ return mark_safe(hooks.apply_filters('head_meta', '', context))
+
+
@register.simple_tag
def timeformat(data):
try:
diff --git a/djangoblog/__init__.py b/djangoblog/__init__.py
index e69de29..1e205f4 100644
--- a/djangoblog/__init__.py
+++ b/djangoblog/__init__.py
@@ -0,0 +1 @@
+default_app_config = 'djangoblog.apps.DjangoblogAppConfig'
diff --git a/djangoblog/apps.py b/djangoblog/apps.py
new file mode 100644
index 0000000..d29e318
--- /dev/null
+++ b/djangoblog/apps.py
@@ -0,0 +1,11 @@
+from django.apps import AppConfig
+
+class DjangoblogAppConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'djangoblog'
+
+ def ready(self):
+ super().ready()
+ # Import and load plugins here
+ from .plugin_manage.loader import load_plugins
+ load_plugins()
\ No newline at end of file
diff --git a/djangoblog/plugin_manage/loader.py b/djangoblog/plugin_manage/loader.py
new file mode 100644
index 0000000..12e824b
--- /dev/null
+++ b/djangoblog/plugin_manage/loader.py
@@ -0,0 +1,19 @@
+import os
+import logging
+from django.conf import settings
+
+logger = logging.getLogger(__name__)
+
+def load_plugins():
+ """
+ Dynamically loads and initializes plugins from the 'plugins' directory.
+ This function is intended to be called when the Django app registry is ready.
+ """
+ for plugin_name in settings.ACTIVE_PLUGINS:
+ plugin_path = os.path.join(settings.PLUGINS_DIR, plugin_name)
+ if os.path.isdir(plugin_path) and os.path.exists(os.path.join(plugin_path, 'plugin.py')):
+ try:
+ __import__(f'plugins.{plugin_name}.plugin')
+ logger.info(f"Successfully loaded plugin: {plugin_name}")
+ except ImportError as e:
+ logger.error(f"Failed to import plugin: {plugin_name}", exc_info=e)
\ No newline at end of file
diff --git a/djangoblog/settings.py b/djangoblog/settings.py
index e48a018..d076bb6 100644
--- a/djangoblog/settings.py
+++ b/djangoblog/settings.py
@@ -60,7 +60,8 @@ INSTALLED_APPS = [
'oauth',
'servermanager',
'owntracks',
- 'compressor'
+ 'compressor',
+ 'djangoblog'
]
MIDDLEWARE = [
@@ -337,14 +338,6 @@ ACTIVE_PLUGINS = [
'article_copyright',
'reading_time',
'external_links',
- 'view_count'
-]
-
-# 加载插件
-for plugin_dir in os.listdir(PLUGINS_DIR):
- plugin_path = os.path.join(PLUGINS_DIR, plugin_dir)
- if os.path.isdir(plugin_path) and os.path.exists(os.path.join(plugin_path, '__init__.py')):
- try:
- __import__(f'plugins.{plugin_dir}.plugin')
- except ImportError as e:
- print("Failed to import plugin:", plugin_dir, e)
+ 'view_count',
+ 'seo_optimizer'
+]
\ No newline at end of file
diff --git a/docs/README-en.md b/docs/README-en.md
index 4b72655..37ea069 100644
--- a/docs/README-en.md
+++ b/docs/README-en.md
@@ -1,122 +1,158 @@
# DjangoBlog
-🌍
-*[English](README-en.md) ∙ [简体中文](README.md)*
+
+
+
+
+
+
+
+
+ A powerful, elegant, and modern blog system.
+
+ English • 简体中文
+
-A blog system based on `python3.8` and `Django4.0`.
-
-
-[](https://github.com/liangliangyy/DjangoBlog/actions/workflows/django.yml) [](https://github.com/liangliangyy/DjangoBlog/actions/workflows/codeql-analysis.yml) [](https://codecov.io/gh/liangliangyy/DjangoBlog) []()
-
-
-## Main Features:
-- Articles, Pages, Categories, Tags(Add, Delete, Edit), edc. Articles and pages support `Markdown` and highlighting.
-- Articles support full-text search.
-- Complete comment feature, include posting reply comment and email notification. `Markdown` supporting.
-- Sidebar feature: new articles, most readings, tags, etc.
-- OAuth Login supported, including Google, GitHub, Facebook, Weibo, QQ.
-- `Memcache` supported, with cache auto refresh.
-- Simple SEO Features, notify Google and Baidu when there was a new article or other things.
-- Simple picture bed feature integrated.
-- `django-compressor` integrated, auto-compressed `css`, `js`.
-- Website exception email notification. When there is an unhandle exception, system will send an email notification.
-- Wechat official account feature integrated. Now, you can use wechat official account to manage your VPS.
-
-## Installation:
-Change MySQL client from `pymysql` to `mysqlclient`, more details please reference [pypi](https://pypi.org/project/mysqlclient/) , checkout preperation before installation.
-
-Install via pip: `pip install -Ur requirements.txt`
-
-If you do NOT have `pip`, please use the following methods to install:
-- OS X / Linux, run the following commands:
-
- ```
- curl http://peak.telecommunity.com/dist/ez_setup.py | python
- curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
- ```
+---
-- Windows:
+DjangoBlog is a high-performance blog platform built with Python 3.10 and Django 4.0. It not only provides all the core functionalities of a traditional blog but also features a flexible plugin system, allowing you to easily extend and customize your website. Whether you are a personal blogger, a tech enthusiast, or a content creator, DjangoBlog aims to provide a stable, efficient, and easy-to-maintain environment for writing and publishing.
- Download http://peak.telecommunity.com/dist/ez_setup.py and https://raw.github.com/pypa/pip/master/contrib/get-pip.py, and run with python.
+## ✨ Features
-### Configuration
-Most configurations are in `setting.py`, others are in backend configurations.
+- **Powerful Content Management**: Full support for managing articles, standalone pages, categories, and tags. Comes with a powerful built-in Markdown editor with syntax highlighting.
+- **Full-Text Search**: Integrated search engine for fast and accurate content searching.
+- **Interactive Comment System**: Supports replies, email notifications, and Markdown formatting in comments.
+- **Flexible Sidebar**: Customizable modules for displaying recent articles, most viewed posts, tag cloud, and more.
+- **Social Login**: Built-in OAuth support, with integrations for Google, GitHub, Facebook, Weibo, QQ, and other major platforms.
+- **High-Performance Caching**: Native support for Redis caching with an automatic refresh mechanism to ensure high-speed website responses.
+- **SEO Friendly**: Basic SEO features are included, with automatic notifications to Google and Baidu upon new content publication.
+- **Extensible Plugin System**: Extend blog functionalities by creating standalone plugins, ensuring decoupled and maintainable code. We have already implemented features like view counting and SEO optimization through plugins!
+- **Integrated Image Hosting**: A simple, built-in image hosting feature for easy uploads and management.
+- **Automated Frontend**: Integrated with `django-compressor` to automatically compress and optimize CSS and JavaScript files.
+- **Robust Operations**: Built-in email notifications for website exceptions and management capabilities through a WeChat Official Account.
-I set many `setting` configuration with my environment variables (such as: `SECRET_KEY`, `OAUTH`, `mysql` and some email configuration parts.) and they did NOT been submitted to the `GitHub`. You can change these in the code with your own configuration or just add them into your environment variables.
+## 🛠️ Tech Stack
-Files in `test` directory are for `travis` with automatic testing. You do not need to care about this. Or just use it, in this way to integrate `travis` for automatic testing.
+- **Backend**: Python 3.10, Django 4.0
+- **Database**: MySQL, SQLite (configurable)
+- **Cache**: Redis
+- **Frontend**: HTML5, CSS3, JavaScript
+- **Search**: Whoosh, Elasticsearch (configurable)
+- **Editor**: Markdown (mdeditor)
-In `bin` directory, we have scripts to deploy with `Nginx`+`Gunicorn`+`virtualenv`+`supervisor` on `linux` and `Nginx` configuration file. You can reference with my article
+## 🚀 Getting Started
->[DjangoBlog部署教程](https://www.lylinux.net/article/2019/8/5/58.html)
+### 1. Prerequisites
-More deploy detail in this article.
+Ensure you have Python 3.10+ and MySQL/MariaDB installed on your system.
-## Run
+### 2. Clone & Installation
-Modify `DjangoBlog/setting.py` with database settings, as following:
+```bash
+# Clone the project to your local machine
+git clone https://github.com/liangliangyy/DjangoBlog.git
+cd DjangoBlog
-```python
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'djangoblog',
- 'USER': 'root',
- 'PASSWORD': 'password',
- 'HOST': 'host',
- 'PORT': 3306,
- }
-}
+# Install dependencies
+pip install -r requirements.txt
```
-### Create database
-Run the following command in MySQL shell:
-```sql
-CREATE DATABASE `djangoblog` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
-```
+### 3. Project Configuration
+
+- **Database**:
+ Open `djangoblog/settings.py`, locate the `DATABASES` section, and update it with your MySQL connection details.
+
+ ```python
+ DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': 'djangoblog',
+ 'USER': 'root',
+ 'PASSWORD': 'your_password',
+ 'HOST': '127.0.0.1',
+ 'PORT': 3306,
+ }
+ }
+ ```
+ Create the database in MySQL:
+ ```sql
+ CREATE DATABASE `djangoblog` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ```
+
+- **More Configurations**:
+ For advanced settings such as email, OAuth, caching, and more, please refer to our [Detailed Configuration Guide](/docs/config-en.md).
+
+### 4. Database Initialization
-Run the following commands in Terminal:
```bash
python manage.py makemigrations
python manage.py migrate
-```
-### Create super user
-
-Run command in terminal:
-```bash
+# Create a superuser account
python manage.py createsuperuser
```
-### Create testing data
-Run command in terminal:
+### 5. Running the Project
+
```bash
+# (Optional) Generate some test data
python manage.py create_testdata
-```
-### Collect static files
-Run command in terminal:
-```bash
+# (Optional) Collect and compress static files
python manage.py collectstatic --noinput
python manage.py compress --force
+
+# Start the development server
+python manage.py runserver
```
-### Getting start to run server
-Execute: `python manage.py runserver`
+Now, open your browser and navigate to `http://127.0.0.1:8000/`. You should see the DjangoBlog homepage!
+
+## Deployment
+
+- **Traditional Deployment**: A detailed guide for server deployment is available here: [Deployment Tutorial](https://www.lylinux.net/article/2019/8/5/58.html) (in Chinese).
+- **Docker Deployment**: This project fully supports Docker. If you are familiar with containerization, please refer to the [Docker Deployment Guide](/docs/docker-en.md) for a quick start.
+- **Kubernetes Deployment**: We also provide a complete [Kubernetes Deployment Guide](/docs/k8s-en.md) to help you go cloud-native easily.
+
+## 🧩 Plugin System
+
+The plugin system is a core feature of DjangoBlog. It allows you to add new functionalities to your blog without modifying the core codebase by writing standalone plugins.
-Open up a browser and visit: http://127.0.0.1:8000/ , the you will see the blog.
+- **How it Works**: Plugins operate by registering callback functions to predefined "hooks". For instance, when an article is rendered, the `after_article_body_get` hook is triggered, and all functions registered to this hook are executed.
+- **Existing Plugins**: Features like `view_count` and `seo_optimizer` are implemented through this plugin system.
+- **Develop Your Own Plugin**: Simply create a new folder under the `plugins` directory and write your `plugin.py`. We welcome you to explore and contribute your creative ideas to the DjangoBlog community!
-## More configurations
-[More configurations details](/docs/config-en.md)
+## 🤝 Contributing
-## About the issues
+We warmly welcome contributions of any kind! If you have great ideas or have found a bug, please feel free to open an issue or submit a pull request.
-If you have any *question*, please use Issue or send problem descriptions to my email `liangliangyy#gmail.com`. I will reponse you as soon as possible. And, we recommend you to use Issue.
+## 📄 License
+
+This project is open-sourced under the [MIT License](LICENSE).
---
-## To Everyone 🙋♀️🙋♂️
-If this project helps you, please submit your site address [here](https://github.com/liangliangyy/DjangoBlog/issues/214) to let more people see it.
-Your reply will be the driving force for me to continue to update and maintain this project.
+## ❤️ Support & Sponsorship
+
+If you find this project helpful and wish to support its continued maintenance and development, please consider buying me a coffee! Your support is my greatest motivation.
+
+
+
+
+
+
+ (Left) Alipay / (Right) WeChat
+
+
+## 🙏 Acknowledgements
-🙏🙏🙏
+A special thanks to **JetBrains** for providing a free open-source license for this project.
+
+