基于.NetCore开发博客项目 StarBlog - (3) 模型设计

系列文章

  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?

  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目

  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计

  • ...

  • 基于.NetCore开发博客项目 StarBlog - 接口返回值包装

  • 基于.NetCore开发博客项目 StarBlog - 上传图片功能

  • 基于.NetCore开发博客项目 StarBlog - 身份认证功能

  • 基于.NetCore开发博客项目 StarBlog - 前端相关

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (1) 准备篇

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (2) 页面路由

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (3) SASS与SCSS

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (4) FontAwesome图标

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (5) Axios网络请求封装

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (6) 登录页面

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (7) 主页面

  • 基于.NetCore开发博客项目 StarBlog - 前端开发 (8) Vuex与状态管理

  • 基于.NetCore开发博客项目 StarBlog - 前端开发之文件上传

  • 基于.NetCore开发博客项目 StarBlog - 前端开发之瀑布流图片列表

  • 基于.NetCore开发博客项目 StarBlog - 前端开发之导航守卫

  • ...

前言

上一篇文章介绍(水)了新建项目的操作,本文开始终于进入正题要开始写代码了!

对了,上一篇文章有朋友留言问管理端的用户名和密码是多少,这个是我疏忽了,没有做一个便捷的项目初始化功能,目前登录管理端需要在数据库的User表创建一个用户,后续我会完善角色和权限控制部分,然后给项目加一些命令行工具,就像django-admin那样。

OK,本文介绍StarBlog博客项目的模型设计。

模型设计

根据博客的功能需求,数据分成三类:

  • 文章相关(文章、文章分类)

  • 摄影/相册相关

  • 推荐内容配置(推荐文章、分类、图片;置顶文章、分类)

代码

由于我还没学DDD,(后续学了Abp vNext框架的话可能会用新技术进行重构),所以先用传统的MVC架构来规划项目~

回顾上一篇文章,我们新建了几个项目,现在,我们要把数据模型写在StarBlog.Data项目中。

打开IDE,在StarBlog.Data项目中新建一个目录,名为 Models,接下来的数据模型全都要放到这个目录/命名空间下。

由于项目代码已经在GitHub开源了,数据模型代码我就不全部贴上来了,先看看创建完成之后的目录结构。

代码可以这里看到:https://github.com/Deali-Axy/StarBlog/tree/master/StarBlog.Data/Models

Models
├── Category.cs    # 文章分类
├── FeaturedCategory.cs  # 推荐分类
├── FeaturedPhoto.cs     # 推荐图片
├── FeaturedPost.cs      # 推荐文章
├── Photo.cs             # 摄影图片
├── Post.cs              # 文章
├── TopPost.cs           # 置顶文章
└── User.cs              # 用户

为了便于读者理解项目设计和模型间的关系,我们挑几个关键的说一下。

Category.cs

文章分类。完整代码见:https://github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Data/Models/Category.cs

StarBlog博客支持markdown批量导入,然后以目录结构作为文章的分类,目录名就是分类名,且支持多级分类。

部分代码如下:

public class Category {public int Id { get; set; }public string Name { get; set; }public int ParentId { get; set; }public bool Visible { get; set; } = true;
}

Post.cs

完整代码见:https://github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Data/Models/Post.cs

博客网站,最重要的就是文章,文章的模型部分代码如下

namespace StarBlog.Data.Models;public class Post {// 省略部分字段...public string? Status { get; set; }public bool IsPublish { get; set; }public string? Path { get; set; }public DateTime CreationTime { get; set; }public DateTime LastUpdateTime { get; set; }public string? Categories { get; set; }
}

首先看StatusIsPublish字段,一个是文章状态(未完成、未修改、未发布),一个是否发布。最终决定文章是否在网站上展示是IsPublish字段,那Status字段存在的意义是啥?

答案:为了保留导入前的文章状态。

