Django2.0学习笔记1(哔哩哔哩杨士航)

1.安装虚拟环境

pip install virtualenvwrapper

安装完之后设置一下环境变量WORK_HOME,设置自己想保存虚拟环境的的文件夹

常用命令

mkvirtualenv 虚拟环境名字 #创建虚拟环境
workon 虚拟环境名字 #打开摸个虚拟环境
deactivate #退出虚拟环境
lsvirtualenv  #列出所有虚拟环境
rmvirtualenv 虚拟环境名字 #删除虚拟环境

workon 运行虚拟环境后
pip install django
安装django

2.Django的Hello world

首先先创建项目

django-admin startproject mysite


打开mysite文件

打开mysite文件夹

这些就是django项目目录

修改一些参数

打开mysite/mysite下的的settings.py
修改语言和时区

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'#UTC

新建views.py

写入以下代码

from django.http import HttpResponse
def index(request):
    return HttpResponse("Hello World!")

打开urls.py,添加以下代码

from . import views #这一行需要添加
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index),#这一行需要添加
]

python manage.py runserver
打开浏览器输入http://127.0.0.1:8000
可以看到如下界面

3.Django应用结构

创建一个app
python manage.py startapp article
文档结构如下

article文件夹如下

打开models.py,写入如下代码

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=30)
    content = models.TextField()

打开admin.py写入如下代码

from .models import Article
# Register your models here.
admin.site.register(Article)#注册模型

首先在settings.py把article app写入

然后制造迁移
python manage.py makemigrations
然后进行数据库迁移
python manage.py migrate
在进行上述步骤之前,你可能没有创建超级用户
超级用户的创建步骤如下
python manage.py migrate
python manage.py createsuperuser
输入管理员账号和密码(邮箱可以不填)
启动Django项目
python manage.py runserver
访问http://127.0.0.1:8000/admin
输入账号密码
可以看到如下界面


添加文章,点击article下的添加文章

可以多添加几篇,添加文章后界面如下

4.模板的使用

打开article下的的views.py

# Create your views here.
def article_detail(request,article_id):
    return HttpResponse("文章id为:{}".format(article_id))

在urls.py下添加如下代码

from django.contrib import admin
from django.urls import path
from . import views
from article.views import article_detail#新添加
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index),
    path('article/<int:article_id>',article_detail),#新添加
    
]

启动django网站
python manage.py runserver
访问如下地址
http://localhost:8000/article/1
(localhost等同于127.0.0.1)
效果如下图


打开article下的的views.py,修改代码如下

from django.shortcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request,article_id):
    article=Article.objects.get(id=article_id)
    return HttpResponse("文章id为:{},标题{}".format(article_id,article.title))

结果如下图


再添加一个arcticle.content
可以再显示一个文章内容

当访问的页面不存在时,例如访问http://127.0.0.1:8000/article/5
网页会出现错误提示,说出现DoesNotExist错误,
首先可以使用try代码

try:
        article=Article.objects.get(id=article_id)
    except Article.DoesNotExist:
        return HttpResponse("页面不存在!")
    return HttpResponse("文章id为:{},标题:{},内容:{}".format(article_id,article.title,article.content))

也可以使用Http404

from django.http import HttpResponse,Http404
def article_detail(request,article_id):
    try:
        article=Article.objects.get(id=article_id)
    except Article.DoesNotExist:
        raise Http404("页面不存在!")
    return HttpResponse("文章id为:{},标题:{},内容:{}".format(article_id,article.title,article.content))

创建模板显示内容

在arcticle app下创建templates文件夹
新建article_detail.html,然后在article app下的views.py写入如下代码

from django.shortcuts import render
from django.http import HttpResponse,Http404
from .models import Article
# Create your views here.
def article_detail(request,article_id):
    try:
        article=Article.objects.get(id=article_id)
        content={}
        content["article_obj"]=article
        return render(request,"article_detail.html",content)
    except Article.DoesNotExist:
        raise Http404("页面不存在!")

在article_detail.html写入如下代码:

<!doctype html>
<html>
<head>
    <charset="utf-8">
    <title>文章内容</title>
</head>
<body>
<h2>{{ article_obj.title }}</h2>
<hr>
<p>{{ article_obj.content }}</p>
</body>
</html>

访问http://localhost:8000/article/1


也可以导入render_to_response

from django.shortcuts import render_to_response
return render_to_response("article_detail.html",content)

也是可以的
导入get_object_or_404(这个方法是比较简洁的)

from django.shortcuts import get_object_or_404
article=get_object_or_404(Article,pk=article_id)
    content={}
    content["article_obj"]=article
    return render(request,"article_detail.html",content)

创建article_list.html,在article app下的views.py创建如下函数

def article_list(request):
    article=Article.objects.all()
    context={}
    context["articles"]=article
    return render(request,"article_list.html",context)

article_list.html里写入如下代码

<!doctype html>
<html>
<head>
    <charset="utf-8">
    <title>文章列表</title>
</head>
<body>
{% for article in articles %}   
    {#<a href="/article/{{article.pk}}">{{ article.title }}</a>#}
    {#<br>#}
    <a href="{% url 'article_detail' article.pk %}">{{ article.title }}</a>
    <br>
{% endfor %}
</body>
</html>

在mysite里面的urls.py下的path添加如下代码

path('article/',article_list,name="article_list"),

访问http://localhost:8000/article/
结果如下图


修改路由,在article下创建urls.py
将mysite下的ruls.py下的

path('article/<int:article_id>',article_detail,name="article_detail"),
path('article/',article_list,name="article_list"),

移动到article app下的urls.py
修改后代码如下
article下的urls.py

from django.urls import path
from .import views 
urlpatterns = [
    path('<int:article_id>',views.article_detail,name="article_detail"),
    path('',views.article_list,name="article_list"),
]

mysite下的urls.py

from django.contrib import admin
from django.urls import path,include
from . import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index),
    path('article/',include("article.urls")),
]

仍然可以正常访问。


后台定制和修改模型

models.py
在article类下添加如下函数

def __str__(self):
        return "Article:{}".format(self.title)


修改admin.py下的代码,注释掉admin.site.register(Article)
添加如下代码

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display=("id","title","content")
    ordering=("id",)#升序排列,倒叙加-,默认倒序

