博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 全栈开发,Day80(博客系统分析,博客主页展示)
阅读量:4560 次
发布时间:2019-06-08

本文共 17464 字,大约阅读时间需要 58 分钟。

一、博客系统分析

数据库的构建

首先,我们分析一个博客系统的功能:

  • 一个博客可以有多个标签(多对多)
  • 一个博客可以有多条评论(一对多)
  • 一个博客只可以有一个类别(多对一)

接下来,我们分析关系的属性:

博客:标题,作者,内容,发布时间,分类(外键),标签(多对多)等
标签:标签名
类别:分类名
评论:作者,博客(外键),邮箱,内容,发布时间等。

有8张表,表关系如下:

 

图中箭头开始的英文字母表示关联字段

按照箭头方向查询,表示正向查询,否则为反向查询

 

新建项目cnblog,应用名为blog

修改models.py,必须导入模块

from django.contrib.auth.models import AbstractUser

因为有一个表userinfo需要继承它。django自带的auth_user表也是继承AbstractUser

表模型如下:

from django.db import models# Create your models here.from django.db import models# Create your models here.from django.contrib.auth.models import AbstractUserclass UserInfo(AbstractUser):    """    用户信息    """    nid = models.AutoField(primary_key=True)    telephone = models.CharField(max_length=11, null=True, unique=True)    avatar = models.FileField(upload_to='avatars/', default="avatars/default.png")    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)    blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)    def __str__(self):        return self.usernameclass Blog(models.Model):    """    博客信息    """    nid = models.AutoField(primary_key=True)    title = models.CharField(verbose_name='个人博客标题', max_length=64)    site_name = models.CharField(verbose_name='站点名称', max_length=64)    theme = models.CharField(verbose_name='博客主题', max_length=32)    def __str__(self):        return self.titleclass Category(models.Model):    """    博主个人文章分类表    """    nid = models.AutoField(primary_key=True)    title = models.CharField(verbose_name='分类标题', max_length=32)    blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)    def __str__(self):        return self.titleclass Tag(models.Model):    nid = models.AutoField(primary_key=True)    title = models.CharField(verbose_name='标签名称', max_length=32)    blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)    def __str__(self):        return self.titleclass Article(models.Model):    nid = models.AutoField(primary_key=True)    title = models.CharField(max_length=50, verbose_name='文章标题')    desc = models.CharField(max_length=255, verbose_name='文章描述')    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)    content = models.TextField()    comment_count = models.IntegerField(default=0)    up_count = models.IntegerField(default=0)    down_count = models.IntegerField(default=0)    user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)    category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)    tags = models.ManyToManyField(        to="Tag",        #through参数可以指定用作中介的中间模型        through='Article2Tag',    )    def __str__(self):        return self.titleclass Article2Tag(models.Model):    nid = models.AutoField(primary_key=True)    article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE)    tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE)    class Meta:        #组合唯一约束        unique_together = [            ('article', 'tag'),        ]    def __str__(self):        v = self.article.title + "---" + self.tag.title        return vclass ArticleUpDown(models.Model):    """    点赞表    """    nid = models.AutoField(primary_key=True)    user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)    article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)    is_up = models.BooleanField(default=True)    class Meta:        # 组合唯一约束        unique_together = [            ('article', 'user'),        ]class Comment(models.Model):    """    评论表    """    nid = models.AutoField(primary_key=True)    article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)    user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)    content = models.CharField(verbose_name='评论内容', max_length=255)    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)    parent_comment = models.ForeignKey('Comment', null=True, on_delete=models.CASCADE)    def __str__(self):        return self.content
View Code

相关参数解释:

through 表示orm,不要创建关系表。而制定一个表,这个表自己来创建!为什么呢?因为orm创建多对多关系表时,只有3个字段。那么需要关系表需要扩充字段时,就不行了!

所以设置through 字段,是为了方便添加额外的字段。使用through,那么这个表,称之为中间模型。

在Comment模型表中,有一个字段parent_comment。它关联的是本身表中的主键nid,它是一个父级评论id,用来展示谁评论谁!to='Comment'等同于to='self'

 

修改settings.py配置文件,覆盖默认的User模型最后一行添加,否则执行创建表命令时会报错!

AUTH_USER_MODEL="blog.UserInfo"

Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。

bolg,是应用名。

 

使用下面2个命令,生成表

python manage.py makemigrationspython manage.py migrate

生成的表如下:

 注意:django自带的auth_user表没有了,取而代之的是blog_userinfo表。

