在Ubuntu 20.04 搭建 Django 开发环境 以及 快速构建一个简单的 Blog

周末整理旧日志发现在 2013 年学习 Django 时写的 《Django:快速搭建简单的Blog》一文得到不少网友的引用,激励了我的创作热情。所以就把旧文重新写一下,毕竟现在的 Django 已经更新到 3.1.1 版本了。

本文分两部分:

第一部分是介绍如何在 Ubuntu 20.04 上搭建 Django 开发环境;

第二部分是介绍快速地使用 Django 构建一个简单的 Blog ,供入门参考。

在 Ubuntu 20.04 搭建 Django 开发环境

1. 设置 Python

Ubuntu 20.04 中,默认的 Python 版本为 Python3, 在终端只能通过 python3 命令调用 Python解释器,不能像以往的 Ubuntu 发行版本那样直接通过 python 命令调用。

检查 python 命令:

1
$ python

为了方便后续工作,可以为 Python3 创建符号链接把 python3 配置为直接通过 python 命令调用。

使用以下命令为 Python3 创建一个符号链接:

1
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1

至此,Python3 的配置已经完成。

2. Pip 包管理程序的安装与配置

使用 apt 命令安装 python3-pip:

1
$ sudo apt install python3-pip -y

python3-pip 安装完毕后,把 pip3 设置为默认的 pip 版本:

sudo update-alternatives --installpip /usr/bin/pip3 1
1
$ sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

检查 pip 的版本:

1
$ pip --version

3. 使用 Virtualenv 安装 Django

安装 Django 框架的方式有多种,本人推荐使用 Virtualenv 虚拟环境安装。因为在以后的开发中,不同的应用可能需要不同的 Python 开发环境,而Virtualenv 可以用来为应用创建一套“隔离”的Python运行环境,而不会干扰到系统中其他的 Python 应用。

安装 Python virtualenv 包:

1
$ sudo pip install virtualenv


注意:如果由于某些不可以描述的原因导致 pip 安装缓慢,可以尝试临时修改源的方法:

可以在使用pip的时候在后面加上-i参数,指定pip源。

例如,对上面的命令指定临时源:

1
$ sudo pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple

国内的一些源:


根据个人需要,选择合适的目录创建 Python 虚拟环境 my_env。

我这里的选择的目录是: /home/matrix/Workspace/Python/Virtualenv

创建 Python 虚拟环境:

1
2
$ cd ~/Workspace/Python/Virtualenv
$ virtualenv myenv

激活虚拟环境:

1
2
$ cd my_env
$ source bin/active

安装 2.2 LTS 版本的 Django 框架:

1
$ django-admin --version

检查 Django 版本:

1
$ django-admin --version

看到以上的版本号输出,说明已经安装成功了。

若想切换为正常的用户环境,可以使用以下的命令:

1
$ deactivate

快速构建简单的 Blog

按第一部分的介绍搭建好 Django 的开发环境后,接下来将介绍如何快速地创建一个 Blog。

1. 创建名为 my_site 的工程项目

使用 django-admin.py 工具创建工程项目:

1
$ django-admin.py startproject mysite

项目的文件结构如下:

  • manage.py : Django 项目里面的工具,通过它可以调用 Django Shell 和数据库等。
  • settings.py : 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
  • urls.py : 项目的 URL 声明,就像你网站的 “目录” ,负责把 URL 模式映射到应用程序。
  • init.py : 一个空文件,告知 Python 当前目录应被认为是一个 Python 包。
  • wsgi.py : 作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。

2. 运行开发服务器

切换到工程项目里,执行以下指令运行开发服务器:

1
$ python manage.py runserver

然后打开浏览器,在地址栏输入 127.0.0.1:8000 访问站点。

3. 创建 Blog 应用

在 mysite 目录下,使用 manage.py 创建 blog 应用:

1
$ python manage.py startapp blog

blog 应用的文件结构如下:

4. 设计 Blog应用的 Model

在 blog 目录下的 models.py 是 blog 应用的核心文件之一,是定义 blog 数据结构的地方。

