博客系统项目:编码篇-基础篇-架构搭建

1 背景

在上一篇中介绍了《博客系统项目:设计篇》从整体上介绍了博客系统的设计方法和思路,本篇围绕设计出具博客系统的具体编码,设计出具后紧接着就到编码阶段,编码阶段涉及到开发环境的选择、开发语言的选型、开发框架的选型、数据库选型、IDE的选型、以及软件架构模式选型。在本篇中会集中介绍,在系统中有一个最小系统法的原则,包括我们组装计算机和器械过程中都会用到这个原则,即用最少和必要的部件以最少的时间最快的速度组装出一台计算机,加电启动,确认启动正常输出硬件信息,既可以进行后面的完整安装。

2 环境

2.1 环境说明

项目工具
开发环境Ubuntu 18.04 TLS
开发语言Python3.6.9
虚拟环境virtualenv15.1.0
开发框架Django3.2.9
数据库sqlite3
IDE集成开发环境vscode1.63.2
设计模式模型-模板-视图 MTV

2.2 模式说明

2.2.1 MTV模式

介绍一下设计模式,MTV模式是Django 的设计模式。其借鉴了MVC模式,将交互过程分为3个层次:

  • Model:数据存储层,处理所有数据相关的业务,和数据库进行交互,并提供数据的增删改查;
  • Template:模板层(也叫表现层)具体来处理页面的显示;
  • View:业务逻辑层,处理具体的业务逻辑,它的作用是连通Model 层和
    Template 。

在这里插入图片描述

  1. 用户通过浏览器对服务器发起 request 请求,服务器接收请求后,通过 View 的业务逻辑层进行分析,同时向 Model 层和Template 层发送指令;

  2. Mole 层与数据库进行交互,将数据返回给 View 层;

  3. Template层接收到指令后,调用相应的模板,并返回给 View 层;

  4. 层接收到模板与数据后,首先对模板进行渲染(即将相应的数据赋值给模板),然后组织成响应格式返回给浏览器,浏览器进行解析后并最终呈现给用户。

2.2.2 MVC

在开发领域,MVC模式是非常出门的一种设计模式,
MVC 是 Model-View-Controller 的缩写,其中每个单词都有其不同的含义:

  • Modle 代表数据存储层,是对数据表的定义和数据的增删改查;
  • View 代表视图层,是系统前端显示部分,它负责显示什么和如何进行显示;
  • Controller 代表控制层,负责根据从 View 层输入的指令来检索 Model 层的数据,并在该层编写代码产生结果并输出。 PHP语言框架中 laravel 使用的是MVC模式

在这里插入图片描述
请求与响应过程描述如下:

  1. 用户通过浏览器向服务器发起 request 请求,Controller 层接受请求后,同时向 Model 层和 View 发送指令;
  2. Mole 层根据指令与数据库交互并选择相应业务数据,然后将数据发送给 Controller 层;
  3. View 层接收到Controller 的指令后,加载用户请求的页面,并将此页面发送给 Controller 层;
  4. Controller 层接收到 Model 层和 View 层的数据后,将它们组织成响应格式发送给浏览器,浏览器通过解析后把页面展示出来。

MVC 的 3 层之间紧密相连,但又相互独立,每一层的修改都不会影响其它层,每一层都提供了各自独立的接口供其它层调用,MVC 的设计模式降低了代码之间的耦合性(即关联性),增加了模块的可重用性,这就是 MVC 的设计模式。
Laravel框架采用了MVC模式,Django采用MTV模式。

3 前置工作

编码阶段包括虚拟环境的创建、框架的安装、项目创建、应用创建、模型编写、模板引用、视图编写、运行测试。

3.1 环境搭建

查看python版本

python3 --version

Python 3.6.9
安装虚拟环境

pip install virtualenv
pip install virtualenvwrapper

创建虚拟环境

cd /code/mycode/python/project
virtualenv venv

激活虚拟环境

source venv/bin/activate

退出虚拟环境

deactivate

安装框架
进入到虚拟环境中

pip install django==3.2.9

创建项目

django-admin startproject project
cd project
python manage.py runserver

在这里插入图片描述

浏览器中输入 http://127.0.0.1:8000/
在这里插入图片描述
退出运行模式Ctrl+c