本项目的博客支持导入整个目录markdown文件作为文章,我的习惯是会在markdown文件的文件名最前面写上这个文章的状态,比如一篇未完成的文章,它的文件名是:(未完成)StarBlog博客开发笔记(3):模型设计,所以这个Status字段就是要把(未完成)中的这个状态识别提取出来,(具体用到的是正则表达式,这是后面要介绍的内容)。

然后是Path字段,这个字段表示文章作为markdown文件导入前存放的相对位置,比如导入了D:\blog这个目录里的所有文章,而这个目录的结构是这样的:

blog
├── Asp-Net-Core学习笔记
│   ├── Asp-Net-Core学习笔记:1.MVC入门篇.md
│   ├── Asp-Net-Core学习笔记:2.MVC视图、模型、持久化、文件、错误处理、日志.md
│   ├── Asp-Net-Core学习笔记:3.使用SignalR实时通信框架开发聊天室.md
│   ├── Asp-Net-Core学习笔记:4.Blazor-WebAssembly入门.md
│   ├── Asp-Net-Core学习笔记:5.构建和部署.md
│   ├── Asp-Net-Core学习笔记:WebApi开发实践.md
│   ├── Asp-Net-Core学习笔记:身份认证入门.md
│   ├── Asp-Net-Core学习笔记:部署,早知道,还是docker,以及一点碎碎念.md
├── Asp-Net-Core开发笔记
│   ├── Asp-Net-Core开发笔记:使用NPM和gulp管理前端静态文件.md
│   ├── Asp-Net-Core开发笔记:在docker部署时遇到一个小坑.md
│   └── Asp-Net-Core开发笔记:接口返回json对象出现套娃递归问题.md
├── 不吹不黑,跨平台框架AspNetCore开发实践杂谈.md
├── 梦想家装平台开发记录,Asp-Net-Core上手实践.md
├── (未修改)How-to-Connect-to-MySQL-from--NET-Core.md
├── (未修改)使用Ocelot实现Api网关.md
├── (未发布)跨域配置.md
├── (未完成)ASP-NET-Core-使用-Hangfire-定时任务.md
├── (未完成)Core-定时任务之HangFire.md
├── (未完成)使用-ASP-NET-Core-和-Hangfire-实现-HTTP-异步化方案.md
├── (未完成)使用Sentry.md
└── (未完成)在xunit里使用依赖注入.md

那对于在blog/AspNetCore目录下的文章(未发布)跨域配置.md 来说,它的Path字段就是AspNetCore

对于在blog/AspNetCore/Asp-Net-Core学习笔记目录下的文章来说,Path字段就是AspNetCore/Asp-Net-Core学习笔记

这个Path字段的意义,就在于实现前面说的多级分类,同时最下面的Categories字段,也是为了实现多级分类准备的。

在文章导入的过程中,目录名称作为文章分类名创建了文章的分类,同时记录分类ID到文章的CategoryId字段中,如果是多级分类的话,文章的CategoryId字段记录的是最后一个分类,父分类是不在这个CategoryId里的,虽然Category有个ParentId字段可以找到父分类,但是在实际使用的时候比较麻烦,所以我又加了这个 Categories 字段,把文章的分类层级记录起来,其内容类似这样 1,2,3 ,用逗号分隔开分类ID

这样前台展示的时候只需要用 servicesCategories 字段处理成 List<Category> 就可以了。

Photo.cs

对了,还有图片模型,因为平时有空会拍照,所以做个摄影分享的功能,这个模型就存上传的图片。

部分代码如下

public class Photo {// 省略部分字段...public string Location { get; set; }public string FilePath { get; set; }public long Height { get; set; }public long Width { get; set; }
}

图片的高度和宽度字段我一开始是没考虑的,不过在做瀑布流展示的时候发现没有宽高度不行,于是找到了 SixLabors.ImageSharp 这个库读取图片信息,这个库功能还挺强的,推荐一波~

Location拍摄地点现在只能手动输入,我之前用Python做过一个相册的项目,可以根据图片的Exif信息读取拍摄的GPS信息,然后用逆地址解析的方法解析出拍摄的地址,这个先记个todo,后面来实现~

其他的

三个Featured开头的是推荐相关的,可以在后台配置;