用编辑器打开models.py ,新添加BlogPost类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from django.db import models

from django.contrib.auth.models import User

STATUS = (
(0,"Draft"),
(1,"Publish")
)

class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
updated_on = models.DateTimeField(auto_now= True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)

class Meta:
ordering = ['-created_on']

def __str__(self):
return self.title

5.设置数据库

Dajango支持主流的数据库服务器(MySQL,PostgreSQL,Oracle和MSSQL),但本项目使用SQLite,这里之需要通过一条简单的命令可以创建SQLite数据库。

在终端 切换到工程主目录mysite/下,执行如下命令:

1
2
$ python manage.py makemigrations
$ python manage.py migrate

运行上述的数据迁移指令后,会生成框架自带的相关数据表和 我们自己创建的 Post 数据表。

创建后台管理员账号:

1
$ python manage.py createsuperuser

在浏览器地址栏输入:127.0.0.1:8000/admin

成功登录有就会见到后台管理界面:

6. 把 Post 模型添加到管理员后台

打开 blog/admin.py 文件,注册 BlogPost 模型:

1
2
3
4
5
6
from django.contrib import admin

from .models import Post

# Register your models here.
admin.site.register(Post)

保存文件,刷新管理员后台页面:

7.添加文章

点击 Posts右侧的Add 按钮,添加文章。

修改 blog/admin.py 文件,为它添加一个admin.ModelAdmin的子类BlogPostAdmin.以列表形式显示BlogPost的标题和时间,可以让admin的BlogPost界面更加美观。

原来的代码:

1
2
3
4
5
6
from django.contrib import admin

from .models import Post

# Register your models here.
admin.site.register(Post)

修改后的代码:

1
2
3
4
5
6
7
8
9
10
from django.contrib import admin
from .models import Post

class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'status','created_on')
list_filter = ("status",)
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}

admin.site.register(Post, PostAdmin)

刷新页面后,可看到效果:

8. 创建 Blog 的视图

从Django的角度看,一个页面具有三个典型的组件:

  • 一个模板(template):模板负责把传递进来的信息显示出来。
  • 一个视图(viw):视图负责从数据库获取需要显示的信息。
  • 一个URL模式:它负责把收到的请求和你的试图函数匹配,有时候也会向视图传递一些参数。

编辑视图:

打开 blog/views.y ,并编辑:

1
2
3
4
5
6
7
8
9
10
from django.views import generic
from .models import Post

class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'

class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'

为视图添加 URL模式

在 blog 应用目录创建 urls.py 文件,然后编辑它:

blog/urls.py

1
2
3
4
5
6
7
from . import views
from django.urls import path

urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
]

把 blog 应用的 URLS 添加到项目的 urls.py 文件中:

mysite/urls.py

1
2
3
4
5
6
7
from django.contrib import admin
from django.urls import path, include

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

9. 为视图创建模版

在工程目录创建 templates 文件夹:

然后打开 mysite/settings.py 文件,在 BASE_DIR 底下 添加模版路径:

1
TEMPLATES_DIRS = os.path.join(BASE_DIR,'templates')

即, 在 setting.py 中,找到 TEMPLATES 位置,编辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# Add 'TEMPLATE_DIRS' here
'DIRS': [TEMPLATES_DIR],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},

在 templates 文件夹里面,创建 base.html 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<!DOCTYPE html>
<html>
<head>
<title>Matrix Tech</title>

<link
href="https://fonts.googleapis.com/css?family=Roboto:400,700"
rel="stylesheet">
<meta name="google" content="notranslate" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>

</head>

<body>
<style>
body {
font-family: "Roboto", sans-serif;
font-size: 17px;
background-color: #fdfdfd;
}

.shadow{
box-shadow: 0 4px 2px -2px rgba(0,0,0,0.1);
}
.btn-danger {
color: #fff;
background-color: #f00000;
border-color: #dc281e;
}

