Django搭建个人博客Blog-Day05

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

创建文章模块

创建文章app
  1. 在虚拟环境中apps路径下使用如下代码:

# 进入虚拟环境
workon wsl
# 进入要创建app的路径下
cd blog/blog/apps
# 创建app
python ../../manage.py startapp articles
  1. 将articles注册进配置文件dev.py中的INSTALLED_APPS

INSTALLED_APPS = [
    ...
    'articles',
]
  1. 创建数据模型在blog/blog/apps/articles/models.py文件中添加如下代码

from django.db import models

from user.models import BaseModel
from user.models import User

# 创建数据模型
# 博客文章数据模型    应该有哪些字段?
# 
class Articles(BaseModel):  # BaseModel  
    # 文章正文内容   TextField
    body = models.TextField(verbose_name='正文')
    # 文章标题      CharField
    title = models.CharField(max_length=100,verbose_name='标题')
    # 文章封面图片  ImageField
    avatar = models.ImageField(upload_to='articles/%Y%m%d/',verbose_name='文章封面')
    # 文章摘要      CharField
    desc  =models.CharField(max_length=255,verbose_name='文章摘要')
    # 文章的浏览量   IntegerField
    read_num = models.IntegerField(verbose_name='文章浏览量',default=0)
    # 文章的作者    外键   文章是多的   用户是一的    外键字段写在哪一方? 多的这一方
    author = models.ForeignKey(User,on_delete=models.CASCADE)
    # 文章的专栏    CharField    外键字段    专栏表  一对多  多  
    column = models.ForeignKey('Column',on_delete=models.CASCADE)
    
    class Meta:
        db_table = 'blog_articles'
        verbose_name = '文章'
        verbose_name_plural = verbose_name
    
class Column(BaseModel):
    # 专栏的名字
    title = models.CharField(max_length=100, verbose_name='专栏标题')
    
    class Meta:
        db_table = 'blog_column'
        verbose_name = '专栏'
        verbose_name_plural = verbose_name
        
    def __str__(self):
        # 打印一个对象的时候
        return self.title
  1. 执行数据库迁移生成对应的数据表(在虚拟环境中manage.py文件下

python manage.py makemigrations
python manage.py migrate
将文章模块中的数据模型加入后台管理
  1. 在admin.py文件中添加如下代码:

from django.contrib import admin
from articles.models import Articles,Column

# Register your models here.
class ArticlesAdmin(admin.ModelAdmin):
    list_display = ['title','author','create_time']
    # 想通过作者来搜索 ==》 通过作者的名字来搜索  ===》
    search_fields = ['title','author__username']

class ColumnAdmin(admin.ModelAdmin):
    list_display = ['title','create_time']
    # 想通过作者来搜索 ==》 通过作者的名字来搜索  ===》
    search_fields = ['title']

# 将原来的数据模型和ModelAdmin结合起来
admin.site.register(Articles,ArticlesAdmin)
admin.site.register(Column,ColumnAdmin)
  1. 在apps.py文件中添加如下代码:

from django.apps import AppConfig

class ArticlesConfig(AppConfig):
    name = 'articles'
    verbose_name = '文章管理'
  1. 在__init__.py文件中添加如下代码:

default_app_config = 'articles.apps.ArticlesConfig'

实现创建文章

  1. 写路由(总路由

from django.contrib import admin
from django.urls import path,include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    # 进行路由分发
    path('user/',include('user.urls')),
    path('password-reset',include('password_reset.urls')),
    path('',include('articles.urls')),
]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
  1. 在articles文件夹下创建urls.py文件添加如下代码用作路由分发:

from django.urls import path

from . import views

app_name = 'articles'

urlpatterns = [
    # 创建文章
    path('create',views.Create.as_view(),name='create'),
    path('index',views.index,name='index'),
]
  1. 写视图(view.py

from django.http import HttpResponse
from django.shortcuts import render,redirect,reverse

from user.views import LoginRequired
from articles.models import Column,Articles

# 继承LoginRequired   只有用户登录了以后才能访问
class Create(LoginRequired):
    # 展示创建文章的html页面
    def get(self,requests):
        # 先查出来所有的专栏展示在html页面中让用户去勾选
        columns = Column.objects.all()
        return render(requests,'articles/create.html',locals())

    # 实现创建文章的功能逻辑
    def post(self,requests):
        # 接受请求数据
        title = requests.POST.get('title')
        desc = requests.POST.get('desc')
        body = requests.POST.get('body')
        column = requests.POST.get('column')
        # 用户  就是当前登录的用户
        author = requests.user
        # 封面图  文件是通过FILES接受的
        avatar = requests.FILES.get('avatar')
        # 数据入库
        try:
            Articles.objects.create(author=author,title=title,body=body,desc=desc,avatar=avatar,column_id=column)
            # 返回结果
            return redirect(reverse('articles:index'))
        except Exception as err:
            return render(requests,'articles/create.html',{'errmsg':'请选择专栏'})


def index(request):
    return HttpResponse('首页')
  1. 在templates/目录下创建articles/create.html并添加如下代码:

{% extends 'base.html' %}
{% block title %}创建文章{% endblock title %}
{% block content %}
    <div class="container">
        <div class="row">
            <div class="clo-12">
                <form action="" method="post" enctype="multipart/form-data">
                    {% csrf_token %}
                    <!--文章标题 -->
                    <div class="form-group">
                        <label for="title">文章标签</label>
                        <input type="text" class="form-control" id="title" name="title">
                    </div>
                    <!--文章专栏 -->
                    <div class="form-group">
                        <label for="column">文章专栏</label>
                        <select name="column" id="column" class="form-control">
                            <option value="none">请选择专栏</option>
                            {% for column in columns %}
                                <option value="{{ column.id }}">{{ column.title }}</option>
                            {% endfor %}
                        </select>
                    </div>
                    <!--文章摘要 -->
                    <div class="form-group">
                        <label for="desc">文章摘要</label>
                        <input type="text" class="form-control" id="desc" name="desc">
                    </div>
                    <!--文章图片 -->
                    <div class="form-group">
                        <label for="avatar">文章封面</label>
                        <input type="file" class="form-control" id="avatar" name="avatar">
                    </div>
                    <!--文章正文 -->
                    <div class="form-group">
                        <label for="body">文章正文</label>
                        <textarea class="form-control" name="body" id="body" cols="30" rows="10"></textarea>
                    </div>
                    <!--提交按钮 -->
                    <button type="submit" class="btn btn-success">完成</button>
                </form>
            </div>
        </div>
    </div>
<!--展示错误信息 -->
    {% if errmsg %}
        <div class="alert alert-danger alert-dismissible">
        <strong>错误</strong>{{ errmsg }}
        </div>
    {% endif %}
{% endblock content %}

实现修改文章

  1. 写视图(view.py

class Update(LoginRequired):
    # 展示创建文章的html页面
    def get(self,requests,id):
        # 先查出来要修改的文章   展示在html中
        article = get_object_or_404(Articles,pk=id)
        # 先查出来所有的专栏展示在html页面中让用户去勾选
        columns = Column.objects.all()
        return render(requests,'articles/update.html',locals())

    # 实现创建文章的功能逻辑
    def post(self,requests,id):
        # 对指定的文章进行修改
        # 1. 先查出文章
        article = get_object_or_404(Articles, pk=id)
        # 2. 判断文章的作者是不是登录的用户是则能修改不是就不能修改
        if requests.user == article.author:
            # 接受数据
            article.title = requests.POST.get('title')
            article.desc = requests.POST.get('desc')
            article.body = requests.POST.get('body')
            column = requests.POST.get('column')
            avatar = requests.FILES.get('avatar')
            if avatar:
                article.avatar = avatar
            # 专栏是外键字段
            article.column  =get_object_or_404(Column,pk=column)
            # 数据入库
            article.save()
            # 返回结果
            return redirect(reverse('articles:index'))
        return HttpResponse('不能修改其他作者的文章')
  1. 写路由(articles/urls.py

from django.urls import path
from . import views

app_name = 'articles'
urlpatterns = [
    # 创建文章
    path('create',views.Create.as_view(),name='create'),
    path('update/<int:id>',views.Update.as_view(),name='update'),
    path('index',views.index,name='index'),
]
  1. 在templates/articles/文件夹下创建update.html文件添加如下代码:

{% extends "base.html" %}
{% block title %} 更新文章 {% endblock title %}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-12">
            <br>
            <form method="post" action="" enctype="multipart/form-data">
                {% csrf_token %}
                <div class="form-group">
                    <label for="title">文章标题</label>
                    <!-- 在 value 属性中指定文本框的初始值为旧的内容即 article 对象中的 title 字段 -->
                    <input type="text" class="form-control" id="title" name="title" value="{{ article.title }}">
                </div>
                <!-- 文章栏目 -->
                <div class="form-group">
                    <label for="column">栏目</label>
                    <select class="form-control"  id="column" name="column">
                            <option value="none">请选择栏目..</option>
                        {% for column in columns %}
                            <option value="{{ column.id }}"
                                {% if column.id == article.column.id %}
                                    selected
                                {% endif %}
                            >
                                {{ column }}
                            </option>
                        {% endfor %}
                    </select>
                </div>
            <div class="form-group">
                <!-- avatar -->
                    <label for="avatar">文章图片</label>
                <!-- 有封面则展示封面 -->
            {% if article.avatar %}
                <img src="{{ article.avatar.url }}" style="max-width: 20%; border-radius: 15%;" class="col-md-4">
                <input type="file" class="form-control-file" name="avatar" id="avatar">
            {% else %}
                <h5 class="col-md-4">请上传文章图片</h5>
                <input type="file" class="form-control-file" name="avatar" id="avatar">
            {% endif %}
            <!-- 有头像则展示头像 -->

            </div>
                <!-- 文章摘要 -->
                <div class="form-group">
                    <!-- 标签 -->
                    <label for="desc">文章摘要</label>
                    <!-- 文本框 -->
                    <input type="text" class="form-control" id="desc" name="desc" value="{{ article.desc }}">
                </div>

                <div class="form-group">
                    <label for="body">文章正文</label>
                    <!-- 文本域不需要 value 属性直接在标签体中嵌入数据即可 -->
                    <textarea type="text" class="form-control" id="body" name="body" rows="12">{{ article.body }}</textarea>
                </div>
                <button type="submit" class="btn btn-primary">完成</button>
            </form>
        </div>
    </div>
</div>
{% endblock content %}

实现删除文章

  1. 写视图(view.py

def delete(requests,id):
    # 1. 先根据ID查出文章
    article = get_object_or_404(Articles, pk=id)
    # 2. 判断当前登录用户是不是作者
    if requests.user == article.author:
        # 3. 如果是作者就删除文章 数据入库
        article.delete()
        return redirect(reverse('articles:index'))
    # 4. 如果不是作者就提示不能删
    return HttpResponse('不能删除其他作者的文章')
  1. 写路由(urls.py

from django.urls import path
from . import views

app_name = 'articles'
urlpatterns = [
    # 创建文章
    path('create',views.Create.as_view(),name='create'),
    path('update/<int:id>',views.Update.as_view(),name='update'),
    path('delete/<int:id>',views.delete,name='delete'),
    path('index',views.index,name='index'),
]

展示所有文章

基础版本(无分页

  1. 写视图(view.py

def index(request):
    # 获取所有的文章再展示在html页面中
    articles = Articles.objects.all()
    return render(request,'articles/index.html',locals())
  1. 写路由(总路由

from django.urls import path,include
from django.conf.urls.static import static
from django.conf import settings

from articles.views import index

urlpatterns = [
    path('',index,name='index'),
    path('admin/', admin.site.urls),
    # 进行路由分发
    path('user/',include('user.urls')),
    path('password-reset',include('password_reset.urls')),
    path('',include('articles.urls')),
]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
  1. 写路由(articles/urls.py

from django.urls import path
from . import views

app_name = 'articles'
urlpatterns = [
    # 创建文章
    path('create',views.Create.as_view(),name='create'),
    path('update/<int:id>',views.Update.as_view(),name='update'),
    path('delete/<int:id>',views.delete,name='delete'),
    # 展示所有的博文
    path('index',views.index,name='index'),
]
  1. 在templates/articles/文件夹下创建index.html文件并添加如下代码:

{% extends "base.html" %}
{% block title %} 博客正文 {% endblock title %}
{% block content %}
    <div class="container">
    <div class="col-12">
        <div class="row mt-2">
            {% for article in articles %}
                <!-- 封面图-->
                {% if article.avatar %}
                    <div class="col-3">
                    <img src="{{ article.avatar.url }}" alt="avatar" style="max-width: 100%;border-radius:20px ">
                    </div>
                {% endif %}
                <!-- 文章内容-->
                <div class="col">
                    <!-- 文章栏目-->
                    <button type="button" class="btn btn-sm mb-2 btn-success">{{ article.column }}</button>
                    <!-- 文章标题-->
                    <h4>
                        <b>
                            <a href="{% url 'articles:detail' article.id %}">{{ article.title }}</a>
                        </b>
                    </h4>
                    <!-- 文章摘要-->
                    <div>
                        <p style="color: gray;">
                            {% if article.desc %}
                                {{ article.desc }}
                                {% else %}
                                还没有摘要
                            {% endif %}
                        </p>
                    </div>
                    <!-- 其他信息-->
                <p>
                    <span style="color: green">
                        作者:{{ article.author }}&nbsp;&nbsp;&nbsp;
                    </span>
                    <span style="color: green">
                        浏览量:{{ article.read_num }}&nbsp;&nbsp;&nbsp;
                    </span>
                    <span style="color: green">
                        发布时间:{{ article.create_time|date:'Y-m-d' }}&nbsp;&nbsp;&nbsp;
                    </span>
                    <span style="color: green">
                        更新时间:{{ article.update_time|date:'Y-m-d' }}&nbsp;&nbsp;&nbsp;
                    </span>
                </p>
                </div>
                <hr style="width: 100%;">
            {% endfor %}


        </div>
    </div>
    </div>
{% endblock content %}

展示文章详情页

  1. 写视图(view.py

# 查看文章详情
def detail(request,id):
    # 根据文章的ID 查出对应的文章展示在html页面中
    article = get_object_or_404(Articles, pk=id)
    # 没查看一次文章 就增加一次浏览量
    article.read_num += 1
    article.save()
    return render(request,'articles/detail.html',locals())
  1. 写视图(urls.py

from django.urls import path
from . import views

app_name = 'articles'
urlpatterns = [
    # 创建文章
    path('create',views.Create.as_view(),name='create'),
    path('update/<int:id>',views.Update.as_view(),name='update'),
    path('delete/<int:id>',views.delete,name='delete'),
    # 展示所有的博文
    path('index',views.index,name='index'),
    # 查看博文详情
    path('detail/<int:id>',views.detail,name='detail'),
]
  1. 在templates/articles/文件夹下创建detail.html文件:

{% extends 'base.html' %}
{% block title %}文章详情{% endblock title %}
{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-9">
                <!--标题和作者-->
                <h1 class="mt-4 mb-4">{{ article.title }}</h1>
                <div class="alert alert-success">
                    作者:{{ article.author }}
                    创建时间:{{ article.create_time|date:'Y-m-d' }}
                    文章浏览量:{{ article.read_num }}
                    <!--如果当前登录的用户就是作者则展示删除文章和修改文章-->
                    {% if request.user == article.author %}
                        <a href="#" onclick="confirm_delete()">删除文章</a>
                        <a href="{% url 'articles:update' article.id %}">修改文章</a>
                    {% endif %}
                    <!--文章的专栏-->
                    <button type="button" class="btn btn-success btn-sm mb-2">{{ article.column }}</button>
                </div>
                <!--文章的正文-->
                <div class="col-12">
                    <p>{{ article.body }}</p>
                </div>
            </div>
        </div>
    </div>
    <script>
    //删除文章的函数
    function confirm_delete(){
        // 调用layer弹窗组件
        layer.open({
            title:"确认删除",
            content:'确认删除这篇文章吗?',
            yes:function (index,layero){
                // 指定前往的url
                location.href = '{% url "articles:delete" article.id %}'
            },
        })
    }
    </script>
{% endblock content %}
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go