修改模型
修改模型要更新数据库

python manage.py makemigrations
python manage.py migrate

(需要设置默认值)
修改模型之前要先备份数据库文件
打开 article app下models.py
在Article类下添加如下代码
created_time=models.DateTimeField()
然后运行,python manage.py makemigrations
提示字段没有设置默认值,无法创建
(1)设置默认值
timezone.now
就可以了
python manage.py makemigrations无报错
在article app下的admin.py下的list_display后面添加一个"created_time"字段
(2)
admin.py下修改如下代码

from django.utils import timezone
created_time=models.DateTimeField(default=timezone.now)
python manage.py makemigrations

(3)
created_time=models.DateTimeField(auto_now_add=True)#自动添加时间
选择1,输入

timezone.now
python manage.py migrate

创建成功
在article app下的admin.py下的list_display后面添加一个"created_time"字段


last_update_time=models.DateTimeField(auto_now=True)#增加最后修改时间

在article app下的admin.py下的list_display后面添加一个"last_update_time"字段

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

外键

from django.contrib.auth.models import User
auther=models.ForeignKey(User,on_delete=models.DO_NOTHING,default=1)

在article app下的admin.py下的list_display后面添加一个"auter"字段

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

修改字段名

author=models.ForeignKey(User,on_delete=models.DO_NOTHING,default=1)

在article app下的admin.py下的list_display后面添加一个"autor"字段

python manage.py makemigrations
Did you rename article.auther to article.author (a ForeignKey)? [y/N]y
python manage.py migrate
python manage.py runserver
is_deleted=models.BooleanField(default=False)#是否删除
readed_num=models.IntegerField(default=0)#阅读数量

在article app下的admin.py下的list_display后面添加两个"is_deleted,readed_num"字段

python manage.py makemigrations
python manage.py migrate
python manage.py runserver


显示未被删除的数据
将第二篇文章的的is_deleted值改为True

在article app下的views.py的
article_list下的article=Article.objects.all()改为
articles=Article.objects.filter(is_deleted=False)

构建个人博客网站

网站的功能模块

1.博客

博文
博客分类
博客标签
2.评论

3.点赞
4.阅读
5.用户

第三方登录
功能模块约等于Django App

mkvirtualenv mysite_env
pip install django
django-admin startproject mysite
python manage.py startapp blog

在blog app下的models.py写入如下代码

from django.contrib.auth.models import User
# Create your models here.
class BlogType(models.Model):
    type_name=models.CharField(max_length=15)
class Blog(models.Model):
    title=models.CharField(max_length=50)
    blog_type=models.ForeignKey(BlogType,on_delete=models.DO_NOTHING)
    content=models.TextField()
    author=models.ForeignKey(User,on_delete=models.DO_NOTHING)
    created_time=models.DateTimeField(auto_now_add=True)
    last_update_time=models.DateTimeField(auto_now=True)

博文+博客分类
一篇博客一种分类√
一篇博客多种分类
在settings.py下添加blog app

python manage.py  makemigrations
python manage.py  migrate
python manage.py createsuperuser

修改blog app下admin.py文件的内容

from .models import Blog,BlogType
# Register your models here
@admin.register(BlogType)
class BlogTypeAdmin(admin.ModelAdmin):
    list_display=("id","type_name",)
@admin.register(Blog)
class BlogAdmin(admin.ModelAdmin):
    list_display=("title","blog_type","author","created_time","last_update_time")

访问http://localhost:8000/admin/
增加博客类型
Django 随笔 感悟

添加三篇博客
在blog app下models.py的BlogType类后面添加一个函数

def __str__(self):
    return "BlogType:{}".format(self.type_name)

在blog app下models.py的Blog类后面添加一个函数

def __str__(self):
    return "Blog:{}".format(self.title)

添加如下内容
第一篇博客
随笔
这是我的第一篇博客


pip freeze > requirements.txt
#导出需要的包
pip install -r requirements.txt
#安装需要的包

常用模版标签和过滤器

blog app下的views.py添加如下代码

from .models import Blog,BlogType
# Create your views here.
def blog_list(request):
    context={}
    context["blogs"]=Blog.objects.all()
    return render_to_response('blog_list.html',context)
def blog_detail(request,blog_pk):
    context={}
    context["blog"]=get_object_or_404(Blog,pk=blog_pk)
    return render_to_response("blog_detail.html",context)

在blog app文件夹内新建一个templates文件夹,添加
blog_list.html和blog_detail.html列表
blog_list.html内容如下

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我的网站</title>
</head>
<body>
    <div>
        <h2>个人博客网站</h2>
    </div>
    {% for blog in blogs %}
        <h3>{{ blog.title }}</h3>
        <p>{{blog.content}}</p>
    {% endfor %}
</body>
</html>

blog_detail.html内容如下

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{ blog.title }}</title>
</head>
<body>
    <h3>{{blog.title}}</h3>
    <p>{{blog.content}}</p>
</body>
</html>

blog app文件夹下新建urls.py

from django.urls import path
from . import views
#start with blog
urlpatterns = [
    #http://lcolhost:8000/blog/1
    path('<int:blog_pk>',views.blog_detail,name="blog_detail"),
]

mysite下的urls.py添加如下代码

from django.urls import path,include
path('',blog_list,name="home"),
path('blog/',include("blog.urls")),

访问http://127.0.0.1:8000/


将blog_list.html的