然后置顶文章和置顶分类只能分别设置一个,展示在网站主页。

大概就这些了,下篇文章见~

同时所有项目代码已经上传GitHub,欢迎各位大佬Star/Fork!

  • 博客后端+前台项目地址:https://github.com/Deali-Axy/StarBlog

  • 管理后台前端项目地址:https://github.com/Deali-Axy/StarBlog-Admin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab读取文件夹下所有文件的字符串,MATLAB读取文件夹下所有文件的文件名并读取数据...

MATLAB读取文件夹下特定类型格式文件的文件名并读取该格式文件的数据利用代码对大量数据进行自动批处理时&#xff0c;首先需要获取该数据存放的文件夹(文件夹路径)&#xff0c;然后获取该文件夹下某一类型数据所有的文件名&#xff0c;最后通过特定的数据读取代码读取数据进行…

sqlserver建表语句_重新认识MySQL中的COUNT语句

在数据库的增删改查操作中&#xff0c;使用最频繁的就是查询操作。而在所有查询操作中&#xff0c;统计数量操作更是经常被用到。关于数据库中行数统计&#xff0c;无论是MySQL还是Oracle亦或者是SqlServer&#xff0c;都有一个函数可以使用&#xff0c;那就是COUNT。而对于COU…

显示学生各科成绩和总成绩-面试被问到

表结构如下&#xff1a; name schedule score 张三 语文 20张三 数学 60张三 英语 80李四 数学 30李四 英语 60李四 语文 80 想要的结果如下&#xff1a; 姓名 语文 数学 英语 总成绩 …

sql INNER JOIN 取得两个表中存在连接匹配关系的记录(mysql)

首先&#xff1a;JOIN 通常与 ON 关键字搭配使用 其次我们来看我们的两个表格&#xff1a; table1: table2: 在这里&#xff0c;INNER JOIN&#xff08;内连接,或等值连接&#xff09;&#xff1a;取得两个表中存在连接匹配关系的记录。 例如我要取到table1和table2之…

【Linux】IPC-消息队列

问题 消息队列id 和键值KEY区别&#xff1f; 首先要注意一个概念&#xff1a;IPC结构都是内核的结构。也就是说IPC结构由内核维护&#xff0c;对于每个进程都是公共的&#xff0c;不属于某个特定进程。只有这样&#xff0c;IPC结构才能支持它们“进程间通信”的功能。 有两个东…

linux shell之得到当前路径下的目录

方法1 find . -type d 方法2 ^是开头开头得意思&#xff0c;然后d是dictionary意思 ls -al | grep ^d 方法3 ls -F | grep /$ 方法4 ls -d */

python中html.parser_在Python中使用HTMLParser解析HTML的教程

如果我们要编写一个搜索引擎&#xff0c;第一步是用爬虫把目标网站的页面抓下来&#xff0c;第二步就是解析该HTML页面&#xff0c;看看里面的内容到底是新闻、图片还是视频。假设第一步已经完成了&#xff0c;第二步应该如何解析HTML呢&#xff1f;HTML本质上是XML的子集&…

分别统计出其中英文字母、空格、数字和其它字符的个数 matlab 程序,编写一段程序,要求先输入一行字符,然后分别统计出其中英文...

