文章列表设计

先规划一下模型

文章

父体(空) ,字段(标题), 作者, 点赞数, 评论数

评论

父体(文章ID或者评论ID),字段(评论内容),作者(评论者),点赞数, 评论数

可以看出,文章和评论是差不多的,只是显示的位置不同,以及评论是文章的从属关系.以及为文章设置父体,方便之后给文章分类归档

model.py
class Post(models.Model):
    text = models.CharField(max_length=255)  # 文章的标题或评论的内容
    author = models.ForeignKey(User, on_delete=models.CASCADE)  # 作者或评论者
    parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, related_name='comments')  # 自引用父体,可以是文章或评论
    likes = models.IntegerField(default=0)  # 点赞数
    comments_count = models.IntegerField(default=0)  # 评论数
    created_at = models.DateTimeField(auto_now_add=True)  # 创建时间
 
    def __str__(self):
        return self.text
使用定时计划爬取文章

这里用宝塔自带的计划任务,每1分钟爬取1次,使用webdav抓nextcloud的文件,再使用nextcloud win客户端的webdav功能上传文件,就可以实现全自动保存和上传到文件列表了

task.py
import requests
from requests.auth import HTTPBasicAuth
import MySQLdb
 
# 数据库连接配置
db_config = {
    'host': 'localhost',  # 数据库主机
    'user': 'your_username',  # 数据库用户名
    'passwd': 'your_password',  # 数据库密码
    'db': 'your_database'  # 数据库名
}
 
# 连接到 MySQL 数据库
db = MySQLdb.connect(**db_config)
cursor = db.cursor()
 
# 配置你的 API URL 和 token
api_url = "https://your-nextcloud-instance.com/remote.php/dav/files/username/your-folder/"
token = "your_api_token"
 
# 发起请求
response = requests.request("PROPFIND", api_url, auth=HTTPBasicAuth('username', token), headers={
    "Depth": "1",
    "Content-Type": "application/xml"
})
 
# 检查响应
if response.status_code == 207:  # 多状态响应
    print("获取 .md 文件名成功:")
    from xml.etree import ElementTree as ET
    root = ET.fromstring(response.content)
    
    for response in root.findall('{DAV:}response'):
        href = response.find('{DAV:}href')
        if href is not None:
            filename = href.text.split('/')[-1]
            if filename.endswith('.md'):
                # 检查文件名是否已存在
                cursor.execute("SELECT COUNT(*) FROM your_table_name WHERE text = %s", (filename,))
                if cursor.fetchone()[0] == 0:  # 如果文件名不存在
                    # 插入新记录
                    cursor.execute(
                        "INSERT INTO your_table_name (text, author, parent, likes, comments_count) VALUES (%s, %s, %s, %s, %s)",
                        (filename, 'admin', None, 0, 0)
                    )
                    db.commit()  # 提交更改
                    print(f"已添加文件: {filename}")
                else:
                    print(f"文件已存在: {filename}")
 
else:
    print(f"获取文件名失败,状态码:{response.status_code}")
 
# 关闭数据库连接
cursor.close()
db.close()

nextcloud

视图函数中向前端传文章列表, 对父体进行筛选空,就能全选文章了,之后也可以根据文章分类, 设置不同的父体进行筛选,完成专栏分类功能!

@login_required
def index(request):
 
    articles = Post.objects.filter(parent__isnull=True)
    context = {
        'articles': articles
    }
    return render(request, 'index.html',context)

模板判断登录,以及循环遍历文章标题等,由于前面加了@login_required, 所以这里不判断是否登录{% if user.is_authenticated%}也是可以的,整个页面都会要求登录可见

{% if user.is_authenticated%}
    <div id="body_content">
 
    <h1>Articles</h1>
    <ul>
        {% for article in articles %}
            <li>
                <strong>标题:</strong> {{ article.text }} <br>
                <strong>评论数:</strong> {{ article.comments_count }} <br>
                <strong>点赞数:</strong> {{ article.likes }} <br>
                <strong>浏览量:</strong> {{ article.views|default:0 }}  <!-- 如果没有views字段,使用default显示0 -->
            </li>
        {% endfor %}
    </ul>
 
    </div>
{%endif%}
 
pattern = r'\.\/\.\./images/(.*?)\/(.*?)\)'
    # 替换字符串
    replacement = r'https://cloud.jhwww.top/index.php/s/Fyr5enMKXR2gYQW/download?path=\1&files=\2)'
    md_content = re.sub(pattern, replacement, response.text)
#由于图片存放在本地, 可以通过typora的图片复制存放的功能放到./../images文件夹下,在nextcloud中设置共享文件夹images,就可以不用api_token读取了,使用re模块改个前缀