安装环境
Pipenv 创建和管理虚拟环境
首先通过命令pip install pipenv
安装 Pipenv。
安装 Django
django 的官方文档对 如何安装 django 给出了详细且明确的指导,不过我们目前用不上这些,只需使用 pipenv 命令就可以解决问题。进入项目根目录,运行:
pipenv install django==2.2.3
建立 Django 工程
万事已经具备了,让我们来建立 django 项目工程。
django 工程(Project)是我们项目代码的容器,例如我们博客项目中所有的代码(包括 django 为我们自动生成的以及我们自己写的)都包含在这个工程里。其实说通俗一点就是用一个文件夹把一系列 Python 代码文件和 django 配置文件包裹起来,这个文件夹就可以看做一个 django 工程。我们不必亲自动手新建这个文件夹和代码文件,django 的内置命令已经帮我们做了这些事情。例如我把博客工程的代码放在E:\CODE\python目录下,工程名我把它叫做 blogproject,那么在项目根目录运行如下命令创建工程:
pipenv run django-admin startproject DjangoBlog E:\CODE\python\Blog
创建应用
现在就来创建我们的 django 博客应用,我把它命名为 blog。进入到 manage.py 文件所在的目录(即项目根目录)下,运行下面命令即可建立一个 blog 应用:
pipenv run python manage.py startapp blog
python manage.py createsuperuser # 创建后台用户
设计博客的数据库表结构
加入文章含有的内容如下表所示:
id | 标题 | 正文 | 发表时间 | 分类 | 标签 |
---|---|---|---|---|---|
1 | title 1 | text 1 | 2019-7-1 | django | django 学习 |
2 | title 2 | text 2 | 2019-7-2 | django | django 学习 |
3 | title 3 | text 3 | 2019-7-3 | Python | Python 学习 |
数据库表设计成这样其实已经可以了,但是稍微分析一下我们就会发现一个问题,这 3 篇文章的分类和标签都是相同的,这会产生很多重复数据,当数据量很大时就浪费了存储空间。不满足数据库的第三范式
博客数据库模型的代码
# blog.models.py
class Post(models.Model):
pass
Django 迁移、操作数据库
pipenv run python manage.py makemigrations
pipenv run python manage.py migrate
视图解析
接下来我们分析一下下面的4个文件:urls.py, views.py, models.py, index.html
urls.py
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.index, name='index'),
path('posts/<int:pk>/', views.detail, name='detail'),
]
views.py
import re
import markdown
from django.shortcuts import get_object_or_404, render
from django.utils.text import slugify
from markdown.extensions.toc import TocExtension
from .models import Post
def index(request):
post_list = Post.objects.all().order_by('-created_time')
return render(request, 'blog/index.html', context={'post_list': post_list})
models.py
class Post(models.Model):
# 文章标题
title = models.CharField('标题', max_length=70)
# 文章正文,我们使用了 TextField。
# 存储比较短的字符串可以使用 CharField,但对于文章的正文来说可能会是一大段文本,因此使用 TextField 来存储大段文本。
body = models.TextField('正文')
# 这两个列分别表示文章的创建时间和最后一次修改时间,存储时间的字段用 DateTimeField 类型。
created_time = models.DateTimeField('创建时间', default=timezone.now)
modified_time = models.DateTimeField('修改时间')
# 文章摘要,可以没有文章摘要,但默认情况下 CharField 要求我们必须存入数据,否则就会报错。
# 指定 CharField 的 blank=True 参数值后就可以允许空值了。
excerpt = models.CharField('摘要', max_length=200, blank=True)
# 文章作者,这里 User 是从 django.contrib.auth.models 导入的。
# django.contrib.auth 是 Django 内置的应用,专门用于处理网站用户的注册、登录等流程,User 是 Django 为我们已经写好的用户模型。
# 这里我们通过 ForeignKey 把文章和 User 关联了起来。
# 因为我们规定一篇文章只能有一个作者,而一个作者可能会写多篇文章,因此这是一对多的关联关系,和 Category 类似。
author = models.ForeignKey(User, verbose_name='作者', on_delete=models.CASCADE)
class Meta:
verbose_name = '文章'
verbose_name_plural = verbose_name
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.modified_time = timezone.now()
super().save(*args, **kwargs)
# 自定义 get_absolute_url 方法
# 记得从 django.urls 中导入 reverse 函数
def get_absolute_url(self):
return reverse('blog:detail', kwargs={'pk': self.pk})
index.html
{% extends 'base.html' %}
{% block main %}
{% for post in post_list %}
<article class="post post-{{ post.pk }}">
<header class="entry-header">
<span class="post-author"><a href="#">{{ post.title }} {{ post.author }}</a></span>
</header>
</div>
</article>
{% empty %}
<div class="no-post">暂时还没有发布的文章!</div>
{% endfor %}
{% endblock main %}
python manage.py createsuperuser
#pip install Pygments
#pygmentize -S default -f html -a .codehilite > code.css
pipenv install Faker
pipenv run python -m scripts.fake
pipenv install django-haystack