.masthead {
background:#3398E1;
height: auto;
padding-bottom: 15px;
box-shadow: 0 16px 48px #E3E7EB;
padding-top: 10px;
}
</style>

<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow" id="mainNav">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'home' %}" >Matrix Tech</a>
<button
class="navbar-toggler navbar-toggler-right"
type="button"
data-toggle="collapse"
data-target="#navbarResponsive"
aria-controls="navbarResponsive"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">

<li class="nav-item text-black">
<a
class="nav-link text-black font-weight-bold"
href="#"
>About</a
>
</li>
<li class="nav-item text-black">
<a
class="nav-link text-black font-weight-bold"
href="#"
>Policy</a
>
</li>
<li class="nav-item text-black">
<a
class="nav-link text-black font-weight-bold"
href="#"
>Contact</a
>
</li>
</ul>
</div>
</div>
</div>
</nav>


{% block content %}
<!-- Content Goes here -->
{% endblock content %}

<!-- Footer -->
<footer class="py-3 bg-grey">
<p class="m-0 text-dark text-center ">Copyright &copy; Matrix Tech</p>
</footer>

</body>
</html>

在 templates 文件夹里面,创建 index.html 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{% extends "base.html" %}

{% block content %}
<style>

body {
font-family: "Roboto", sans-serif;
font-size: 18px;
background-color: #fdfdfd;
}

.head_text{
color: white;
}
.card{
box-shadow: 0 16px 48px #E3E7EB;
}
</style>

<header class="masthead" >
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class=" col-md-8 col-md-10 mx-auto">
<div class="site-heading">
<h3 class=" site-heading my-4 mt-3 text-white"> 欢迎访问我的博客 </h3>
<p class="text-light">Write the Code. Change the World. &nbsp
</p>
</div>
</div>
</div>
</div>
</div>
</header>

<div class="container">
<div class="row">

<!-- Blog Entries Column -->
<div class="col-md-8 mt-3 left">
{% for post in post_list %}
<div class="card mb-4" >
<div class="card-body">
<h2 class="card-title">{{ post.title }}</h2>
<p class="card-text text-muted h6">{{ post.author }} | {{ post.created_on}} </p>

<p class="card-text">{{post.content|slice:":200" }}</p>
<a href="{% url 'post_detail' post.slug %}" class="btn btn-primary">Read More &rarr;</a>
</div>

</div>
{% endfor %}
</div>
{% block sidebar %}
{% include 'sidebar.html' %}
{% endblock sidebar %}
</div>
</div>
{%endblock%}

在 templates 文件夹里面,创建 sidebar.html 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% block sidebar %}

<style>
.card{
box-shadow: 0 16px 48px #E3E7EB;
}

</style>

<!-- Sidebar Widgets Column -->
<div class="col-md-4 float-right ">
<div class="card my-4">
<h5 class="card-header">About Us</h5>
<div class="card-body">
<p class="card-text"> Hi, 我是 Matrix, 一名全栈工程师, 熟悉前后端开发和运维各个环节.</p>
<a href=""
class="btn btn-danger">Know more!</a>
</div>
</div>
</div>

{% endblock sidebar %}

在浏览器访问 http://127.0.0.1:8000/

创建 post_detail.html 文件

mysite/templates/post_detail.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% extends 'base.html' %} {% block content %}

<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h1>{% block title %} {{ object.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class="card-text ">{{ object.content | safe }}</p>
</div>
</div>
{% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
</div>
</div>

{% endblock content %}

点击页面文章摘要下的 Read More 可以访问 Post 的详细内容:

后记

此教程可以作为 Django 入门练习,通过教程学可以会在 Ubuntu 上搭建 Django 开发环境,以及如何使用 Django 框架。教程是采用『线索性』书写方式,跟着教程一步步练习最终就会搭建出一個简易博客。由于此教程只是展示如何简单入门,所以很多开发细节被忽略,如果希望进一步了解 Django 的使用可以参阅 Django 官方手册。

项目源代码地址: https://github.com/matrixtechxyz/Django_Mysite

單片機項目開發紀錄

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×