{% for blog in blogs %}
    <h3>{{ blog.title }}</h3>{#修改这一行#}
    <p>{{blog.content}}</p>
{% endfor %}

改为下面的代码

<a href="{% url 'blog_detail' blog.pk %}">
    {{ blog.title }}
</a>

在blog_detail.html下添加如下代码:

<div>
    <a href="{% url 'home' %}">
        <h2>个人博客网站</h2>
    </a>
</div>

也可以将blog_list.html也改为以下代码

<div>
    <a href="{% url 'home' %}">
        <h2>个人博客网站</h2>
    </a>
</div>

访问http://localhost:8000/admin/blog/blog/add/
添加一篇文章
标题:第二篇博客
类型:随笔
内容:这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客
这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客这是我的第二篇博客
访问http://127.0.0.1:8000/


统计博客数量

在blog_list.html下添加如下代码

<p>一共有{{ blog|length }}篇博客</p>

2.views.py下的blog_list函数下添加一行代码

context["blogs_count"]=Blog.objects.all().count()

在blog_list下添加如下代码

 <p>一共有{{ blogs_count }}篇文章</p>

在blog_list下拓展for循环,在for循环内部添加如下带代码:

{% empty %}
<p>暂时没有博客</p>
{#如果为0篇文章则显示此内容#}

过滤器处理过长文本,在blog_list.html下的

<p>{{blog.content}}</p>

修改为:

<p>{{blog.content|truncatechars:30}}</p>

过长内容则显示为省略号



{{|truncatewords:30}}
用来统计英文单词,规则使用空格来辨认
blog_detail.html添加如下带代码:

<p>作者:{{ blog.author}}</p>
<p>发表日期:{{ blog.created_time|date:"Y-m-d h:n:s" }}</p>
<p>分类:{{ blog.blog_type }}</p>
{#时间默认十二进制的#}
{#把h改为G/H则为二十四进制#}

官网地址介绍


blog app下的views.py添加如下代码

def blogs_with_type(request,blog_type_pk):
   context={}
   blog_type=get_object_or_404(BlogType,pk=blog_type_pk)
   context['blogs']=Blog.objects.filter(blog_type=blog_type)
   context['blog_type']=blog_type
   return render_to_response('blogs_with_type.html',context)

blog app下的urls.py添加如下代码

path('type/<int:blog_type_pk>',views.blogs_with_type,name="blogs_with_type"),

在templates文件夹下新建blogs_with_type.html,代码如下

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{blog_type.type_name}}</title>
</head>
<body>
    <div>
        <a href="{% url 'home' %}">
            <h2>个人博客网站</h2>
        </a>
    </div>
    <h3>{{blog_type.type_name}}</h3>
    {% for blog in blogs %}
        <a href="{% url 'blog_detail' blog.pk %}">
                {{ blog.title }}
        </a>
        <p>{{ blog.content|truncatechars:30 }}</p>
        {% empty %}
        <p>暂时没有博客</p>
        {# 如果为0篇文章则显示此内容 #}
    {% endfor %}
</body>
</html>

修改blog_detail.html文件夹下的<p>分类:{{ blog.blog_type }}</p>

<p>分类:
    <a href="{% url 'blogs_with_type' blog.blog_type.pk %}">
        {{ blog.blog_type }}
    </a>
</p>

配型为随笔的博客分类

再添加一篇django类型的博客





{#注释#}
truncatechars_html自动忽略掉html代码
truncatewords_html
是否信任html:safe

模板嵌套

循环 for
条件 if,ifequeal,ifnotequal
模板嵌套 block,extends,include
注释 {# #}

三个html文件有重复的地方

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">

</head>
<body>
    <div>
        <a href="{% url 'home' %}">
            <h2>个人博客网站</h2>
        </a>
    </div>
</body>
</html>

blog app下的templates文件夹新建一个html文件,名为base.html内容如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <div>
        <a href="{% url 'home' %}">
            <h2>个人博客网站</h2>
        </a>
    </div>
    <hr>
    {% block content %}{% endblock %}
</body>
</html>

blog_detail.html文件修改为如下内容:

{% extends 'base.html' %}

{% block title %}
    {{ blog.title }}
{% endblock %}

{% block content %}
    <h3>{{blog.title}}</h3>
    <p>作者:{{ blog.author}}</p>
    <p>{{blog.content}}</p>
    <p>发表日期:{{ blog.created_time|date:"Y-m-d h:n:s" }}</p>
    <p>分类:
        <a href="{% url 'blogs_with_type' blog.blog_type.pk %}">
                {{ blog.blog_type }}
        </a>
    </p>
{% endblock %}

blog_list.html内容修改为:

{% extends 'base.html' %}
{#页面标题#}
{% block title %}
    我的网站
{% endblock %}
{#页面内容#}
{% block content %}
    {% for blog in blogs %}
    <a href="{% url 'blog_detail' blog.pk %}">
            {{ blog.title }}
    </a>
    <p>{{ blog.content|truncatechars:30 }}</p>
    {% empty %}
    <p>暂时没有博客</p>
    {# 如果为0篇文章则显示此内容 #}
    {% endfor %}
    <p>一共有{{ blogs_count }}篇文章</p>
{% endblock %}

blogs_with_type.html修改为如下内容:

{% extends 'base.html' %}
{#页面标题#}
{% block title %}
    {{blog_type.type_name}}
{% endblock %}
{#页面内容#}
{% block content %}
    <h3>{{blog_type.type_name}}</h3>
    {% for blog in blogs %}
        <a href="{% url 'blog_detail' blog.pk %}">
                {{ blog.title }}
        </a>
        <p>{{ blog.content|truncatechars:30 }}</p>
        {% empty %}
        <p>暂时没有博客</p>
        {# 如果为0篇文章则显示此内容 #}
    {% endfor %}
{% endblock %}

python manage.py runserver
访问http://127.0.0.1:8000 可以正常访问

全局模板文件夹设置

在项目的根目录下,新建templates文件夹



打开settings.py文件
TEMPLATES下修改'DIRS': []为:

'DIRS': [
        os.path.join(BASE_DIR,'templates'),
    ],

把base.html移动到全局的templates文件夹下


访问http://lcoalhost:8000 如下图

模板文件设置建议
想任意迁移app,templates建议放在app文件夹里面
app为项目工作,可以放在全局的templates文件夹下,一般在templates文件夹下新建文件夹名字命名为app的名字即可

修改blog app下views.py的模板引用



访问http://lcoalhost:8000 网站还在正常运行

CSS页面设计

导航栏

logo网站名称+导航
把base.html文件添加两个a标签,代码如下:

<a href="/">首页</a>
<a href="{% url 'blog_list' %}">博客列表</a>

blog app下的urls.py添加一个路由

path('',views.blog_list,name='blog_list'),

修改首页的处理方法
新建文件命名为views.py保存到mysite文件夹下,


输入以下代码:

from django.shortcuts import render_to_response
def home(request):
    context={}
    return render_to_response('home.html',context)

mysite文件夹下修改urls.py

from .views import home
path('',home,name="home"),

在全局的templates文件夹下新建home.html
输入一下内容:

{% extends 'base.html' %}
{# 标题 #}
{% block title %}
    我的网站|首页
{% endblock %}
{#主体内容#}
{% block content %}
    <h3>欢迎访问我的网站,随便看</h3>
{% endblock %}

访问:http://127.0.0.1:8000/

页面如下:

页面美化:CSS
把base.html添加css代码,总体代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <div class="nav">
        <a class="logo" href="{% url 'home' %}">
            <h2>个人博客网站</h2>
        </a>
        <a href="/">首页</a>
        <a href="{% url 'blog_list' %}">博客列表</a>
    </div>
    {% block content %}{% endblock %}
    <style type="text/css">
        *{
            margin: 0px;
            padding: 0px;
        }
        div.nav{
            background-color: #eee;
            border-bottom: 1px solid #ccc;
            padding:10px 5px;
        }
        div.nav a.logo {
            display:inline-block;
            font-size: 120%;
        }
        div.nav a{
            text-decoration: none;
            color:black;
            padding:5px 10px;
        }
    </style>
</body>
</html>

home.html添加如下代码:

<h3 class="home-content">欢迎访问我的网站,随便看</h3>
    <style type="text/css">
        .home-content{
            font-size:222%;
            position:absolute;
            left:50%;
            top:50%;
            transform:translate(-50%,-50%);
        }
    </style>

效果如下图


引用静态文件

静态文件

css文件
js文件
图片等

新建文件夹名为static,在static文件夹下新建base.css,把base.html里面的css代码粘贴到base.css里面。
在settings.py最后添加如下代码:

STATICFILES_DIRS=[
    os.path.join(BASE_DIR,'static'),
]

在base.html的head里面添加如下代码:

 <link rel="stylesheet" href="/static/base.css">

第二种方法加载静态文件
在base.html文件下添加如下代码

{% load staticfiles %}
<link rel="stylesheet" href="{% static 'base.css' %}">

刷新网页,网页没有变化
同理在static文件夹下新建home.css,把home.html文件下的css代码剪切过去,在base.html文件夹下添加一行代码。

{% block header_extends %}{% endblock %}

在home.html文件里面添加一行代码:

{% load staticfiles %}
{% block header_extends %}
<link rel="stylesheet" href="{% static 'home.css' %}">
{% endblock %}

主题内容
尾注

css框架协助前端布局

下载bootstrap3,官网
在static文件夹下新建bootstrap文件夹,放入下载的css、js文件

打开base.html,添加对bootstrap的css和js的引用,

<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script type="text/javascript" src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>

下载最新版的jquery官网,放到static文件夹下

添加对jquery的引用,jquery的引用要放在bootstrap.js的前面

<script type="text/javascript" src="{% static 'jquery-3.3.1.min.js' %}"></script>
<!--要相兼容IE请下载jquery1的版本-->

结构如下图:



,在head标签里面添加一个meta标签

<meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1">

添加导航栏,在base.html文件夹下添加如下代码:

 <div class="navbar navbar-default  navbar-fixed-top" role="navigation">
        <div class="container-fluid">
            <div class="navbar-header">
                <a class="navbar-brand" href="{% url 'home' %}">
                    个人博客网站
                </a>
                 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                  </button>
            </div>
            <div class="collapse navbar-collapse" id="navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="{% block nav_home_active %}{% endblock %}">
                        <a href="{% url 'home' %}">首页</a>
                    </li>
                    <li class="{% block nav_blog_active %}{% endblock %}">
                        <a href="{% url 'blog_list' %}">博客</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>

把对base.css的引用代码修改如下,多余的删除

*{
    margin: 0px;
    padding: 0px;
}
body{
    margin-top: 70px !important;
}

在home.html文件夹下添加如下代码:

{% block nav_home_active %}
    active
{% endblock %}

blog_list.html,blog_detail.html和blog_with_type.html文件都添加如下代码:

{% block nav_blog_active %}active{% endblock %}

结果如下:

bootstrap响应式布局

修改blog_list.html文件,修改后代码如下

{% extends 'base.html' %}
{#页面标题#}
{% block title %}
    我的网站
{% endblock %}
{# 加载静态文件 #}
{% load staticfiles %}
{# 文件引用 #}
{% block header_extends %}
    <link rel="stylesheet" href="{% static 'blog/blog.css' %}">
{% endblock %}
{% block nav_blog_active %}active{% endblock %}
{#页面内容#}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-sm-8 col-md-9 col-lg-10">
            <div class="panel panel-default">
            <div class="panel-heading">
{#                博客列表 (一共有{{ blogs_count }}篇文章)#}
                {% block blog_list_title %}
                    博客列表 (一共有{{ blogs_count }}篇文章)
                {% endblock %}
            </div>
            <div class="panel-body">
                 {% for blog in blogs %}
                     <div class="blog">
                         <h3>
                             <a href="{% url 'blog_detail' blog.pk %}">
                                 {{ blog.title}}
                             </a>
                         </h3>
                         <p class="blog-info">
                             <span class="glyphicon glyphicon-tag"></span>
                             <a href="{% url 'blogs_with_type' blog.blog_type.pk %}">{{ blog.blog_type }}</a>
                             <span class="glyphicon glyphicon-time"></span>
                             {{ blog.created_time|date:'Y-m-d'  }}
                         </p>
                         <p>{{ blog.content|truncatechars:50 }}</p>
                     </div>
                    {% empty %}{# 如果为0篇文章则显示此内容 #}
                     <div class="blog">
                        <h3>暂时没有博客</h3>
                     </div>
                 {% endfor %}
            </div>
            </div>
        </div>
        <div class="hidden-xs col-sm-4 col-md-3 col-lg-2">
            <div class="panel panel-default">
              <div class="panel-heading">博客分类</div>
              <div class="panel-body">
               <ul class="blog-types">
                {% for blog_type in blog_types %}
                    <li>
                        <a href="{% url 'blogs_with_type' blog_type.pk %}">{{ blog_type.type_name }}</a>
                    </li>
                    {% empty %}
                    <li>暂无分类</li>
                {% endfor %}
                </ul>
              </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

修改blog app下的blog_list函数,添加代码如下

context["blog_types"]=BlogType.objects.all()

把全局templates文件夹下的blog文件夹剪切粘贴到blog app下的templates文件夹下



在static文件夹下新建blog.css
写入如下代码:

.blog-types{
    list-style-type: none;
}
div.blog:not(:last-child){
    margin-bottom: 2em;
    padding-bottom: 1em;
    border-bottom: 1px solid #ddd;
}
div.blog h3{
    margin-top: 0.5em;
}
div.blog p.blog-info{
    margin-bottom: 0;
}
ul.blog-info-description{
    list-style-type: none;
    margin-bottom: 1em;
}
ul.blog-info-description li{
    display: inline-block;
    margin-right: 2em;
}
div.blog-content{
    text-indent: 2em;
}

blog app下创建static文件夹,在static文件夹下新建blog文件夹,把blog.css移动到blog app下的static文件夹下的blog文件夹



修改blogs_with_type.html代码

{% extends 'blog/blog_list.html' %}
{#页面标题#}
{% block title %}
    {{blog_type.type_name}}
{% endblock %}
{% block blog_list_title %}
    {{blog_type.type_name}}:
    一共有{{ blogs_count }}篇文章
    <a href="{% url 'blog_list' %}">返回博客列表</a>
{% endblock %}

修改views.py下的blogs_with_type函数代码

 context['blogs_count'] = Blog.objects.filter(blog_type=blog_type).count()
 context["blog_types"]=BlogType.objects.all()

修改blog_detail.html代码如下:

{% extends 'base.html' %}
{# title #}
{% block title %}
    {{ blog.title }}
{% endblock %}
{# nav #}
{% block nav_blog_active %}active{% endblock %}
{# 引用 #}
{% load staticfiles %}
{% block header_extends %}
    <link rel="stylesheet" href="{% static 'blog/blog.css' %}">
{% endblock %}

{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-md-10 col-md-offset-1">
                <h3>{{blog.title}}</h3>
                <ul class="blog-info-description">
                     <li>作者:{{ blog.author}}</li>
                     <li>分类:
                     <a href="{% url 'blogs_with_type' blog.blog_type.pk %}">
                            {{ blog.blog_type }}
                     </a>
                     </li>
                     <li>发表日期:{{ blog.created_time|date:"Y-m-d h:n:s" }}</li>
                </ul>
                <div class="blog-content"> {{blog.content}}</div>
            </div>
        </div>
    </div>
{% endblock %}

最终效果入下:




分页和shell命令行模式

新增或编辑博客内容
博客文章数量较多导致加载过慢,分页加载
shell命令行模式添加博客
1、cmd python manage.py shell

#添加一篇文章
from blog.models import Blog
dir()
# ['Blog', '__builtins__']
Blog.objects.all()
# <QuerySet [<Blog: Blog:第一篇博客>, <Blog: Blog:第二篇博客>, <Blog: Blog:第三篇博客>]>
Blog.objects.count()
# 3
Blog.objects.all().count()
# 3
blog=Blog()
dir()
# ['Blog', '__builtins__', 'blog']
Blog.objects.all()
# <QuerySet [<Blog: Blog:第一篇博客>, <Blog: Blog:第二篇博客>, <Blog: Blog:第三篇博客>]>
blog.title="shell下的第一篇博客"
blog.content="shell下的博客内容"
from blog.models import BlogType
BlogType.objects.all()
# <QuerySet [<BlogType: Django>, <BlogType: 随笔>, <BlogType: 感悟>]>
BlogType.objects.all()[0]
# <BlogType: Django>
blog_type=BlogType.objects.all()[0]
blog.blog_type=blog_type
from django.contrib.auth.models import User
User.objects.all()
# <QuerySet [<User: wjl>]>
user=User.objects.all()[0]
blog.author=user
blog.save()
Blog.objects.all()
# <QuerySet [<Blog: Blog:第一篇博客>, <Blog: Blog:第二篇博客>, <Blog: Blog:第三篇博客>, <Blog: B
log:shell下的第一篇博客>]>
访问localhost:8000/admin
dir(blog)
#查看blog的方法
# ['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__dir__',
# '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '_
#_hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new_
#_', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '_
#_str__', '__subclasshook__', '__weakref__', '_check_column_name_clashes', '_check_field_name_c
#lashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_indexes', '_chec
#k_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_m
#anagers', '_check_model', '_check_model_name_db_lookup_clashes', '_check_ordering', '_check_pr
#operty_name_related_field_accessor_clashes', '_check_single_primary_key', '_check_swappable',
#'_check_unique_together', '_do_insert', '_do_update', '_get_FIELD_display', '_get_next_or_prev
#ious_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta'
#, '_perform_date_checks', '_perform_unique_checks', '_save_parents', '_save_table', '_set_pk_v
#al', '_state', 'author', 'author_id', 'blog_type', 'blog_type_id', 'check', 'clean', 'clean_fi
#elds', 'content', 'created_time', 'date_error_message', 'delete', 'from_db', 'full_clean', 'ge
#t_deferred_fields', 'get_next_by_created_time', 'get_next_by_last_update_time', 'get_previous_
#by_created_time', 'get_previous_by_last_update_time', 'id', 'last_update_time', 'objects', 'pk
#', 'prepare_database_save', 'refresh_from_db', 'save', 'save_base', 'serializable_value', 'tit
#le', 'unique_error_message', 'validate_unique']
blog.last_update_time
# datetime.datetime(2019, 2, 8, 8, 3, 47, 270708, tzinfo=<UTC>)

2、for循环执行新增博客代码

from blog.models import Blog,BlogType
from django.contrib.auth.models import User
user=User.objects.all()[0]
blog_type=BlogType.objects.all()[0]
for i in range(1,31):
    blog=Blog()
    blog.title="for %s" % i
    blog.content="for循环第%s篇文章" % i
    blog.blog_type=blog_type
    blog.author=user
    blog.save()
    
Blog.objects.all().count()
# 34

分页

from django.core.paginator import Paginator
dir()
# ['Blog', 'BlogType', 'Paginator', 'User', '__builtins__', 'blog', 'blog_type', 'i', 'user']
del Blog
dir()
# ['BlogType', 'Paginator', 'User', '__builtins__', 'blog', 'blog_type', 'i', 'user']
exit()

分页器:

from django.core.paginator import Paginator
paginator=Paginator(object_list,each_page_count)
page1=paginator.page(1)

python manage.py shell

from django.core.paginator import Paginator
from blog.models import Blog 
blogs=Blog.objects.all()
blogs.count() 
#34
paginator=Paginator(blogs,10)
# <string>:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class 'blog.models.Blog'> QuerySet.
# <string>:1:无序对象列表警告:分页可能会产生与无序object_list不一致的结果:<class'blog.models.Blog'> QuerySet。
"""
在blog app下的models.py下的Blog添加如下代码:
制造迁移
python manage.py makemigrations
同步数据库
python manage.py migrate
重新开启本地服务
"""
exit()

python manage.py shell

from django.core.paginator import Paginator
from blog.models import Blog 
blogs=Blog.objects.all()
paginator=Paginator(blogs,10)
paginator
#<django.core.paginator.Paginator object at 0x0000000003D85B70>
dir(paginator)
#['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__
#', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt_
#_', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__
#', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_check_object_list_is_ordered'
#, '_get_page', 'allow_empty_first_page', 'count', 'get_page', 'num_pages', 'object_list', 'orp
#hans', 'page', 'page_range', 'per_page', 'validate_number']
paginator.count
# 34
paginator.num_pages
# 4
paginator.page_range
# range(1, 5)
page1=paginator.page(1)
page1
#<Page 1 of 4>
dir(page1)
#['__abstractmethods__', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__
#doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash
#__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__',
# '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__'
#, '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc
#_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'count', 'end_index', 'has_n
#ext', 'has_other_pages', 'has_previous', 'index', 'next_page_number', 'number', 'object_list',
# 'paginator', 'previous_page_number', 'start_index']
help(page1.count)
"""
Help on method count in module collections.abc:

count(value) method of django.core.paginator.Page instance
    S.count(value) -> integer -- return number of occurrences of value
"""
page1.object_list
"""
<QuerySet [<Blog: Blog:for 30>, <Blog: Blog:for 29>, <Blog: Blog:for 28>, <Blog: Blog:for 27>,
 <Blog: Blog:for 26>, <Blog: Blog:for 25>, <Blog: Blog:for 24>, <Blog: Blog:for 23>, <Blog: Bl
og:for 22>, <Blog: Blog:for 21>]>
"""
page1.object_list.count()
# 10
"""
前端:发送请求,请求打开具体的分页内容
后端:处理请求,返回具体分页内容
例如:localhost:8000/blog/page/1
或者:localhost:8000/blog?page=1
第二个是get请求
"""

编写后端处理方法
blog app下的views.py的blog_list函数下添加如下代码:

def blog_list(request):
    blogs_all_list=Blog.objects.all()
    paginator=Paginator(blogs_all_list,10) #每十页进行分页
    page_num = request.GET.get('page',1)  #字典,如果没有默认给1,获取页码参数
    page_of_blogs=paginator.get_page(page_num)
    #得到无效字符,自动返回1
    context={}
    #context["blogs"]=page_of_blogs.object_list
    context['page_of_blogs']=page_of_blogs
    context["blogs_count"]=Blog.objects.all().count()
    context["blog_types"]=BlogType.objects.all()
    return render_to_response('blog/blog_list.html',context)

修改blog_list.html下的代码:
把<div class="panel-body">下的
{% for blog in blogs %}```` 改为{% for blog in page_of_blogs.object_list %}````
在<div class="col-sm-8 col-md-9 col-lg-10">新建div,添加如下代码:

<div>
    <nav aria-label="Page navigation">
      <ul class="pagination">
        {% if page_of_blogs.has_previous %}
            <li>
              <a href="?page={{ page_of_blogs.previous_page_number }}" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
              </a>
            </li>
        {% else %}
        {% endif %}
        {% for page_num in page_of_blogs.paginator.page_range %}
             <li><a href="?page={{ page_num }}">{{ page_num }}</a></li>
        {% endfor %}
      {% if page_of_blogs.has_next %}
          <li>
              <a href="?page={{ page_of_blogs.next_page_number }}" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
              </a>
            </li>
          {% else %}
      {% endif %}
      </ul>
    </nav>
</div>

优化分页展示

页码很多怎么显示
blog app views.py下的blog_list函数代码

paginator=Paginator(blogs_all_list,10) #每十篇进行分页

修改为

paginator=Paginator(blogs_all_list,2) #每2篇进行分页

优化:
当前页高亮
不要过多页码选择,凸显页面布局
修改blog_list.html
在{# 全部页码 #}下修改为如下代码:

{% for page_num in page_of_blogs.paginator.page_range %}
    {% if page_num == page_of_blogs.number %}
          <li class="active">
            <span>{{ page_num }}</span>
          </li>
        {% else %}
         <li>
            <a href="?page={{ page_num }}">{{ page_num }}</a>
         </li>
    {% endif %}

{% endfor %}

blog app下views.py修改blog_list函数代码

currentr_page_num=page_of_blogs.number #获取当前页码
page_range=[currentr_page_num-2,currentr_page_num-1,currentr_page_num,currentr_page_num+1,currentr_page_num+2]
context['page_range']=page_range

修改blog_list.html
在{# 全部页码 #}下修改为如下代码:

 {% for page_num in page_range %}

blog app下views.py修改blog_list函数代码

    page_range=list(range(max(currentr_page_num-2,1),currentr_page_num))+list(range(currentr_page_num,min(currentr_page_num+2,paginator.num_pages)+1))


在blog app下的views.py下的blog_list函数下添加如下代码:

#加上省略页码标记
if page_range[0]-1 >=2:#3-1>=2 第5页开始
    page_range.insert(0,'...')
if paginator.num_pages-page_range[-1]>=2:
    page_range.append("...")#15<=17-2


在blog app下的views.py下的blog_list函数下添加如下代码:

if page_range[0]!=1:
    page_range.insert(0,1)
if page_range[-1]!=paginator.num_pages:
    page_range.append(paginator.num_pages)


修改blog_list.html文件下的{#全部代码#}下的{% else %}代码

{% if page_num == '...' %}
    <li><span>{{ page_num }}</span></li>
    {% else %}
    <li><a href="?page={{ page_num }}">{{ page_num }}</a></li>
{% endif %}

找到blog_list.html里面的一共有多少篇博客的代码,剪切粘贴至</nav>前面的新建的<p></p>标签里面
代码如下:

 共有{{ page_of_blogs.paginator.count }}篇文章,共{{ page_of_blogs.paginator.num_pages }}页,当前第{{ page_of_blogs.number }}页

为<ul class="pagination">上的nav/div添加一个class为mypaginator,修改blog.css
添加如下代码:

nav.mypaginator{
text-align: center;
}

在blog app下的views.py下的blogs_with_type函数删除原本代码,添加如下代码:

context={}
blog_type=get_object_or_404(BlogType,pk=blog_type_pk)
blogs_all_list = Blog.objects.filter(blog_type=blog_type)
paginator = Paginator(blogs_all_list, 2)  # 每十篇进行分页
page_num = request.GET.get('page', 1)  # 字典,如果没有默认给1,获取页码参数
page_of_blogs = paginator.get_page(page_num)  # 得到无效字符,自动返回1
currentr_page_num = page_of_blogs.number  # 获取当前页码
page_range = list(range(max(currentr_page_num - 2, 1), currentr_page_num)) + \
             list(range(currentr_page_num, min(currentr_page_num + 2, paginator.num_pages) + 1))
# 获取当前页码以及前后各两页的页码范围
# 加上省略页码标记
if page_range[0] - 1 >= 2:  # 3-1>=2 第5页开始
    page_range.insert(0, '...')
if paginator.num_pages - page_range[-1] >= 2:
    page_range.append("...")  # 15<=17-2
# 加上首页和尾页
if page_range[0] != 1:
    page_range.insert(0, 1)
if page_range[-1] != paginator.num_pages:
    page_range.append(paginator.num_pages)
context['blog_type'] = blog_type
context["blogs"]=page_of_blogs.object_list
context['page_of_blogs'] = page_of_blogs
context["blog_types"] = BlogType.objects.all()
context['page_range'] = page_range
return render_to_response('blog/blogs_with_type.html',context)

blog app下的views.py下定义全局变量

each_page_blogs_number=2
#paginator=Paginator(blogs_all_list,2),2改为each_page_blogs_number

公用全局设置可以放在settings统一管理,在settings.py下添加自定义参数EACH_PAGE_BLOGS_NUMBER=7
blog app下的views.py下添加如下代码:

from django.conf import settings
#paginator=Paginator(blogs_all_list,2),2改为settings.EACH_PAGE_BLOGS_NUMBER

注释掉blog_with_type.html的代码

{#    一共有{{ page_of_blogs.paginator.count }}篇文章#}

上下篇博客和按月分类

filter筛选条件:
名称 表示
直接筛选 =
大于 __gt(greater than)
大于等于 __gte
小于 __lt(less than)
小于等于 __lte
包含 __contains(加i忽略大小写)
开头是 __startwith
结尾是 __endwith
其中之一 __in
范围 __range

在blog app下的views.py里面的blog_detail函数添加如下代码:

    context["previous_blog"]=Blog.objects.filter(created_time__gt=blog.created_time).last()#[-1]
    context["next_blog"]=Blog.objects.filter(created_time__lt=blog.created_time).first()#[0]

打开blog_detail.html
<div class="blog-content"> {{blog.content}}</div>后面添加如下代码:

<div class="blog-more">
    <p>
        {% if previous_blog %}
            <a href="{% url 'blog_detail' previous_blog.pk %}">上一篇:{{ previous_blog.title }} </a>
        {% else %}
            木有了
        {% endif %}
    </p>
    <p>
        {% if next_blog %}
             <a href="{% url 'blog_detail' next_blog.pk %}">下一篇:{{ next_blog.title }}</a>
        {% else %}
            木有了
        {% endif %}
    </p>
</div>

blog.css添加如下代码:

div.blog-more{
    margin-top: 1em;
}

开启shell模式
python manage.py shell

from blog.models import Blog
Blog.objects.filter(title__contains="for")
Blog.objects.filter(title__icontains="for")
# SQLite不支持
Blog.objects.filter(id__in=[1,3,4])
Blog.objects.filter(id__range=(1,4))
exclude排除条件

用法和filter一样,都是得到查询QuerySet,相当于filter条件的取反

Blog.objects.exclude(pk=3)
Blog.objects.exclude(pk<=3)
条件中的双下划线:
  • 字段查询类型
  • 外键拓展
  • 日期拓展
  • 支持链式查询
Blog.objects.exclude(created_time__year=2019)# month

按日期分类

在blog app下的views.py添加如下代码:

def blogs_with_date(request,year,month):
    blogs_all_list = Blog.objects.filter(created_time__year=year,created_time__month=month)
    paginator = Paginator(blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)  # 每十篇进行分页
    page_num = request.GET.get('page', 1)  # 字典,如果没有默认给1,获取页码参数
    page_of_blogs = paginator.get_page(page_num)  # 得到无效字符,自动返回1
    currentr_page_num = page_of_blogs.number  # 获取当前页码
    page_range = list(range(max(currentr_page_num - 2, 1), currentr_page_num)) + \
                 list(range(currentr_page_num, min(currentr_page_num + 2, paginator.num_pages) + 1))
    # 获取当前页码以及前后各两页的页码范围
    # 加上省略页码标记
    if page_range[0] - 1 >= 2:  # 3-1>=2 第5页开始
        page_range.insert(0, '...')
    if paginator.num_pages - page_range[-1] >= 2:
        page_range.append("...")  # 15<=17-2
    # 加上首页和尾页
    if page_range[0] != 1:
        page_range.insert(0, 1)
    if page_range[-1] != paginator.num_pages:
        page_range.append(paginator.num_pages)
    #context['blog_type'] = blog_type
    context = {}
    context["blogs_with_date"]="%s年%s月" % (year,month)
    context["blogs"] = page_of_blogs.object_list
    context['page_of_blogs'] = page_of_blogs
    context["blog_types"] = BlogType.objects.all()
    context['page_range'] = page_range
    context["blog_dates"] = Blog.objects.dates('created_time', 'month', order="DESC")
    return render_to_response('blog/blogs_with_date.html',context)

在blog app下的urls.py添加如下代码:

path('date/<int:year>/<int:month>',views.blogs_with_date,name="blogs_with_date")

打开blog_list.html文件,在<div class="panel panel-default">同级的建立一个<div class="panel panel-default"></div>
里面添加如下代码:

<div class="panel panel-default">
    <div class="panel-heading">
        日期归档
    </div>
    <div class="panel-body">
        <ul>
             {% for blog_date in blog_dates %}
                <li>{{ blog_date|date:"Y年-m月" }}</li>
            {% endfor %}
        </ul>
    </div>
</div>

在blog app下的views.py的blog_list函数添加如下代码:

context["blog_dates"]=Blog.objects.dates('created_time','month',order="DESC")# field ['year','month','day'] ['ASC','DESC']

修改base.css添加如下代码:

ul{
    list-style: none;
    /*去掉li的圆点*/
}

新建blogs_with_date.html
里面添加如下内容:

{% extends 'blog/blog_list.html' %}
{% block title %}
    {{blog_type.type_name}}
{% endblock %}
{% block blog_list_title %}
    日期归档:{{blogs_with_date}}:
    <a href="{% url 'blog_list' %}">返回博客列表</a>
{% endblock %}
整理重复代码

blog app下views.py的代码整理如下:

from django.shortcuts import render_to_response,get_object_or_404
from .models import Blog,BlogType
from django.core.paginator import Paginator
from django.conf import settings
# Create your views here.
def get_blog_list_common_data(request,blogs_all_list):
    paginator = Paginator(blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)  # 每十篇进行分页
    page_num = request.GET.get('page', 1)  # 字典,如果没有默认给1,获取页码参数
    page_of_blogs = paginator.get_page(page_num)  # 得到无效字符,自动返回1
    currentr_page_num = page_of_blogs.number  # 获取当前页码
    page_range = list(range(max(currentr_page_num - 2, 1), currentr_page_num)) + \
                 list(range(currentr_page_num, min(currentr_page_num + 2, paginator.num_pages) + 1))
    # 获取当前页码以及前后各两页的页码范围
    # 加上省略页码标记
    if page_range[0] - 1 >= 2:  # 3-1>=2 第5页开始
        page_range.insert(0, '...')
    if paginator.num_pages - page_range[-1] >= 2:
        page_range.append("...")  # 15<=17-2
    # 加上首页和尾页
    if page_range[0] != 1:
        page_range.insert(0, 1)
    if page_range[-1] != paginator.num_pages:
        page_range.append(paginator.num_pages)

    context = {}
    # context["blogs"]=page_of_blogs.object_list
    context['page_of_blogs'] = page_of_blogs
    context["blogs_count"] = Blog.objects.all().count()
    context["blog_types"] = BlogType.objects.all()
    context['page_range'] = page_range
    context["blog_dates"] = Blog.objects.dates('created_time', 'month', order="DESC")
    return context
def blog_list(request):
    blogs_all_list=Blog.objects.all()
    context=get_blog_list_common_data(request,blogs_all_list)
    return render_to_response('blog/blog_list.html',context)
def blogs_with_type(request,blog_type_pk):
    blog_type=get_object_or_404(BlogType,pk=blog_type_pk)
    blogs_all_list = Blog.objects.filter(blog_type=blog_type)
    context = get_blog_list_common_data(request, blogs_all_list)
    context['blog_type'] = blog_type
    return render_to_response('blog/blogs_with_type.html',context)
def blogs_with_date(request,year,month):
    blogs_all_list = Blog.objects.filter(created_time__year=year,created_time__month=month)
    context = get_blog_list_common_data(request, blogs_all_list)
    context["blogs_with_date"]="%s年%s月" % (year,month)
    return render_to_response('blog/blogs_with_date.html',context)
def blog_detail(request,blog_pk):
    context={}
    blog=get_object_or_404(Blog,pk=blog_pk)
    context["previous_blog"]=Blog.objects.filter(created_time__gt=blog.created_time).last()
    context["next_blog"]=Blog.objects.filter(created_time__lt=blog.created_time).first()#[0]
    context["blog"]=blog
    #Blog.objects.all(pk=blog_pk)
    return render_to_response("blog/blog_detail.html",context)

博客分类统计

在blog app下的views.py的get_blog_list_common_data函数添加如下代码

#获取博客分类的对应博客数量
blog_types=BlogType.objects.all()
blog_types_list=[]
for blog_type in blog_types:
    blog_type.blog_count=Blog.objects.filter(blog_type=blog_type).count()
    blog_types_list.append(blog_type)
 context["blog_types"] = blog_types_list

在博客分类下找到{{ blog_type.type_name }}在他的后面追加一下代码:

({{ blog_type.blog_count }})

刷新页面查看:


annotate拓展查询字段
(1)blog app下的models.py的Blog类修改一行代码为:

blog_type=models.ForeignKey(BlogType,on_delete=models.DO_NOTHING,related_name="blog_blog")

注释掉刚刚添加的代码,添加如下代码:

from django.db.models import Count
BlogType.objects.annotate(Count('blog_blog'))

(2)注释掉刚刚添加的代码,添加如下代码:

from django.db.models import Count
BlogType.objects.annotate(blog_count=Count('blog'))

获取日期归档对应的博客数量

在blog app下的views.py的get_blog_list_common_data函数添加如下代码

#获取日期归档对应的博客数量
blog_dates=Blog.objects.dates('created_time', 'month', order="DESC")
blog_dates_dict={}
for blog_date in blog_dates:
    blog_count=Blog.objects.filter(created_time__year=blog_date.year,created_time__month=blog_date.month).count()
    blog_dates_dict[blog_date]=blog_count
context["blog_dates"] = blog_dates_dict

在日期归档下找到<div class="panel-body">在他的<ul></ul>里面追加一下代码:

{% for blog_date,blog_count in blog_dates.items %}
    <li>
        <a href="{% url 'blogs_with_date' blog_date.year blog_date.month %}">
            {{ blog_date|date:"Y年-m月" }}({{ blog_count }})
        </a>
    </li>
{% endfor %}

刷新页面查看:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容