创建应用

django-admin startapp blog

全局变量
使用Visual Studio Code工具打开project文件夹
在这里插入图片描述

4 编码实现

4.1 项目调整

4.1.1 修改语言时区

project/project/settings.py

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

调整为

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True

英文调整为中文,时区UTC调整为亚洲/上海。

4.1.2 添加应用路由

新增文件

project/blog/urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name = 'index'),
]

4.1.3 添加项目路由

编辑文件

project/project/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
]

4.1.4 添加应用视图

编辑文件

project/blog/views.py

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello,You're at the blog index.")

运行查看

python manage.py runserver

浏览器中输入 http://127.0.0.1:8000/blog/
在这里插入图片描述

4.1.5 生成迁移文件

python manage.py migrate

在这里插入图片描述

4.1.6 项目中添加应用

编辑文件

project/project/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'blog.apps.BlogConfig',
]

4.2 模型

4.2.1 编辑项目模型

project/blog/models.py

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=70)
    created_date = models.DateTimeField('创建时间',auto_now_add=True)
    updated_date = models.DateTimeField('修改时间',auto_now=True)

    def __str__(self):
        return self.name
        

class Tag(models.Model):
    name = models.CharField(max_length=70)
    created_date = models.DateTimeField('创建时间',auto_now_add=True)
    updated_date = models.DateTimeField('修改时间',auto_now=True)

    def __str__(self):
        return self.name


class Article(models.Model):
    STATUS_CHOICES = (
        ('d','Draft'),
        ('p','Published'),
    )
    title = models.CharField('文章标题',max_length=70)
    description = models.CharField('摘要',max_length=255)
    content = models.TextField('文章内容')
    created_date = models.DateTimeField('创建时间',auto_now_add=True)
    updated_date = models.DateTimeField('修改时间',auto_now=True)
    author = models.CharField('文章作者',max_length=70)
    views = models.PositiveIntegerField('浏览量',default=0)
    likes = models.PositiveIntegerField('点赞数',default=0)
    topped = models.BooleanField('置顶',default=False)
    status = models.CharField('文章状态', max_length=1,choices=STATUS_CHOICES)
    image = models.CharField('文章图片',max_length=255)
    category = models.ForeignKey('Category',verbose_name='分类',null=True,on_delete=models.SET_NULL)
    tag = models.ForeignKey('Tag',verbose_name='标签',null=True,on_delete=models.SET_NULL)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-updated_date']
   
class Banner(models.Model):
    text_title = models.CharField('图片标题',max_length=50,default='')
    text_info = models.CharField('图片文本', max_length=255)
    img = models.ImageField('轮播图', upload_to='banner/')
    link_url = models.CharField('图片链接', max_length=255)
    is_active = BooleanField('图片状态',default=False)

    def __str__(self):
        return self.text_title

    class Meta:
        verbose_name = '轮播图'
        verbose_name_plural='轮播图'

4.2.2 生成模型文件

执行生成模型命令

(venv) j@T:~/code/python/project$ python manage.py makemigrations blog
Migrations for 'blog':
  blog/migrations/0001_initial.py
    - Create model Banner
    - Create model Category
    - Create model Tag
    - Create model Article

查看模型文件

blog/migrations/0001_initial.py

执行数据迁移

(venv) j@TK:~/code/python/project$ python manage.py migrate blog
Operations to perform:
  Apply all migrations: blog
Running migrations:
  Applying blog.0001_initial... OK

查看生成的数据库表

