对Django这个
框架
感
兴趣
很久了,却一直懒于
研究
学习
,如今跟随官网的
教程
跑一遍,学学Django同时也
继续
学学
Python
。
在开始以前,
咱们
先把Python和Django这个框架安装好。
官网:
https://www.djangoproject.com/
下载
:http://www.djangoproject.
com
/download/1.3/tarball/
因为兼容性
问题
,Django并不支持Python3+,只支持版本2.4到2.7,因此若是你的
系统
(本人使用的是SUSE Linux Enterprise Server 10 SP3,如下都是以这个系统为例)没有安装Python,或者版本不
符合
,那么就先要安装一个合适的版本,我使用的是2.7.2版本:
2 |
tar jxvf Python-2.7.2. tar .bz2 |
下载完后运行python setup.py install进行安装:
2 |
tar xzvf Django-1.3. tar .gz |
4 |
python setup.py install |
安装完成后,
验证
下是否
成功
,
输入
python进入命令行,而后输入以下语句导入django而且输出django的版本号:
2 |
>>> print django.get_version() |
OK,下面咱们
能够
正式开始了。 在这个教程里,咱们会建立一个简单的投票
应用
。它包括两部分:
- 一个公共网页让人查看投票和进行投票。
- 一个管理网页让你添加,修改和删除投票
获取帮助:node
若是你对这个教程有任何疑问,请到django-users留言或者在irc.freenode.net上访问#django,找一些可能为你提供帮助的Django用户。python
下面开始
创建
一个项目。首先
cd
到存放项目的目录,而后运行
django-admin.py startproject mysite
命令建立项目:
2 |
django-admin.py startproject mysite |
执行
完后将会在当前目录建立一个名为mysite的项目。
发布包的文件名可能不一样mysql
若是你是经过Linux发布包管理系统(例如apt-get或者yum)安装Django,django-admin.py可能会被重命名为django-admin,你能够忽略命令里的.py继续完成这个文档。sql
Mac OS X权限问题shell
若是你使用的是Mac OS X,当运行django-admin.py startproject的时候可能会看到信息"permission denied"。这是由于像OS X这种基于Unix的系统,一个文件在运行前必须是"executable"的。你能够打开Terminal.app而且去到django-admin.py被安装到的目录,并运行命令chmod +x django-admin.py来解决这个问题。数据库
注意apache
要避免跟Python和Django组件的命名冲突,避免使用像django和test这样的命名。django
若是你是经过
python setup.py
安装Django的话,django-admin.py应该会在你的系统
路径
下。若是它不在这个路径上的话,你能够在
site-packages/django/bin
里找到它,
site-packages
是你安装Python的目录。你能够考虑把某个路径软
连接
到django-admin.py,例如
/usr/local/bin
。
代码应该放在哪浏览器
若是你是PHP出身的话,你大概会把代码放在Web Server的根目录下(例如/var/www)。但在Django里,别这么干。把Python代码放在Web Server的根目录里并非一个好主意,由于有被人在网页上看到代码的风险。这个不利于安全。安全
把你的代码放在根目录外面的地方,例如/home/mycod(我这里用的目录是/home/python)。
回到正题,startproject建立的目录结构以下:
这些文件的用途是:
- __init__.py: 一个空文件让Python知道这个目录是一个Python包。(若是你是一个Python初学者,能够看官方的Python文档了解更多关于包的内容)
- manage.py: 一个命令行工具用于跟项目的各类交互。详情查看django-admin.py和manage.py这两个文件。
- settings.py: 当前项目的设置和配置。详情能够查看Django settings。
- urls.py: 当前项目的URL定义。详情能够查看URL dispatcher。
下面启动Django development server来检查下成果。进入项目目录
mysite
运行命令
python manage.py runserver
:
Django version 1.3, using settings 'mysite.settings' |
Quit the server with CONTROL-C. |
你已经启动了Django的开发
服务
器,一个用纯Python编写的轻量级Web server。咱们已经把它包含在Django里,这样你就能够进行快速的开发而不须要去配置诸如
apache
这样的Production服务器,除非你已经准备好要发布了。
注意不要把这个服务器看成发布环境用,它是专门在开发环境中使用的。
如今服务已经启动了,你能够在
浏览器
上访问http://127.0.0.1:8000/。你将会看到欢迎
页面
,以下图:
改变端口
runserver命令的默认端口是8000。
若是你想改变端口,你能够把它做为参数传给命令行,例如,这个命令会在端口8080上启动服务:
python manage.py runserver 8080 |
若是想改变IP,那么能够跟端口一块儿传给命令行。若是要监听全部的公共IP,能够这样:
python manage.py runserver 0.0.0.0:8000 |
开发服务器的文档能够在runserver里找到。
如今,
编辑
settings.py
文件。修改DATABASES的
default
项里下面的值:
- ENGINE:django.db.backends.postgresql_psycopg2或者django.db.backends.mysql和django.db.backends.sqlite3。也支持其余数据库。
- NAME:数据库名。若是使用的是SQLite的话,数据库则是系统里的一个文件,因此NAME应该设为包含这个文件名字的绝对路径(注意路径要使用斜杠/,不管在什么系统上)。这个文件不须要建立,在第一次进行数据库同步的时候会自动建立这个文件。
- USER:用户名。使用SQLite的话则不须要。
- PASSWORD:密码。使用SQLite的话则不须要。
- HOST:主机地址。使用SQLite的话则不须要。若是数据库安装在同一台机器上,也能够不指定。
若是你对数据库不太熟悉的话,
建议
你使用SQLite(把
ENGINE
设为
django.db.backends.sqlite3
)。SQLite已经做为Python 2.5以上版本的一部分包含在里面,因此你不须要做任何的安装。
在编辑
settings.py
的时候,你会注意到文件底部的INSTAL
LED
_APPS配置项。这些变量保存了那些随着Django实例启动的Django应用(如下用app表示)的名字。app能够被使用到多个项目里,你也能够把它们打包和发布出去供其余人使用。 INSTALLED_APPS默认包含了如下app,这些app所有由Django自带:
- django.contrib.auth -- 一个认证系统。
- django.contrib.contenttypes -- 内容类型框架。
- django.contrib.sessions -- session框架。
- django.contrib.sites -- 多网站管理框架。
- django.contrib.messages -- 消息管理框架。
- django.contrib.staticfiles -- 静态文件管理框架。
为了方便使用,这些一般
网站
都会用到的应用已经默认包含在项目里。 这些app每一个都至少要用到一个以上的数据库表,因此在使用这些应用前咱们先要建立这些表。运行一下命令:
syncdb命令会根据
settings.py
文件里的INSTALLED_APPS设置建立必需的数据表。你会看到建立表的信息以及会提示你为认证系统建立超级用户,跟着提示作就好了。
简化
就像咱们上面说的,基于常理,默认的那些应用会被自动包含,可是并非全部人都会用到它们。因此若是你不须要用到这些应用,你能够在执行syncdb命令前随意把它们在INSTALLED_APPS里注释掉或者删掉。syncdb只会为INSTALLED_APPS里的应用建立表。
建立模型
如今环境已经搭好了,能够正式开工了。
在Django里,你写的每一个应用都包含一个Python的包,这个包会根据一个特定的约定放在Python path里。Django会自动为每一个app建立一些
基本
的目录结构,因此你能够专心写代码而没必要在建立目录上费心。
Projects vs. apps
项目跟app有什么不一样呢?app是一个实现某个功能的网页应用,例如一个网页日志系统,一个公共数据数据库或者一个简单的投票应用。而一个项目则是由一堆配置和应用组成的网页。一个项目能够包含多个应用,而一个应用可使用在多个项目里。
你的应用能够存放在Python path上的任何地方。简单起见,咱们在
mysite
目录里建立一个投票应用。确认你的当前目录为
mysite
,并输入命令:
python manage.py startapp polls |
这样会建立一个目录polls,以下:
这个目录结构将会存放这个poll应用。
在Django里写一个有数据库操做的网页应用第一步要作的就是定义模型(Model),模型实质上就是附带元数据的数据层(database layout)。
原理(Philosophy)
模型是跟你的数据相关的一个单一和明确的数据源。它包含了你所储存的数据的一些必要字段和行为。Django遵循DRY原则,目的是在一个地方定义你的数据模型而后根据它自动派生出其余的东西。
在咱们这个简单的投票应用里,咱们建立了两个模型:polls和choices。一个poll包含有一个问题和一个发表日期。一个choice有两个字段:选项
文字
和投票计数。每个choice都跟一个poll关联。
这个概念将由一个简单的Python类来实现。编辑文件
polls/models.py
:
1 |
from django.db import models |
2 |
class Poll(models.Model): |
3 |
question = models.CharField(max_length = 200 ) |
4 |
pub_date = models.DateTimeField( 'date published' ) |
5 |
class Choice(models.Model): |
6 |
poll = models.ForeignKey(Poll) |
7 |
choice = models.CharField(max_length = 200 ) |
8 |
votes = models.IntegerField() |
代码很直白。每一个模型都由一个django.db.models.Model的子类实现。每一个模型包含一些变量,每一个变量对应一个数据库里的字段。
每一个字段由类Field的一个实例表示,例如字符类型的字段由CharField实现,
时间
类型的字段则由DateTimeField实现,这样Django就知道每一个字段保存的是什么类型的数据了。
每一个Field实例的名字(例如
question
和
pub_date
)都是机器友好格式的字段名。这些字段会用在你的Python代码里,而数据库则会把它用做字段名。
你能够在Field的第一个参数指定一个可读的名字,这个名字会用在Django内部多个地方。若是没有指定这个名字,Django会使用机器可读的名字。在这个例子里,咱们只为
Poll.pub_date
定义了人可读的名字,模型里其余全部的字段,机器可读名字已经可做为人可读名字。
一些Field类有必须含有的元素,例如CharField,必须给它指定
max_length
。这个不只会用在数据库schema里,也会用在数据验证里,咱们很快会看到。
最后,注意到用ForeignKey定义了一个
关系
。它告诉Django每一个Choice会关联到一个Poll。Django支持全部的
经常使用
数据库关系:多对已,多对多和一对一。
激活模型
Django经过模型里的那点代码获取到了不少的信息,经过这些信息,Django能够:
- 为应用建立数据库模式(CREATE TABLE语句) 。
- 建立访问Poll和Choice对象的Python数据库访问API。
可是首先咱们先要让咱们的项目知道
polls
这个应用已经安装。
原理(Philosophy)
Django应用是“可插拔式”的:你能够把一个应用用在多个项目里,也能够把它发布出去,由于它们不是跟Django的安装绑定的。
再次编辑文件
settings.py
,修改设置INSTALLED_APPS包含字符串
'polls'
。修改后的配置以下:
'django.contrib.contenttypes', |
'django.contrib.sessions', |
如今Django知道要去包含
polls
这个应用了。咱们执行
另外
一个命令:
python manage.py sql polls |
你应该会看到相似下面的东西(poll应用的
CREATE TABLE
SQL语句):
CREATE TABLE "polls_poll" ( |
"id" integer NOT NULL PRIMARY KEY, |
"question" varchar(200) NOT NULL, |
"pub_date" datetime NOT NULL |
CREATE TABLE "polls_choice" ( |
"id" integer NOT NULL PRIMARY KEY, |
"poll_id" integer NOT NULL REFERENCES "polls_poll" ( "id" ), |
"choice" varchar(200) NOT NULL, |
注意如下几点:
- 实际输出的东西会根据你所使用的数据库而不一样。
- 表名由应用的名称(polls)和小写的模型名称 —— poll和choice组合而成并自动生成。(你能够重写这个规则。)
- 主键(IDs)会被自动添加。(一样能能够重写它)
- 为了方便,Django会添加"_id"到外键的字段名上。对的,你一样能够重写它。
- 外键关系由一个REFERENCES语句明确肯定。
- 它是为你所使用的数据库量身定制的,因此数据库特有的字段如auto_increment (MySQL),serial (PostgreSQL)或者integer primary key (SQLite)都会自动帮你处理,一样字段名的引号也是如此,例如,是使用双引号仍是单引号。这篇教程的做者使用PostgreSQL,因此例子里的输出都是PostgreSQL语法。
- sql命令并不会在你的数据库里执行SQL语句,它只是在屏幕上显示给你看Django认为须要执行哪些SQL语句。若是你想的话,能够复制和粘贴这些SQL语句到你的数据库命令行。可是,咱们很快就能看到,Django提供了一个更为简单的方式去执行这些SQL到数据库上。
若是你有兴趣,能够运行如下的命令:
- python manage.py validate -- 检查模型的结构错误。
- python manage.py sqlcustom polls -- 输出全部为应用定义的自定义SQL语句 (例如表修改和约束)。
- python manage.py sqlclear polls -- 根据已存在的表,输出这个应用中必要的DROP TABLE语句。
- python manage.py sqlindexes polls -- 输出这个应用CREATE INDEX语句。
- python manage.py sqlall polls -- sql,sqlcustom和sqlindexes命令产生的SQL语句的结合。
看这些命令的输出能够帮助你更好的
理解
底层发生的事情。
如今,再次运行syncdb在数据库上建立这些模型的表:
syncdb命令会为在INSTALLED_APPS里没有相应数据表的应用运行'sqlall'产生的sql语句。它会为自上次运行syncdb以来新添加的应用创建全部的表,初始化数据和
索引
。你能够在任什么时候候执行syncdb,它只会建立不存在的表。
阅读django-admin.py documentation以获取
manage.py
这个工具所能作的事情的全部信息。
使用API
如今,咱们进入Python的交互
shell
并使用Django提供的API。要进入Python shell,使用这个命令:
我在这里遇到了ImportError: No module named readline这个错误,
解决方法
是下载readline,编译安装,而后从新编译和安装python就能够解决这个问题。
咱们使用这个而不是简单的输入"python",是由于
manage.py
会帮你建立项目的环境。“建立项目环境”包括两件事:
- 把polls添加到sys.path里。为了灵活性,Django中的模块经过加点的路径来引用(例如'polls.models')。为了实现这个,polls包必须在sys.path里。
咱们已经遇到过一个这样的例子了:the INSTALLED_APPS设置里的列表就是使用点路径表示法。
- 设置DJANGO_SETTINGS_MODULE环境变量,为Django指定了你的settings.py文件的路径。
省略manage.py
若是你不想使用manage.py,没问题,只须要确保mysite和polls 位于Python路径的根目录 (例如import mysite和import polls能正常工做)以及把DJANGO_SETTINGS_MODULE这个环境变量设置到mysite.settings里。
更多的信息能够查看django-admin.py documentation.
在shell里面时,能够
探索
下database API:
>>> from polls.models import Poll, Choice # 导入咱们刚写的模型。 |
>>> p = Poll(question = "What's up?" , pub_date = datetime.datetime.now()) |
# 把对象保存进数据库里。你须要明确调用save()。 |
# 如今它有个ID了。注意这里也可能显示1L而不是1, |
# 取决于你使用的是什么数据库。不过这没什么打不了, |
# 它只是代表数据库更倾向于把整型返回成Python的长整型对象。 |
datetime.datetime( 2007 , 7 , 15 , 12 , 00 , 53 ) |
>>> p.pub_date = datetime.datetime( 2007 , 4 , 1 , 0 , 0 ) |
# objects.all()显示数据库全部的poll。 |
等等。
<Poll: Poll object>
彻底不能表现出这个对象的
有用信息
。咱们能够编辑poll模型(在文件
polls/models.py
里)添加一个__unicode__()
方法
给
Poll
和
Choice
来解决这个问题:
class Poll(models.Model): |
class Choice(models.Model): |
为你的模型添加__unicode__()方法是颇有必要的。不只是为了让你本身更好理解交互提示,并且由于对象的表现的使用会贯穿于整个Django自动产生的admin。
为何是__unicode__()而不是__str__()?
若是你熟悉Python的话,你可能会更喜欢在你的类里添加__str__()而不是__unicode__()方法。咱们这里使用__unicode__()是由于Django模型默认使用Unicode,全部保存在数据库的数据在返回的时候都会转化成Unicode。
Django模型有一个默认的__str__()方法叫__unicode__(),它会把结果集转化成UTF-8字节字符串。在各个意味着unicode(p)会返回一个Unicode字符串,而str(p)会返回一个普通的UTF-8编码的字符串。
若是你仍是以为莫名其妙的话,记得把__unicode__()方法加进你的模型中就好了,幸运的话,一切都会如你所想工做。
注意这些都是普通的Python方法,让咱们添加一个自定义的方法,用做示范:
class Poll(models.Model): |
def was_published_today( self ): |
return self .pub_date.date() = = datetime.date.today() |
添加
import datetime
会引用Python的
datetime
模块。 保存这些修改而后再次运行
python manage.py shell
新开一个Python交互shell:
>>> from polls.models import Poll, Choice |
# 确保咱们新加的__unicode__()正常工做。 |
>>> Poll.objects. filter ( id = 1 ) |
>>> Poll.objects. filter (question__startswith = 'What' ) |
>>> Poll.objects.get(pub_date__year = 2007 ) |
>>> Poll.objects.get( id = 2 ) |
Traceback (most recent call last): |
DoesNotExist: Poll matching query does not exist. |
# 因此Django为这种查找方法提供一个便捷的方式。 |
# 下面至关于Poll.objects.get(id=1)。 |
>>> Poll.objects.get(pk = 1 ) |
>>> p = Poll.objects.get(pk = 1 ) |
>>> p.was_published_today() |
# 调用建立函数建立choice对象,会调用INSERT语句, |
# 把choice添加到已存choice的集合里,并返回这个新建立的Choice对象。 |
# Django会建立一个集合保存外键关联,这个集合能够经过API进行访问。 |
>>> p = Poll.objects.get(pk = 1 ) |
>>> p.choice_set.create(choice = 'Not much' , votes = 0 ) |
>>> p.choice_set.create(choice = 'The sky' , votes = 0 ) |
>>> c = p.choice_set.create(choice = 'Just hacking again' , votes = 0 ) |
# Choice对象可经过API访问它关联的Poll对象。 |
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] |
# 查找pub_date在2007年的poll的全部choice。 |
>>> Choice.objects. filter (poll__pub_date__year = 2007 ) |
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] |
# 咱们使用delete()删除一个choice。 |
>>> c = p.choice_set. filter (choice__startswith = 'Just hacking' ) |
更多关于模型关系的信息,能够看Accessing
related
objects。想知道更多关于如何使用双下划线经过API实现字段的查找,看Field lookups。要获取数据库API的全部信息,请看Database API reference。
好吧,开篇就到这里,更详细请查看:
https://docs.djangoproject.com/en/dev/intro/tutorial01/
Written by icyfire @ 2011.08.05 updated @ 2011.10.09