查看表字段

它在auth_user表的基础上,增加了5个字段!

 

登录验证

添加超级用户,密码必须是8位或者以上!

python manage.py createsuperuser

效果如下:

再创建2个用户,zhang和lisi。用来测试多个用户登录! 

lisi用户

 

修改urls.py,增加路径

from blog import viewsurlpatterns = [    path('admin/', admin.site.urls),    path('index/', views.index),    path('login/', views.login),]
View Code

修改views.py,增加视图函数

from django.shortcuts import render,HttpResponse,redirectfrom django.contrib import authfrom blog.models import Article,UserInfo# Create your views here.def login(request):    if request.method=="POST":        user=request.POST.get("user")        pwd=request.POST.get("pwd")        # 用户验证成功,返回user对象,否则返回None        user=auth.authenticate(username=user,password=pwd)        if user:            # 登录,注册session            # 全局变量 request.user=当前登陆对象(session中)            auth.login(request,user)            return redirect("/index/")    return render(request,"login.html")def index(request):    return render(request,"index.html")
View Code

修改login.html

    
Title
{
% csrf_token %}
用户名
密码
View Code

修改index.html

    
Title

INDEX

View Code

访问登录页面

跳转到首页

 

首页修饰

修改settings.py,设置静态文件目录。最后一行添加:

STATICFILES_DIRS=[    os.path.join(BASE_DIR,"static")]
View Code

下载bootsrtap,将压缩的包内容放到satic目录

img和js是新建的

目录如下:

修改urls.py,增加路径

urlpatterns = [    path('admin/', admin.site.urls),    path('login/', views.login),    path('index/', views.index),    path('logout/', views.logout),    path('', views.index),]
View Code

修改views.py,增加注销

def logout(request):  # 注销    auth.logout(request)    return redirect("/index/")
View Code

修改index.html

    
Title

Panel title

Panel content

Panel title

Panel content
222

Panel title

Panel content

Panel title

Panel content

Panel title

Panel content
View Code

重新登录,效果如下:

 

添加内容

 使用django自带的admin后台,快速添加数据。

访问后台页面,这里必须是超级用户。上面已经创建了超级用户xiao

默认是空的

操作表,必须要注册

修改views.py同级目录下的admin.py

注册所有的模型表

from django.contrib import admin# Register your models here.from blog import modelsadmin.site.register(models.UserInfo)admin.site.register(models.Blog)admin.site.register(models.Category)admin.site.register(models.Tag)admin.site.register(models.Article2Tag)admin.site.register(models.Article)admin.site.register(models.ArticleUpDown)admin.site.register(models.Comment)
View Code

再次刷新页面

 

点击Articles,添加文章

 

从http://www.py3study.com 上面copy一篇博客

注意内容都是html代码

 添加分类

 添加站点

 

 保存

点击保存

 添加成功

多添加几篇博客

首页文章展示

修改settings.py,更改时区

TIME_ZONE = 'Asia/Shanghai'

修改index视图函数

def index(request):    article_list=Article.objects.all()    return render(request,"index.html",{
"article_list":article_list})
View Code

修改index.html

    
Title

Panel title

Panel content

Panel title

Panel content
{
% for article in article_list %}
{ { article.title }}
{ { article.desc }}
{ { article.user.username }}   发布于
{ { article.create_time|date:'Y-m-d H:i' }}  
评论({ { article.comment_count }})  
点赞({ { article.up_count }})

{
% endfor %}

Panel title

Panel content

Panel title

Panel content

Panel title

Panel content
View Code

访问首页,效果如下:

 

 

个人站点展示

比如博客园范围个人站点是域名加用户名,就可以了,比如:

如果用户不存在,会提示404页面

增加404页面

修改urls.py,增加路径。注意导入re_path

from django.contrib import adminfrom django.urls import path,re_pathfrom blog import viewsurlpatterns = [    path('admin/', admin.site.urls),    path('login/', views.login),    path('index/', views.index),    path('logout/', views.logout),    path('', views.index),    re_path('(?P
\w+)', views.homesite),]
View Code

修改views.py,增加视图函数

def homesite(request,username):    """    查询    :param request:    :param username:    :return:    """    # 查询当前站点的用户对象    user=UserInfo.objects.filter(username=username).first()    if not user:        return render(request,"not_found.html")    return render(request,"homesite.html",{
"user":user})
View Code

在templates目录创建文件not_found.html

    
Title
cnblogs

404. 抱歉! 您访问的资源不存在!

请确认您输入的网址是否正确,如果问题持续存在,请发邮件至 xx@qq.com 与 xiao 联系。

返回网站首页

View Code

创建homesite.html

    
Title

{
{ user }}

View Code

访问网页:http://127.0.0.1:8000/xiao

访问一个不存在的用户

http://127.0.0.1:8000/123

页面提示404

 

展示文章列表

修改homesite视图函数

def homesite(request,username):    """    查询    :param request:    :param username:    :return:    """    # 查询当前站点的用户对象    user=UserInfo.objects.filter(username=username).first()    if not user:        return render(request,"not_found.html")    # 查询当前站点对象    blog=user.blog    # 查询当前用户发布的所有文章    article_list=Article.objects.filter(user__username=username)    return render(request,"homesite.html",{
"blog":blog,"article_list":article_list})
View Code

修改homesite.html

    
Title

{

{ blog.title }}

Panel title

Panel content

Panel title

Panel content

Panel title

Panel content
{
% for article in article_list %}
{ { article.title }}
{ { article.desc }}
发布于
{ { article.create_time|date:'Y-m-d H:i' }}  
评论({ { article.comment_count }})  
点赞({ { article.up_count }})

{
% endfor %}
View Code

访问xiao的个人站点,效果如下:

 这个时候发现,左上角没有显示博客标题。那是因为用户认证表的blog_id字段默认为空,需要在admin后台绑定一下

登录到后台,点击用户表,点击指定的用户xiao

拉到最下面,绑定blog,点击保存

再次刷新个人站点,发现出来了!

 

作业:

查询当前站点每一个分类的名称以及对应的文章数

查询当前站点每一个标签的名称以及对应的文章数

答案:

修改homesite视图函数

def homesite(request,username):    """    查询    :param request:    :param username:    :return:    """    # 查询当前站点的用户对象    user=UserInfo.objects.filter(username=username).first()    if not user:        return render(request,"not_found.html")    # 查询当前站点对象    blog=user.blog    # 查询当前用户发布的所有文章    article_list=Article.objects.filter(user__username=username)    # 查询当前站点每一个分类的名称以及对应的文章数    cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article__title")).values("title","c")    print(cate_list)    # 查询当前站点每一个标签的名称以及对应的文章数    tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article__title")).values("title","c")    print(tag_list)    dict = {
"blog":blog, "article_list":article_list, "category_count":cate_list, "tag_count":tag_list, } return render(request,"homesite.html",dict)
View Code

修改homesite.html

    
Title

{

{ blog.title }}

我的标签

{
% for foo in category_count %}
{ { foo.title }}({ { foo.c }})
{
% endfor %}

随笔分类

{
% for foo in tag_count %}
{ { foo.title }}({ { foo.c }})
{
% endfor %}

随笔档案

Panel content
{
% for article in article_list %}
{ { article.title }}
{ { article.desc }}
发布于
{ { article.create_time|date:'Y-m-d H:i' }}  
评论({ { article.comment_count }})  
点赞({ { article.up_count }})

{
% endfor %}
View Code

进入admin后台,添加一个tag。增加一篇文章

重新访问个人站点网页,效果如下:

 

 

转载于:https://www.cnblogs.com/xiao987334176/p/9291166.html

你可能感兴趣的文章
jQuery 跨域访问问题解决方法
查看>>
谨慎能捕千秋蝉(一)——XSS
查看>>
Spring、SpringMVC、Spring Boot、Spring Cloud 概念、关系及区别
查看>>
iOS effect & swiper delete components
查看>>
CSS3 & Grid Layout All In One
查看>>
《机器学习实战》学习笔记第四章 —— 朴素贝叶斯法
查看>>
承接上篇scanf函数何时取&问题
查看>>
python笔记 - day4-之装饰器
查看>>
HttpWebResponse远程服务器返回错误: (500) 内部服务器错误
查看>>
关于.net MVC5+EF6 网站部署的问题
查看>>
异常 : identifier of an instance of com.mi.domain.Department was altered from 2 to 1
查看>>
实现托管代码调用非托管代码以及非托管代码调用托管代码->COM Interop
查看>>
简易乘方算法
查看>>
leetcode - Unique Paths
查看>>
舵机控制
查看>>
句柄类与继承
查看>>
cocos2d-x-3.1 事件分发机制 (coco2d-x 学习笔记七)
查看>>
多项式问题
查看>>
服务器实现的多种方法汇总
查看>>
理解jquery的$.extend()、$.fn和$.fn.extend()
查看>>