(venv) j@T:~/code/python/project$ python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Banner
--
CREATE TABLE "blog_banner" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "text_title" varchar(50) NOT NULL, "text_info" varchar(255) NOT NULL, "img" varchar(100) NOT NULL, "link_url" varchar(255) NOT NULL, "is_active" bool NOT NULL);
--
-- Create model Category
--
CREATE TABLE "blog_category" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(70) NOT NULL, "created_date" datetime NOT NULL, "updated_date" datetime NOT NULL);
--
-- Create model Tag
--
CREATE TABLE "blog_tag" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(70) NOT NULL, "created_date" datetime NOT NULL, "updated_date" datetime NOT NULL);
--
-- Create model Article
--
CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(70) NOT NULL, "description" varchar(255) NOT NULL, "content" text NOT NULL, "created_date" datetime NOT NULL, "updated_date" datetime NOT NULL, "author" varchar(70) NOT NULL, "views" integer unsigned NOT NULL CHECK ("views" >= 0), "likes" integer unsigned NOT NULL CHECK ("likes" >= 0), "topped" bool NOT NULL, "status" varchar(1) NOT NULL, "img" varchar(100) NULL, "category_id" bigint NULL REFERENCES "blog_category" ("id") DEFERRABLE INITIALLY DEFERRED, "tag_id" bigint NULL REFERENCES "blog_tag" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_article_category_id_7e38f15e" ON "blog_article" ("category_id");
CREATE INDEX "blog_article_tag_id_4c94be52" ON "blog_article" ("tag_id");
COMMIT;
(venv) j@T:~/code/python/project$ 

注册

from django.contrib import admin
from . models import Article, Tag, Banner, Category
# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,      {'fields': ['title']}),
        (None,    {'fields': ['description']}),
        (None,    {'fields': ['content']}),
        (None,    {'fields': ['author']}),
        (None,    {'fields': ['topped']}),
        (None,    {'fields': ['img']}),
        (None,    {'fields': ['status']}),
    ]
admin.site.register(Article, ArticleAdmin)

4.3 视图

4.3.1 前端视图

project/blog/views.py

from blog.models import Article, Category, Tag
from django.views.generic import ListView
import markdown2

# Create your views here.
class IndexView(ListView):
    template_name = "index.html"
    context_object_name = "article_list"
 
    def get_queryset(self):
        article_list = Article.objects.filter(status='p')
        for article in article_list:
            article.content = markdown2.markdown(article.content,)
        return article_list

    def get_context_data(self,**kwargs):
        kwargs['category_list'] = Category.objects.all().order_by('name')
        return super(IndexView,self).get_context_data(**kwargs)

在views.py文章有一个index.html文件
在project/blog目录下创建templates(存放index.html/detail.html)文件夹和static(存储css和js)文件夹,在index.html和detail.html文件中引入css和js文件。

project/blog/templates/blog/index.html

{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
 </head>
 <body>
     <script src="{% static 'js/jquery.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
  </body>
</html> 

编辑应用路由信息

/project/blog/urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('',views.IndexView.as_view(), name='index'),

浏览器中输入http://127.0.0.1:8000/blog/
在这里插入图片描述
以上信息为静态模板信息,后面需要管理后台维护到数据库信息,然后页面读取

4.3.2 后台页面

文章维护页面
在维护页面中可以对文章的内容、分类、标签、轮播图进行新增、编辑的维护管理

project/blog/admin.py

from django.contrib import admin
from . models import Article, Tag, Banner, Category
# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,      {'fields': ['title']}),
        (None,    {'fields': ['description']}),
        (None,    {'fields': ['content']}),
        (None,    {'fields': ['author']}),
        (None,    {'fields': ['img']}),
        (None,    {'fields': ['category','tag','status','topped']}),
    ]
admin.site.register(Article, ArticleAdmin)

class CategoryAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,  {'fields': ['name']}),
    ]
admin.site.register(Category,CategoryAdmin)

class TagAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,  {'fields': ['name']}),
    ]
admin.site.register(Tag,TagAdmin)

class BannerAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,  {'fields': ['text_title']}),
        (None,  {'fields': ['text_info']}),
        (None,  {'fields': ['img']}),
        (None,  {'fields': ['link_url']}),
        (None,  {'fields': ['is_active']}),
    ]
admin.site.register(Banner,BannerAdmin)

后台页面显示
执行

python manage.py runserver

浏览器中输入http://127.0.0.1:8000/admin/
输入创建的管理员账号
登录后首页
在这里插入图片描述
文章维护页面
在这里插入图片描述

分类页面
在这里插入图片描述

标签页面
在这里插入图片描述

轮播图页面
在这里插入图片描述

手动后台维护分类、标签和文章信息。

原计划把编码整个在一篇中介绍,写了一部分后篇幅原因,随一分为二,下一篇中着手介绍视图读取数据库信息。

参考链接

Django博客开发教程
django 博客开发(一)
Django博客开发实战:开篇

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值