我们已经在上一篇笔记中成功的安装和配置了Django的学习环境。从本篇笔记开始,我们将正式开始Django之旅,汪咔咔。
背景知识:MVC模式
首先,要熟悉一下MVC模式。记得大狗刚刚从大学毕业时,第一份工作是用ASP编写政府OA系统,那时候典型的代码风格是这样的:
// 前面省略
<% if userInRole('DocumentAuditPerson') then %>
<%
function userInRole(roleName)
dim conn as ADOConnection;
dim rs as recordser
// 代码省略
if rs.count > 0 then
return true
else
return false
end if
end function
%>
// 后面省略
<% else %>
<% end if %>
嗯,差不多是这个样子吧。
大家可以发现,当时的代码存在以下几个问题:
- HTML代码和业务逻辑代码交杂,阅读/调试困难
- 没有很好的代码封装造成大量的冗余代码,单个代码文件尺寸较大
为解决上述问题,MVC模式顺势而生。简单的说,MVC模式将程序分解为以下三部分:
- 模型(Model):管理数据,商业逻辑和应用规则
- 视图(View):负责数据的外部呈现,例如,同样的数据可以使用图表视图以柱状图进行呈现,也可以使用表格视图现实数据的详细信息
- 控制器(Controller):向模型发送命令,更新模型状态,并更新视图信息
如此一来,如果应用的配色和字体需要修改,只需要修改视图代码;如果商业逻辑发生了变化,也仅仅需要修改模型代码。而且模型、视图和控制器的解耦也为代码复用提供了可能。
而Django,也是遵从MVC模式开发的,强烈建议对MVC模式不熟悉的童鞋在阅读后续内容之前,先简单的了解一下MVC模式的相关信息。
如果想获得关于MVC的详细信息,请点击这里
创建项目和应用
创建项目
我们的博客开发,现在正式开始了。首先,需要为博客创建项目(project),和大多数的软件开发应用一样,Django的代码也是通过项目进行管理的。
我们打开了命令行工具(大狗用的是Macbook上的iTerm),键入以下代码:
django-admin.py startproject DjangoQuickTour
(如果是Windows电脑,不能直接执行python文件,可能需要在命令行前附加“python”,下同)
命令瞬间结束,似乎什么都没有发生。然而,当我们回到存储代码的目录,发现Django已经偷偷的创建了以下文件:
.
├── DjangoQuickTour
│ ├── DjangoQuickTour
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── manage.py
└── LICENSE
下面,大狗来解释一下上面这些文件的用途:
- LICENSE: 这个是GitHub中的版权信息文件,大家暂时可以无视
- __init__.py: python的包文件,会将所在的目录变成一个python的包(package)。包是一个或者多个python模块的集合,将目录变成包后,就可以使用点记号(dot notation)指定包中的某个部分了(例如, dog.bark)
- manage.py: Django项目管理工具
- settings.py: Django项目的配置文件,其中包含了数据库、调试标志等信息
- urls.py: URL映射文件,用于将用户请求的URL以一定的模式映射到程序模块
运行开发服务器
为了便于程序开发调试,Django贴心的内置了一个轻量级的开发服务器。在日常开发中,我们没有必要频繁的将程序部署到Apache,Nginx等应用服务器中,开发服务器完全可以满足开发过程中的预览、调试功能。* (但是,不要将开发服务器用于生产环境!不要将开发服务器用于生产环境!不要将开发服务器用于生产环境!重要的事情说三遍!)*
运行开发服务器,就要用到大狗前面提到过的manage.py文件。现在,让我们在命令行工具中键入:
./manage.py runserver
命令行输出了如下信息:
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
January 01, 2017 - 06:48:59
Django version 1.10.4, using settings 'DjangoQuickTour.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
其他的信息暂时可以无视,我们需要关心的只有“http://127.0.0.1:8000/”。 打开浏览器,键入“http://127.0.0.1:8000/”, 然后回车,哦耶!
如果8000端口被占用,或者电脑有安全策略禁止使用该端口,也可以通过在上面的命令后面附加端口号参数来指定其它端口,就像这样:
./manage.py runserver 8001
如果我们在自己的电脑开发Django应用,现在其它电脑上展示自己的工作成果,也可以运行以下命令:
./manage.py runserver 0.0.0.0:8000
创建应用
接下来,我们要在刚刚创建的项目中创建博客对应的应用(app)。还是需要使用命令行工具,在其中运行:
./manage.py startapp blog
仍然似乎是什么都没有发生的样子,然而刷新了一下目录,我们会发现Django又偷偷的在项目目录中加了一个blog目录:
.
├── DjangoQuickTour
│ ├── DjangoQuickTour
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── settings.py
│ │ ├── settings.pyc
│ │ ├── urls.py
│ │ ├── urls.pyc
│ │ ├── wsgi.py
│ │ └── wsgi.pyc
│ ├── blog
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── migrations
│ │ │ └── __init__.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ └── views.py
│ ├── db.sqlite3
│ └── manage.py
└── LICENSE
看得出,和项目一样,Django中的应用也是以包的形式存在的。除创建blog目录以及包含在其中的文件以外,Django还在项目目录里创建了一个SQLite数据库,诶嘿,这个可以有!
除创建blog目录和相关文件外,为了在项目中使用该应用,我们还需要将新创建的应用“挂接”到项目上。方法,是打开DjangoQuickTour目录下的settings.py文件,找到以下代码段:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
我们将我们新创建的blog应用添加到INTALLED_APPS中,修改后的代码段应该是:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
注意:INTALLED_APPS是元组(tuple),不要忘记结尾还有一个逗号。
模型和数据库
接下来,我们将完成应用中最核心的部分,即定义博客模块的数据结构,简单的说,就是博客页面上需要包含什么内容。
大狗用爪子数了数,可以先添加以下几个:
- 文章题目
- 文章作者
- 文章内容
- 发布时间
其他的属性可以在后面再往里添。我们打开blog目录下的models.py文件,在里面添加了如下代码:
from __future__ import unicode_literals
from django.db import models
class Article(models.Model):
title = models.CharField(max_length = 100)
author = models.CharField(max_length = 30)
body = models.TextField()
timestamp = models.DateTimeField()
刚刚新建的这个类是django.db.models.Model的子类,这个也是Django为应用模型类准备的标准基类。只要模型类继承自该类,就可以利用Django集成的对象关系映射(ORM)机制简化我们的开发过程。
我们在上面的模型类中使用了CharField, TextField和DateTimeField三种字段类(field class),除此之外,django在django.db.models模块中还定义了二十余种字段类,完整列表请参见 Django Model field reference
在进行后续步骤之前,需要确认一下当前的数据库设置。打开DjangoQuickTour目录下的settings.py文件,找到了DATABASE配置节,发现默认配置如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
正是项目目录下的SQLite数据库,所以我们也就不需要做什么修改了。
然后,我们就可以把模型类中定义的数据结构写入数据库了。如果你认为还需要手工编写SQL语句,然后连接到数据库,建立数据表和索引,你就想多了。实际上,只需要在命令行工具中运行:
./manage.py makemigrations
然后运行:
./manage.py migrate
我们可以看到命令行输出了以下信息:
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying blog.0001_initial... OK
CNTI001:DjangoQuickTour mye$ ./manage.py makemigrations
No changes detected
CNTI001:DjangoQuickTour mye$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
这样就搞定了么?是的。只需一条命令,相关的数据表已经在数据库中建好了。不信?look!
为了后面编写视图,我们需要先在博客中添加一些数据。什么?在insert语句?不不不,完全不用这么麻烦,我们直接在博客管理后台做。什么?你说博客管理后台还没写?谁说还需要写管理后台?[坏笑]
保险起见,我们还是需要检查一下项目设置。首先,打开DjangoQuickTour目录的settings.py,确定后台管理应用已经挂接:
INSTALLED_APPS = [
'django.contrib.admin', //后台管理
'django.contrib.auth', //身份验证
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
看来管理应用已经默认挂接好了。
下面我们检查一下后台管理的URL是否已经配置好,打开DjangoQuickTour目录下的urls.py:
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
看来后台管理的地址是“http://127.0.0.1:8000/admin”。
最后,还有一项工作要做,我们必须将我们刚刚添加的Article类注册到后台管理模块(否则后台管理模块就不知道需要在admin窗口需要显示哪些模型对象信息以供编辑了,对吧?)。好在本项工作很简单,我们只需要打开blog目录下的admin.py,在其中添加注册语句:
from django.contrib import admin
from blog.models import *
admin.site.register(Article)
是不是很简单呢?下面我们就用"./manage.py runserver"把开发服务器跑起来,然后打开浏览器,访问“http://127.0.0.1:8000/admin”
等下!后台管理管理账号是什么?哎呀呀,大狗忘记了!我们还需要手动添加一下超级用户帐号,方法是在命令行工具中运行:
./manage.py createsuperuser
命令行将提示输入用户名,电子地址和密码,其中密码不能和电子地址或用户名类似,且必须满足一定的复杂性要求,大狗输入的超级用户帐号是:
字段 | 字段值 |
---|---|
用户名 | dagou |
电子地址 | [email protected] |
密码 | BigDog123 |
接下来,我们就可以登录进去添加数据了:
点击保存按钮后,我们可以看到数据的确是存进去了,但是在管理后台中的现实却有点奇怪,Article Object是什么鬼?
查了下文档,才知道Django管理后台中的标题需要手工设置。我们需要在blog目录下的admin.py中再添加一些代码:
from django.contrib import admin
from blog.models import *
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'timestamp')
admin.site.register(Article, ArticleAdmin)
保存文件后,我们甚至不用重启开发服务器,刷新一下页面,效果就出来了:
至此,我们的博客已经可以在后台添加数据,我们将在下一篇笔记里进一步完善管理后台界面,并完成博客的前台界面。
大家可以在GitHub中获取文章中提到的博客代码,地址是:
https://github.com/mingyeh/DjangoQuickTour
文章中如果有任何错误,希望大家及时评论,指正,也希望大家将本篇教程分享给更多的人,让知识传播下去,谢谢!