编写一个求和的程序,要求能任意输入两个整数,求和 用javascript写functionadd(){varAdocument.getElementById("a").value;varBdocument.getElementById("b").value;varA用C语言编写一段程序,输入一行字符,分别统计出其中的英文字母、空格、数字和其他字符…

【ArcGIS遇上Python】长时间序列(30年)每两组栅格数据对应做减法运算求物候参数

Python语言在ArcGIS软件中发挥着乾坤大挪移的作用,然而很多人并不知道它的厉害之处。今天我们利用Python语言来批处理遥感物候数据,获取物候期的参数。 说明: (1)Up_Path:始期数据路径变量 (2)Down_Path:末期数据路径变量 (3)outPath:相减输出结果路径变量 完…

Blazor University (14)渲染树

原文链接&#xff1a;https://blazor-university.com/components/render-trees/渲染树当浏览器呈现内容时&#xff0c;它不仅绘制 HTML 中定义的元素&#xff0c;还必须根据页面大小&#xff08;元素流&#xff09;计算绘制它们的位置。例如&#xff0c;以下 Bootstrap HTML 将…

思科加强生成树性能的属性(Portfast /Uplinkfast/BackboneFast)与RSTP的关系

思科加强生成树性能的属性&#xff08;Portfast/Uplinkfast/BackboneFast&#xff09;与RSTP的关系本文截自于博主CCNP交换技术稿件内容4.2.6思科加强生成树性能的属性&#xff08;Portfast/Uplinkfast/BackboneFast&#xff09;与RSTP的关系首先说明一下&#xff0c;为什么笔者…

数据结构(java语言描述)顺序栈的使用

&#xff11;&#xff0e;声明Istack接口&#xff1b; package stack;public interface Istack { public void clear(); public boolean isEmpty(); public int length(); public Object peek(); public void push(Object x) throws Exception; public Objec…

sql LEFT JOIN RIGHT JOIN(左连接)(mysql)

我们首先来看我们的两个表&#xff1a; table1: table2: 在这里&#xff0c;LEFT JOIN&#xff08;内连接,或等值连接&#xff09;&#xff1a;取得左表&#xff08;table1&#xff09;完全记录&#xff0c;即是右表&#xff08;table2&#xff09;并无对应匹配记录。 …

linux shell之xargs 、tr、sha1sum、head、tail一般使用

1 xargs命令 有点类似-exec命令 1&#xff09;删除当前目录下面的c文件 find . -name "*.c" | xargs rm 2&#xff09;统计当前c文件里面的代码行数 find . -name "*.c" | xargs wc -l 2 tr命令 替换命令 1&#xff09;把大小替换成小写 echo &quo…

php的_auto,AutoPHPCheck下载

AutoPHPCheck官方版是一款相当优秀的php开发人员专用PHP验证工具&#xff0c;AutoPHPCheck官方版功能全面&#xff0c;便捷好用&#xff0c;支持执行快速验证来帮助您确保代码的安全性&#xff0c;并且软件还附带了一个基本的语法检查器&#xff0c;可以查找并帮助您处理错误。…

python0表示剪刀_石头,纸,剪刀Python代码。帮助简化

我是Python新手&#xff0c;只写过几个程序。这是我最近为一个“石头剪子”游戏编写的代码。我已经测试过了&#xff0c;效果很好。有什么方法可以简化它吗&#xff1f;谢谢&#xff01;import randomwins0losses0ties0rounds0r1 #rockp2 #papers3 #scissorsy "The compu…

Google图片加载库Glide的简单封装GlideUtils

Google图片加载库Glide的简单封装GlideUtils

【ArcGIS遇上Python】Python实现点转栅格(PointToRaster)

在ArcGIS中提供了点转栅格(PointToRaster)的工具,如下所示: 参数说明: (1)file:点图层(.shp) (2)data:值字段 (3)outFile:转换后的栅格图层 (4)9660.848118:空间分辨率 python批处理代码: import arcpy arcpy.gp.overwriteOutput=1 arcpy.env.workspace=&…

ASP.NET Core认证授权方案

前言在前面我讲过基于token的权限认证&#xff0c;然后前几天有小伙伴私信我&#xff0c;怎么做一个身份认证也就是授权。在Asp.net Core常见的授权方式有:基于角色的授权&#xff0c;有基于声明的授权&#xff0c;有基于策略的授权&#xff0c; 这三种授权我就不做过多介绍了,…

linux基础知识个人总结

linux基础知识个人总结第一章&#xff1a;1. Linux发展史略&#xff0c;有代表性的Linux发行版&#xff1a;Suse、slackware、ubuntu、RedHat、CentOS2. GNU是Richard Stallman在1983年发起的一项自由软件运动&#xff0c;目标是为了创建一套完全自由的操作系统&#xff0c;它要…