基于Django框架的博客平台开发与实现(四)

目录

感谢

摘要

博客帖子功能实现

博客首页帖子分页显示实现

查询所有博客帖子信息

分页查询博客帖子信息

博客详情帖子页面实现

博客评论功能实现 

评论列表显示

添加评论功能实现

我的相册功能实现

后续


感谢

感谢锋哥的指导。由于我使用的是MySQL 5.7版本,因此对项目代码进行了相应的调整。详细修改过程及源代码,请参考锋哥在B站发布的视频教程:

打造Python博客系统 基于Django5+BootStrap5 视频教程 (火爆连载更新中..)_哔哩哔哩_bilibili打造Python博客系统 基于Django5+BootStrap5 视频教程 (火爆连载更新中..)共计22条视频,包括:打造Python博客系统 基于Django5+BootStrap5 视频教程 (火爆连载更新中..)、第2讲 后端架构搭建、第3讲 前端架构搭建等,UP主更多精彩视频,请关注UP账号。https://www.bilibili.com/video/BV1GJ6uYpEwK在此,也向锋哥表示诚挚的谢意!

摘要

        本项目利用Django框架,结合现代Web开发的最佳实践,构建了一个功能全面、易于扩展的博客平台。通过此项目,开发者可以学习到如何使用Django进行模型设计、视图逻辑编写、模板渲染以及静态文件管理等核心技能,同时掌握了用户认证、文章管理等博客系统必备功能的实现方法。 

项目代码地址:

Vlog_systemGitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode.com/m0_50313048/Vlog_system/tree/master上一篇:

基于Django框架的博客平台开发与实现(三)-优快云博客https://blog.youkuaiyun.com/m0_50313048/article/details/146297896

博客帖子功能实现

博客首页帖子分页显示实现

查询所有博客帖子信息

article / models.py 新建帖子类:

# from django.utils import timezone
class Article(models.Model):
    """
    博客帖子实体
    """
    id = models.AutoField(primary_key=True)
    title = models.CharField('标题', max_length=100)
    type = models.ForeignKey(ArticleType, on_delete=models.CASCADE, verbose_name='帖子类别')
    content = models.CharField('内容', max_length=1000)
    author = models.ForeignKey(MyUser, on_delete=models.CASCADE, verbose_name='用户')
    image = models.ImageField('文章图片', blank=True, upload_to='article/')
    reads = models.IntegerField('阅读量', default=0)
    abstract = models.CharField('摘要', max_length=300)
    create_time = models.DateTimeField('创建时间', default=timezone.now)
    update_time = models.DateTimeField('更新时间', auto_now=True)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = '博客帖子管理'
        verbose_name_plural = '博客帖子管理'

再通过makemigrations,migrate,生成数据库表,

makemigrations article
migrate

 新建查询,输入以下sql代码:

INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`,`create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('1','1','文字是心灵的港湾,是我们与世界相连接的桥梁。在文字的世界里,我们可以感受到历史的沧桑,体味生活的美好。文字是心灵的港湾,是我们与世界相连接的桥梁。在文字的世界里,我们可以感受到历史的沧桑,体味生活的美好。文字是心灵的港湾,是我们与世界相连接的桥梁。在文字的世界里,我们可以感受到历史的沧桑,体味生活的美好。文字是心灵的港湾,是我们与世界相连接的桥梁。在文字的世界里,我们可以感受到历史的沧桑,体味生活的美好。文字是心灵的港湾,是我们与世界相连接的桥梁。在文字的世界里,我们可以感受到历史的沧桑,体味生活的美好。','article/11.png','38','2024-12-04 15:50:55.000000','2024-12-03 15:50:55.000000','1','1','文字是心灵的港湾,是我们与世界相连接的桥梁。');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`,`create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('2','1','2','article/22.jpg','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`,`create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('3','2','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`,`create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('4','3','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`) VALUES('5','是的','2','','1','2024-12-01 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('6','5','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('7','6','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('8','7','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('9','8','好啊是的','','2','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','1','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('10','9','2','','1','2024-12-02 15:56:24.000000','2024-12-03 15:56:24.000000','1','2','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('11','10','2','','1','2024-12-03 15:56:24.000000','2024-12-03 15:56:24.000000','1','2','11');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('12','1','<p>1</p>','','2','2024-12-17 03:26:00.000000','2024-12-17 03:27:26.235658','1','2','1');
INSERT INTO `article_article` (`id`, `title`, `content`, `image`, `reads`, `create_time`, `update_time`, `author_id`, `type_id`, `abstract`)
VALUES('15','带儿子去看植物','<p>太牛逼了。</p>\r\n\r\n<p><img alt=\"\"
src=\"/media/article_images/2024/12/18/login-background.jpg\"
style=\"height:394px; width:700px\" /></p>','article/login-background.jpg','9','2024-12-18 00:18:00.000000','2024-12-18 00:23:33.002701','1','3','超大的仙人掌');

article / views.py 实现下article方法:

from article.models import Article
def article(request, id, page, typeId):
    """
    查询帖子信息
    :param request:
    :return:
    """
    print(id, page, typeId)
    if typeId == None or typeId == 0:
        articleList = Article.objects.filter(author_id=id).order_by('-create_time')
    else:
        articleList = Article.objects.filter(author_id=id, type_id=typeId).order_by('-create_time')
    return render(request, 'article.html', locals())

 媒体资源和静态资源请求重写设置,项目urls.py里加下:

# from django.urls import re_path
# from Vlog_system import settings
# from django.views.static import serve
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
    re_path('static/(?P<path>.*)', serve, {'document_root': settings.STATIC_ROOT}, name='static'),

 在media文件夹下新建文件夹article,加入三个图片:11.png 、22.jpg 、login-backeground.jpg;

 templates下重写article.html:

{% extends "base.html" %}
{% load static %}
{% block content %}
    <div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/list_icon.png' %}"/>
            博客列表
        </div>
        <div class="datas">
            {% if not articleList %}
                <p style="text-align: center;padding-top: 10px">未查询到结果!</p>
            {% else %}
                <ul>
                    {% for article in articleList %}
                        <li style="margin-bottom: 30px">
                            <span class="date">
                                <a href="">{{ article.create_time | date:'Y年m月d日' }}</a>
                            </span>
                            <span class="title">
                                <a href="">{{ article.title }}</a>
                            </span>
                            <span class="summary">{{ article.abstract }}</span>
                            <span class="img">
                                {% if article.image %}
                                    <img src="{{ article.image.url }}">
                                {% endif %}
                            </span>
                            <span class="info">发表于 {{ article.create_time | date:'Y-m-d H:i' }} 阅读({{ article.reads }})</span>
                        </li>
                        <hr style="height:5px;border:none;border-top:1px dashed gray;padding-bottom: 10px;"/>
                    {% endfor %}
                </ul>
            {% endif %}
        </div>
    </div>
{% endblock %}

 

 

分页查询博客帖子信息

通过Paginator实现分页;

article/views.py修改article函数

from django.shortcuts import redirect
from user.models import MyUser
from django.urls import reverse
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

def article(request, id, page, typeId):
    """
    查询帖子信息
    :param request:
    :return:
    """
    print(id, page, typeId)
    pageSize = 3  # 每页大小,默认为3个,3个看着最顺眼
    user = MyUser.objects.filter(id=id).first()
    if not user:
        return redirect(reverse('toRegisterPage'))

    if typeId == None or typeId == 0:
        articleList = Article.objects.filter(author_id=id).order_by('-create_time')
    else:
        articleList = Article.objects.filter(author_id=id, type_id=typeId).order_by('-create_time')
    paginator = Paginator(articleList, pageSize)
    try:
        pageData = paginator.page(page)  # 获取一页数据
    except PageNotAnInteger:
        pageData = paginator.page(1)  # 如果前端传来的页码不是整型,则返回第一页数据
    except EmptyPage:
        pageData = paginator.page(paginator.num_pages)  # 如果前端传来的页码超过实际页数,则返回最后一页数据
    return render(request, 'article.html', locals())

结合bootstrap5提供的分页组件以及分页组件自带的属性实现前端分页显示: 分页(Pagination) · Bootstrap v5 中文文档 v5.3 | Bootstrap 中文网

article.html

 

{% extends "base.html" %}
{% load static %}
{% block content %}
    <div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/list_icon.png' %}"/>
            博客列表
        </div>
        <div class="datas">
            {% if not pageData.object_list %}
                <p style="text-align: center;padding-top: 10px">未查询到结果!</p>
            {% else %}
                <ul>
                    {% for article in pageData.object_list %}
                        <li style="margin-bottom: 30px">
                            <span class="date">
                                <a href="">{{ article.create_time | date:'Y年m月d日' }}</a>
                            </span>
                            <span class="title">
                                <a href="">{{ article.title }}</a>
                            </span>
                            <span class="summary">{{ article.abstract }}</span>
                            <span class="img">
                                {% if article.image %}
                                    <img src="{{ article.image.url }}">
                                {% endif %}
                            </span>
                            <span class="info">发表于 {{ article.create_time | date:'Y-m-d H:i' }} 阅读({{ article.reads }})</span>
                        </li>
                        <hr style="height:5px;border:none;border-top:1px dashed gray;padding-bottom: 10px;"/>
                    {% endfor %}
                </ul>
            {% endif %}
        </div>
    </div>

    <div>
        <nav aria-label="...">
            <ul class="pagination">
                {% if pageData.has_previous %}
                    <li class="page-item">
                        <a class="page-link"
                        href="{% url 'article' id pageData.previous_page_number typeId %}">上一页</a>
                    </li>
                {% endif %}
                {% if pageData.object_list %}
                    {% for page in pageData.paginator.page_range %}
                        {% if pageData.number == page %}
                            <li class="page-item active" aria-current="page">
                                <a class="page-link" href="{% url 'article' id page typeId %}">{{ page }}</a>
                            </li>
                        {% else %}
                            <li class="page-item">
                                <a class="page-link" href="{% url 'article' id page typeId %}">{{ page }}</a>
                            </li>
                        {% endif %}
                    {% endfor %}
                {% endif %}
                {% if pageData.has_next %}
                    <li class="page-item">
                        <a class="page-link" href="{% url 'article' id pageData.next_page_number typeId %}">下一页</a>
                    </li>
                {% endif %}
            </ul>
        </nav>
    </div>

{% endblock %}

 

博客详情帖子页面实现

article / views.py 实现details方法:

def detail(request, id, aId):
    """
    根据用户id和帖子id查看详细信息
    :param request:
    :param id: 作者id
    :param aId: 帖子id
    :return:
    """
    article = Article.objects.filter(id=aId).first()
    return render(request, 'detail.html', locals())

templates下新建detail.html

 

{% extends "base.html" %}
{% load static %}
{% block content %}
    <div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/blog_show_icon.png' %}"/>
            博客信息
        </div>
        <div>
            <div class="blog_title">
                <h3><strong>{{ article.title }}</strong></h3>
            </div>
            <div class="blog_info">
                作者:{{ user.name }}&nbsp;&nbsp;发布时间:『 {{article.create_time|date:'Y-m-d H:i' }}』&nbsp;&nbsp;阅读({{ article.reads }})
            </div>
            <div class="blog_content">
                {{ article.content | safe }}
            </div>
        </div>
    </div>
{% endblock %}

safe过滤器可以转移html标签。

article / urls.py 增加映射

# from article.views import detail
path('detail/<int:id>/<int:aId>.html', detail, name="detail"),

article.html 加上帖子详情的链接 {% url 'detail' id article.id %} :

点击测试:

阅读量统计功能通过Django ORM的F()表达式实现原子性更新。在帖子视图处理方法中执行Article.objects.filter(id=aId).update(reads=F('reads')+1),该操作在数据库层面直接对reads字段执行自增运算。这种基于查询表达式的更新方式避免了传统"读取-修改-写入"模式可能引发的竞争条件,同时消除了数据加载到Python层的性能损耗,确保高并发场景下的计数准确性。

article/views.py

# from django.db.models import F
# 阅读量加1
Article.objects.filter(id=aId).update(reads=F('reads') + 1)

博客评论功能实现 

评论列表显示

article / models.py 新建留言类Comment:

class Comment(models.Model):
    """
    博客帖子评论实体
    """
    id = models.AutoField(primary_key=True)
    article = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name='所属文章')
    user = models.CharField('评论用户', max_length=60)
    content = models.TextField('评论内容')
    create_time = models.DateTimeField('创建时间', default=timezone.now)
    author = models.ForeignKey(MyUser, on_delete=models.CASCADE, verbose_name='帖子作者')
    def __str__(self):
        return self.content
    class Meta:
        verbose_name = '评论管理'
        verbose_name_plural = '评论管理'

再通过makemigrations,migrate,生成数据库表,

makemigrations article
migrate

以及添加以下数据:

INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('1','jack','11111','2024-12-06 17:34:16.000000','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('2','张三','222','2024-12-06 17:34:58.000000','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('3','匿名用户','11','2024-12-06 13:04:21.494838','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('4','匿名用户','3232','2024-12-06 13:05:40.925858','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('5','匿名用户','eewew','2024-12-06 00:00:00.000000','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('6','匿名用户','方式电风扇','2024-12-06 21:08:18.300357','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('7','11','11','2024-12-13 18:06:34.000000','1','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('8','11','牛逼','2024-12-28 17:22:27.041900','15','1');
INSERT INTO `article_comment` (`id`, `user`, `content`, `create_time`, `article_id`, `author_id`) VALUES('9','666','不错!','2024-12-28 18:05:42.221089','15','1');

article / views.py / detail方法,增加博客评论信息获取功能:

from article.models import Comment
def detail(request, id, aId):
    """
    根据用户id和帖子id查看详细信息
    :param request:
    :param id: 作者id
    :param aId: 帖子id
    :return:
    """
    article = Article.objects.filter(id=aId).first()
    # 阅读量加1
    Article.objects.filter(id=aId).update(reads=F('reads') + 1)
    # 获取博客评论信息
    commentList = Comment.objects.filter(article_id=aId).order_by('-create_time')
    return render(request, 'detail.html', locals())

detail.html 增加 评论列表信息显示(这里贴上整个修改后的html代码):

{% extends "base.html" %}
{% load static %}
{% block content %}
    <div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/blog_show_icon.png' %}"/>
            博客信息
        </div>
        <div>
            <div class="blog_title">
                <h3><strong>{{ article.title }}</strong></h3>
            </div>
            <div class="blog_info">
                作者:{{ user.name }}&nbsp;&nbsp;发布时间:『 {{article.create_time|date:'Y-m-d H:i' }}』&nbsp;&nbsp;阅读({{ article.reads }})
            </div>
            <div class="blog_content">
                {{ article.content | safe }}
            </div>
        </div>
    </div>
    <div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/comment_icon.png' %}"/>
            评论信息
        </div>
        <div class="commentDatas">
            {% if not commentList %}
                暂无评论
            {% else %}
                {% for comment in commentList %}
                    <div class="comment">
                        <span><font>{{ forloop.counter }}楼
                        &nbsp;&nbsp;&nbsp;&nbsp;{{ comment.user }}:</font>{{ comment.content}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;{{ comment.create_time|date:"Y-m-d H:i" }}&nbsp;]</span>
                    </div>
                {% endfor %}
            {% endif %}
        </div>
    </div>
{% endblock %}

添加评论功能实现

要实现添加评论的功能, 我们可以通过HTTP方法分派实现视图复用的方法实现这个功能。即在detail视图函数中,根据请求类型进行逻辑分支处理——响应GET请求时展示数据列表,处理POST请求时执行新增操作。

article / views.py / detail方法

import datetime
def detail(request, id, aId):
    """
    根据用户id和帖子id查看详细信息
    :param request:
    :param id: 作者id
    :param aId: 帖子id
    :return:
    """
    if request.method == 'GET':  # 查询帖子信息
        article = Article.objects.filter(id=aId).first()
        # 阅读量加1
        Article.objects.filter(id=aId).update(reads=F('reads') + 1)
        # 获取博客评论信息
        commentList = Comment.objects.filter(article_id=aId).order_by('-create_time')
        return render(request, 'detail.html', locals())
    else:  # 添加评论信息
        user = request.POST.get("user")
        content = request.POST.get("content")
        value = {'user': user, 'content': content, 'article_id': aId,
                 'create_time': datetime.datetime.now(),
                 'author_id': id}
        Comment.objects.create(**value)
        kwargs = {'id': id, 'aId': aId}
        return redirect(reverse('detail', kwargs=kwargs))

detail.html 加下 提交表单,和验证js:

<div class="data_list">
        <div class="data_list_title">
            <img src="{% static 'images/publish_comment_icon.png' %}"/>
            发表评论
        </div>
        <div class="publish_comment">
            <form action="" method="post" onsubmit="return checkForm()">
                {% csrf_token %}
                <div style="padding: 5px">
                    用户:<input type="text" id="user" name="user" value="匿名用户">
                </div>
                <div>
                    <textarea style="width: 100%" rows="3" id="content" name="content"
                    placeholder="来说两句吧..."></textarea>
                </div>
                <div class="publishButton">
                    <button class="btn btn-primary" type="submit">发表评论</button>
                </div>
            </form>
        </div>
    </div>
{% block script %}
    <script>
        function checkForm() {
            var user = $("#user").val();
            var content = $("#content").val();
            if (content == null || content == '') {
                alert("请输入评论内容!");
                return false;
            } else if (user == null || user == '') {
                alert("请填写用户!");
                return false;
            }
            return true;
        }
    </script>
{% endblock %}

测试一下:

我的相册功能实现

 我们会发现,这个我的相册功能,右侧和其他模块不一样。所以我们开发的话,可以在建一个公共父类 模版,base2.html

<!DOCTYPE html>
<html lang="en">
    <head>
        {% load static %}
        <meta charset="UTF-8">
        <title>{% block title %}博客首页{% endblock %}-Powered by python222</title>
        <link href="{% static "bootstrap-5.3.3/css/bootstrap.css" %}" rel="stylesheet"/>
        <link href="{% static "css/blog.css" %}" rel="stylesheet"/>
        <script src="{% static "bootstrap-5.3.3/js/bootstrap.js" %}"></script>
        <script src="{% static "js/jquery-1.11.2.min.js" %}"></script>
    </head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-4">
            <img style="width: 326px;height: 60px" alt="开源博客系统" src="{% static "images/screenshot-logo.png" %}">
        </div>
        <div class="col-md-8">
            <iframe style="float: right;" width="400" scrolling="no" height="60" frameborder="0" allowtransparency="true" src="http://i.tianqi.com/index.php?c=code&id=12&icon=1&num=5"></iframe>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12" style="padding-top: 10px;padding-bottom: 10px">
            <nav class="navbar navbar-expand-lg bg-body-tertiary">
                <div class="container-fluid">
                    <a class="navbar-brand" href="{% url 'article' id 1 0 %}">博客首页</a>
                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <div class="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                            <li class="nav-item">
                                <a class="nav-link" href="{% url 'album' id 1%}">我的相册</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="">关于我</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="">留言</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="">博客后台管理</a>
                            </li>
                        </ul>
                        <form class="d-flex" role="search" method="post" action="" onsubmit="return checkSearchForm()">
                    {% csrf_token %}
                        <input class="form-control me-2" type="search" placeholder="请输入搜索内容..." aria-label="Search" name="v" id="v" value="{{v }}">
                        <button class="btn btn-outline-success" type="submit">Search</button>
                    </form>
                    </div>
                </div>
            </nav>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            {% block content %}{% endblock %}
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <div align="center" style="padding-top: 120px">
            <span style="float: left;">Powered by <a href="http://python222.com" target="_blank">小龙ssss</a></span>
            Copyright © 2023-2025 小龙ssss 版权所有
            </div>
        </div>
    </div>
</div>
{% block script %}{% endblock %}
<script>

    function checkSearchForm() {
        var v = $("#v").val();
        if (v == null || v == '') {
        alert("请输入搜索内容!");
        return false;
        }
        return true;
    }
</script>
</body>
</html>

 album / models.py 新建相册类:

from django.db import models
from user.models import MyUser


class AlbumInfo(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(MyUser, on_delete=models.CASCADE, verbose_name='用户')
    title = models.CharField('标题', max_length=50, blank=True)
    introduce = models.CharField('描述', max_length=200, blank=True)
    photo = models.ImageField('图片', blank=True, upload_to='album/')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = '图片墙管理'
        verbose_name_plural = '图片墙管理'

 再通过makemigrations,migrate,生成数据库表,

makemigrations album
migrate album

 以及添加下数据:

INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('1','图片1','图片1介绍','album/1.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('2','图片2','图片2介绍','album/2.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('3','图片3','图片3介绍','album/3.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('4','图片4','图片4介绍','album/4.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('5','图片5','图片5介绍','album/5.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('6','图片6','图片6介绍','album/6.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('7','图片7','图片7介绍','album/7.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('8','图片8','图片8介绍','album/8.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('9','图片9','图片9介绍','album/9.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('10','图片10','图片10介绍','album/10.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('11','图片11','图片11介绍','album/11.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('13','1','2','album/33.jpg','1');
INSERT INTO `album_albuminfo` (`id`, `title`, `introduce`, `photo`, `user_id`) VALUES('14','我去1','不从啊','album/55.jpg','1');

 album / views.py 新建album方法,处理页面请求:

from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.shortcuts import render
from album.models import AlbumInfo


def album(request, id, page):
    """
    分页查询查询图片墙信息
    :param request:
    :return:
    """
    pageSize = 6  # 每页大小
    albumList = AlbumInfo.objects.filter(user_id=id)
    paginator = Paginator(albumList, pageSize)
    try:
        pageData = paginator.page(page)  # 获取一页数据
    except PageNotAnInteger:
        pageData = paginator.page(1)  # 如果前端传来的页码不是整型,则返回第一页数据
    except EmptyPage:
        pageData = paginator.page(paginator.num_pages)  # 如果前端传来的页码超过实际页数,则返回最后一页数据
    return render(request, 'album.html', locals())

 album / urls.py 加下映射:

from django.urls import path
from album.views import album
urlpatterns = [
    # 相册列表
    path('<int:id>/<int:page>.html', album, name='album'),
]

 项目本身的urls.py的urlpatterns加上:

path('album/', include('album.urls')), # 相册模块

 templates下新建album.html,注意,是继承base2.html模版

 

{% extends "base2.html" %}
{% block title %}相册{% endblock %}
{% load static %}
{% block content %}
    <div class="row" style="padding: 10px">
        {% for album in pageData.object_list %}
            <div class="col-md-2">
                <i><img style="width: 200px;height: 200px" src="{{album.photo.url }}"></i>
                <div style="padding: 3px">
                    <h5 style="border-bottom: #ccc 1px solid;padding-top:10px;padding-bottom: 5px">
                        <strong>{{ album.title }}</strong>
                    </h5>
                    <span>{{ album.introduce }}</span>
                </div>
            </div>
        {% endfor %}
    </div>
    <div class="row">
        <nav aria-label="...">
            <ul class="pagination" style="justify-content: center;padding-top:20px">
                {% if pageData.has_previous %}
                    <li class="page-item">
                        <a class="page-link" href="{% url 'album' id pageData.previous_page_number %}">上一页</a>
                    </li>
                {% endif %}
                {% if pageData.object_list %}
                    {% for page in pageData.paginator.page_range %}
                        {% if pageData.number == page %}
                            <li class="page-item active" aria-current="page">
                                <a class="page-link" href="{% url 'album' id page %}">{{ page }}</a>
                            </li>
                        {% else %}
                            <li class="page-item"><a class="page-link" href="{% url 'album' id page %}">{{ page }}</a>
                            </li>
                        {% endif %}
                    {% endfor %}
                {% endif %}
                {% if pageData.has_next %}
                    <li class="page-item">
                        <a class="page-link" href="{% url 'album' id pageData.next_page_number %}">下一页</a>
                    </li>
                {% endif %}
            </ul>
        </nav>
    </div>
{% endblock %}

 base.html和base2.html模版我的相册菜单链接都改成url调用: {% url 'album' id 1 %}

 

 成功!

后续

持续开发中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值