现在你的开发环境——这个“项目” ——已经配置好了,你可以开始干活了。
项目和应用有啥区别?应用是一个专门做某件事的网络应用程序——比如博客系统,或者公共记录的数据库,或者简单的投票程序。项目则是一个网站使用的配置和应用的集合。项目可以包含很多个应用。应用可以被很多个项目使用。
应用可以存放在任何 Python path
中定义的路径。这里将在 manage.py 同级目录下创建一个投票应用。这样它就可以作为顶级模块导入,而不是 mysite 的子模块。
在处于 manage.py 所在的目录下,然后运行这行命令来创建一个应用:
这将会创建一个 polls 目录,它的目录结构大致如下:$ python manage.py startapp polls
编写第一个视图
打开 polls/views.py
,把下面这些 Python 代码输入进去:
from django.http import HttpResponse
def index(request):
return HttpResponse('你好,这里是投票应用的首页')
这是 Django 中最简单的视图。如果想看见效果,我们需要将一个 URL 映射到它——这就是我们需要 URLconf 的原因了。
为了创建 URLconf,请在 polls
目录里新建一个urls.py
文件。
在polls/urls.py
中,输入如下代码:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
下一步是要在根 URLconf 文件中指定我们创建的 polls.urls
模块。在mysite/urls.py
文件的 urlpatterns
列表里插入一个 include()
, 如下:
from django.contrib import admin
from django.urls import path, include #导入include模块
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')), #包含投票模块
]
函数 include()
允许引用其它 URLconfs。
因为投票应用有它自己的 URLconf( polls/urls.py
),他们能够被放在"/polls/"
,"/fun_polls/"
,"/content/polls/"
,或者其他任何路径下,这个应用都能够正常工作。
现在把 index 视图添加进了 URLconf。可以验证是否正常工作,运行下面的命令:
$ python manage.py runserver
用浏览器访问 http://localhost:8000/polls/,你应该能够看见 "你好,这里是投票应用的首页" ,这是在 index
视图中定义的。
函数 path()
具有四个参数,两个必须参数:route
和 view
,两个可选参数:kwargs
和 name
。
path() 参数: route
route 是一个匹配 URL 的准则(类似正则表达式)。当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。
这些准则不会匹配 GET 和 POST 参数或域名。例如,URLconf 在处理请求https://www.example.com/myapp/
时,它会尝试匹配 myapp/ 。处理请求https://www.example.com/myapp/?page=3
时,也只会尝试匹配 myapp/。
path() 参数: view
当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个 HttpRequest
对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入。
path() 参数: kwargs
任意个关键字参数可以作为一个字典传递给目标视图函数。
path() 参数: name
为你的 URL 取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式。
数据库配置
打开 mysite/settings.py
。这是个包含了 Django 项目设置的 Python 模块。
通常,这个配置文件使用 SQLite 作为默认数据库。Python 内置 SQLite,所以你无需安装额外东西来使用它。
如果你不使用 SQLite,则必须添加一些额外设置,比如 USER
、 PASSWORD
、 HOST
等等。
编辑 mysite/settings.py
文件前,先设置 `TIME_ZONE为你自己时区。这里将时区改为上海时区
TIME_ZONE = 'Asia/Shanghai'
此外,关注一下文件头部的 INSTALLED_APPS
设置项。这里包括了会在你项目中启用的所有 Django 应用。应用能在多个项目中使用,你也可以打包并且发布应用,让别人使用它们。
通常, INSTALLED_APPS
默认包括了以下 Django 的自带应用:
-
django.contrib.admin
-- 管理员站点。 -
django.contrib.auth
-- 认证授权系统。 -
django.contrib.contenttypes
-- 内容类型框架。 -
django.contrib.sessions
-- 会话框架。 -
django.contrib.messages
-- 消息框架。 -
django.contrib.staticfiles
-- 管理静态文件的框架。
默认开启的某些应用需要至少一个数据表,所以,在使用他们之前需要在数据库中创建一些表。在命令行下执行以下命令:
$ python manage.py migrate
这个 migrate
命令检查 INSTALLED_APPS
设置,为其中的每个应用创建需要的数据表,至于具体会创建什么,这取决于 mysite/settings.py
设置文件和每个应用的数据库迁移文件。
创建模型
在 Django 里写一个数据库驱动的 Web 应用的第一步是定义模型 - 也就是数据库结构设计和附加的其它元数据。
在这个简单的投票应用中,需要创建两个模型:问题 Question 和选项 Choice。Question 模型包括问题描述和发布时间。Choice模型有两个字段,选项描述和当前得票数。每个选项属于一个问题。
按照下面的例子来编辑 polls/models.py
文件:
from django.db import models
class Question(models.Model): #继承models.Model类
question_text = models.CharField('问题',max_length=200) #定义问题描述字段及最大长度
pub_date = models.DateTimeField('发布日期') #定义发布日期字段
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200) #定义选项描述字段
votes = models.IntegerField(default=0) #定义得票数字段
代码非常直白。每个模型被表示为 django.db.models.Model
类的子类。每个模型有一些类变量,它们都表示模型里的一个数据库字段。
每个字段都是 Field
类的实例 - 比如,字符字段被表示为 CharField
,日期时间字段被表示为 DateTimeField
。这将告诉 Django 每个字段要处理的数据类型。
每个 Field
类实例变量的名字(例如 question_text
或 pub_date
)也是字段名,所以最好使用对机器友好的格式。你将会在 Python 代码里使用它们,而数据库会将它们作为列名。
定义某些 Field
类实例需要参数。例如 CharField
需要一个 max_length
参数。这个参数的用处不止于用来定义数据库结构,也用于验证数据。
Field
也能够接收多个可选参数;在上面的例子中:我们将 votes
的 default
也就是默认值,设为0。
注意在最后,我们使用 ForeignKey
定义了一个关系。这将告诉 Django,每个 Choice
对象都关联到一个Question
对象。Django 支持所有常用的数据库关系:多对一、多对多和一对一。
激活模型
上面的一小段用于创建模型的代码给了 Django 很多信息,通过这些信息,Django 可以:
为这个应用创建数据库 schema(生成 CREATE TABLE
语句)。
创建可以与Question
和 Choice
对象进行交互的 Python 数据库 API。
但是首先得把 polls
应用安装到我们的项目里。
为了在我们的工程中包含这个应用,我们需要在配置类 INSTALLED_APPS
中添加设置。因为 PollsConfig
类写在文件 polls/apps.py
中,所以它的点式路径是 'polls.apps.PollsConfig'
。在文件 mysite/settings.py
中 INSTALLED_APPS
子项添加点式路径后,它看起来像这样:
INSTALLED_APPS = [
'polls.apps.PollsConfig', #自定义的投票app
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
现在 Django 项目会包含 polls 应用。接着运行下面的命令:
$ python manage.py makemigrations polls
再次运行
migrate
命令,在数据库里创建新定义的模型的数据表:
$ python manage.py migrate
这个 migrate
命令选中所有还没有执行过的迁移(Django 通过在数据库中创建一个特殊的表 django_migrations
来跟踪执行过哪些迁移)并应用在数据库上 - 也就是将你对模型的更改同步到数据库结构上。
迁移是非常强大的功能,它能让你在开发过程中持续的改变数据库结构而不需要重新删除和创建表 - 它专注于使数据库平滑升级而不会丢失数据。我们会在后面的教程中更加深入的学习这部分内容,现在,你只需要记住,改变模型需要这三步:
- 编辑
models.py
文件,改变模型。 - 运行
python manage.py makemigrations
为模型的改变生成迁移文件。 - 运行
python manage.py migrate
来应用数据库迁移。
数据库迁移被分解成生成和应用两个命令是为了让你能够在代码控制系统上提交迁移数据并使其能在多个应用里使用;这不仅仅会让开发更加简单,也给别的开发者和生产环境中的使用带来方便。
Django 管理页面
创建一个管理员账号
首先,我们得创建一个能登录页面的用户。请运行下面的命令:
$ python manage.py createsuperuser
依次输入用户名、邮件地址、密码(两次)后输入 y 确认即可。
启动开发服务器
$ python manage.py runserver
打开浏览器,转到你本地域名的 "/admin/" 目录, -- 比如 "http://127.0.0.1:8000/admin/" 。你应该会看见管理员登录界面:
进入管理站点页面
现在,试着使用你在上一步中创建的超级用户来登录。然后你将会看到 Django 管理页面的索引页:
你将会看到几种可编辑的内容:
组和用户
。它们是由
django.contrib.auth
提供的,这是 Django 开发的认证框架。
向管理页面中加入投票应用
但是我们的投票应用在哪呢?它没在索引页面里显示。
只需要做一件事:我们得告诉管理页面,问题 Question 对象需要被管理。打开 polls/admin.py
文件,把它编辑成下面这样:
from django.contrib import admin
from .models import Question
admin.site.register(Question)
便捷的管理功能
现在我们向管理页面注册了问题 Question 类。Django 知道它应该被显示在索引页里,刷新下管理员页面:现在就能看到问题 "Questions" 对象了,可以很方便的进行增删改查操作。
编写更多视图
Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」。
在我们的投票应用中,我们需要下列几个视图:
- 问题索引页——展示最近的几个投票问题。
- 问题详情页——展示某个投票的问题和不带结果的选项列表。
- 问题结果页——展示某个投票的结果。
- 投票处理器——用于响应用户为某个问题的特定选项投票的操作。
在 Django 中,网页和其他内容都是从视图派生而来。每一个视图表现为一个简单的 Python 函数(或者说方法,如果是在基于类的视图里的话)。Django 将会根据用户请求的 URL 来选择使用哪个视图(更准确的说,是根据 URL 中域名之后的部分)。
现在让我们向 polls/views.py
里添加更多视图。这些视图有一些不同,因为他们接收参数:
from django.http import HttpResponse
def index(request): #问题索引页
return HttpResponse('你好,这里是投票应用的首页')
def detail(request, question_id):#问题详情页
return HttpResponse('这是问题 {}'.format(question_id))
def results(request, question_id):#问题结果页
response = '这是问题 {} 的结果'.format(question_id)
return HttpResponse(response % question_id)
def vote(request, question_id): #投票处理器
return HttpResponse('投票给问题 {}'.format(question_id))
把这些新视图添加进 polls.urls
模块里,只要添加几个 url()
函数调用就行: