第五章:数据库交换开发篇
2011-11-01 16:29
253 查看
一、简要描述:
Web应用中,很多业务逻辑经常牵涉到与数据库的交互。数据库驱动网站在后台连接数据库服务器,从中取出一些数据,然后在Web页面用漂亮的格式展示这些数据。或者,站点也提供让访问者自行填充数据库的功能。
只有使用
1、简单数据查询
这种方法可以用,但是不是最理想的方法,在Web开放中是有很多数据操作类,如果每一个类都写数据连接,关闭那太繁琐了。
我们希望不重复同样的代码:创建数据库连接、创建数据库游标、执行某个语句、然后关闭数据库。
下介绍的内容中就可以解决这个问题,也是Django框架对Web开放的很好的支持。
Django紧紧地遵循这种MVC模式,可以称得上是一种MVC框架
M,数据存取部分,由django数据库层处理,本章要讲述的内容。
V,选择显示哪些数据要及怎样显示的部分,由视图和模板处理。
C,根据用户输入委派视图的部分,由Django框架通过按照URLconf设置,对给定URL调用合适的python函数来自行处理。
2、MTV:那到底什么是MTV呢?
模型(Model)、模板(Template)和视图(Views),Django也被称为MTV框架。
M代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如何存取、如何确认有效性、包含哪些行为以及数据之间的关系等。
T代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
V代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看作模型与模板之间的桥梁。
打开项目Mysite在根目录下可以看到“settings.py”文件,找到DATABASES配置如下:
代码描述:
DATABASE_ENGINE数据库引擎设置
DATABASE_NAME将数据库名称告知Django。如果使用SQLite,请对数据库文件指定完整的文件系统路径。(例如'/home/django/mydata.db')。
DATABASE_USER告诉Django用哪个用户连接数据库。如果用SQLite,空白即可。
DATABASE_PASSWORD告诉Django连接用户的密码。SQLite用空密码即可。
DATABASE_HOST告诉Django连接哪一台主机的数据库服务器。如果数据库与Django安装于同一台计算机(即本机),可将此项保留空白。使用SQLite,也可保留空白。
2、数据库引擎设置
DATABASE_ENGINE告诉Django使用哪个数据库引擎
数据库引擎设置
设置数据库适配器
postgresqlPostgreSQLpsycopg版本1.x,
http://www.djangoproject.com/r/python-pgsql/1/.
postgresql_psycopg2PostgreSQLpsycopg版本2.x,
http://www.djangoproject.com/r/python-pgsql/.
mysqlMySQLMySQLdb,
http://www.djangoproject.com/r/python-mysql/.
sqlite3SQLitePython2.5+内建。其他,pysqlite,
http://www.djangoproject.com/r/python-sqlite/.
ado_mssqlSQLServeradodbapi版本2.0.1+,MicrosoftSQLServer
http://www.djangoproject.com/r/python-ado/.
oracleOraclecx_Oracle,
http://www.djangoproject.com/r/python-oracle/.
3、测试数据库配置
启动了一个Python交互界面:运行pythonmanage.pyshell命令
输入下面这些命令来测试你的数据库配置:
如果没有显示什么错误信息,那么你的数据库配置是正确的.
如果显示错误则配置数据库失败,检查错误代码,常见错误:
错误信息:YouhaventsettheDATABASE_ENGINEsettingyet.
解决方案:设置正确的DATABASE_ENGINE配置
错误信息:EnvironmentvariableDJANGO_SETTINGS_MODULEisundefined.
解决方案:运行命令行pythonmanage.pyshell而不是python.
错误信息:Errorloading_____module:Nomodulenamed_____.
解决方案:你没有安装相关的数据库适配器(例如,psycopg或MySQLdb).
错误信息:_____isntanavailabledatabasebackend.
解决方案:设置正确的DATABASE_ENGINE配置也许是拼写错误?
错误信息:database_____doesnotexist
解决方案:设置DATABASE_NAME配置到一个已有的数据库,或者使用CREATEDATABASE语句
创建数据库。
错误信息:role_____doesnotexist
解决方案:修改DATABASE_USER配置到一个有效用户
错误信息:couldnotconnecttoserver
解决方案:确认DATABASE_HOST和DATABASE_PORT设置是正确的,并确认服务器是在运行
的。
转到mysite项目目录,执行命令创建books目录
查看books文件目录中的文件:
2、定义数据模型
打开models.py并输入下面的内容:
缺省情况下如下所示:
把INSTALLED_APPS设置中四个设置前面加#临时注释起来,
改缺省的MIDDLEWARE_CLASSES和TEMPLATE_CONTEXT_PROCESSORS设置,都注释起来。然后添加'mysite.books'到INSTALLED_APPS列表,现在看起来是这样:
校验模型的有效性:
0errorsfound消息:表示一切正常
否则就是错误,检查数据模型是否正确。
生成SQL语句:
运行命令的结果是这样的:
代码描述:
A、自动生成的表名是app名称(books)和模型的小写名称(publisher,book,author)的组合
B、Django会站点添加一个ID主键,是可以修改的。
C、按约定规则,Django添加的"_id"后缀到外键字段名。
D、外键是用REFERENCES语句明确定义的。
E、这些CREATETABLE语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如:auto_increment(MySQL),serial(PostgreSQL),integerprimarykey(SQLite)可以自动处理。
同步数据库:
你将会看到这样的内容:
重启服务器:
重启Web服务器
数据访问类
pythonmanage.pyshell进入
1、获取所以数据
2、插入数据
转换成SQL:
3、修改数据
后面执行的save()相当于下面的SQL语句:
4、过滤数据filter()
相当于SQL语句:
5、获取单个对象
如果查询出多个对象,则会导致抛出异常。
6、数据排序order_by
相当于SQL:
可以指定逆向排序
同用步骤:
A、修改数据模型
B、同步数据库:执行pythonmanage.pysyncdb
C、重启服务器:执行pythonmanage.pyrunserver
先修改在开发环境而不是发布服务器上修改
1、添加字段
在开发环境中执行下面的步骤:
把这个字段添加到你的模型中.
运行manage.pysqlall[yourapp]会看到模型的新的CREATETABLE语句。注意新的字段的列定义。
启动您的数据库交互shell(也就是psql或mysql,或者您也可以使用manage.pydbshell)。执行一个ALTERTABLE语句,添加您的新列
4.(可选)用manage.pyshell动ython交互式shell,并通过引入模型并选择表验证新的字段已被正确添加(比如,MyModel.objects.all()[:5])。
然后在发布服务器上执行下面的步骤:
启动你的数据库的交互式命令行;
执行ALTERTABLE语句,也就是在开发环境中第3步执行的语句;
添加字段到你的模型中。如果你在开发时使用了版本控制系统并checkin了你的修改,现在可以更新代码到发布服务器上了(例如,使用Subverison的话就是svnupdate)。
重启Web服务器以使代码修改生效
2、删除字段
从模型里删除一个字段可要比增加它简单多了。删除一个字段仅需要做如下操作:
从你的模型里删除这个字段,并重启Web服务器。
使用如下面所示的命令,从你的数据库中删掉该列:
Web应用中,很多业务逻辑经常牵涉到与数据库的交互。数据库驱动网站在后台连接数据库服务器,从中取出一些数据,然后在Web页面用漂亮的格式展示这些数据。或者,站点也提供让访问者自行填充数据库的功能。
只有使用
1、简单数据查询
fromdjango.shortcutsimportrender_to_response importMySQLdb defbook_list(request): db=MySQLdb.connect(user='me',db='mydb',passwd='secret',host='localhost') cursor=db.cursor() cursor.execute('SELECTnameFROMbooksORDERBYname') names=[row[0]forrowincursor.fetchall()] db.close() returnrender_to_response('book_list.html',{'names':names})
这种方法可以用,但是不是最理想的方法,在Web开放中是有很多数据操作类,如果每一个类都写数据连接,关闭那太繁琐了。
我们希望不重复同样的代码:创建数据库连接、创建数据库游标、执行某个语句、然后关闭数据库。
下介绍的内容中就可以解决这个问题,也是Django框架对Web开放的很好的支持。
MTV开发模式
1、MVC:了解MTV之前我们还是先复习一下MVC吧。Django紧紧地遵循这种MVC模式,可以称得上是一种MVC框架
M,数据存取部分,由django数据库层处理,本章要讲述的内容。
V,选择显示哪些数据要及怎样显示的部分,由视图和模板处理。
C,根据用户输入委派视图的部分,由Django框架通过按照URLconf设置,对给定URL调用合适的python函数来自行处理。
2、MTV:那到底什么是MTV呢?
模型(Model)、模板(Template)和视图(Views),Django也被称为MTV框架。
M代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如何存取、如何确认有效性、包含哪些行为以及数据之间的关系等。
T代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
V代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看作模型与模板之间的桥梁。
数据库配置
1、缺省匹配打开项目Mysite在根目录下可以看到“settings.py”文件,找到DATABASES配置如下:
DATABASES={ 'default':{ 'ENGINE':'',#Add'postgresql_psycopg2','postgresql','mysql','sqlite3'or'oracle'. 'NAME':'',#Orpathtodatabasefileifusingsqlite3. 'USER':'',#Notusedwithsqlite3. 'PASSWORD':'',#Notusedwithsqlite3. 'HOST':'',#Settoemptystringforlocalhost.Notusedwithsqlite3. 'PORT':'',#Settoemptystringfordefault.Notusedwithsqlite3. } }
代码描述:
DATABASE_ENGINE数据库引擎设置
DATABASE_NAME将数据库名称告知Django。如果使用SQLite,请对数据库文件指定完整的文件系统路径。(例如'/home/django/mydata.db')。
DATABASE_USER告诉Django用哪个用户连接数据库。如果用SQLite,空白即可。
DATABASE_PASSWORD告诉Django连接用户的密码。SQLite用空密码即可。
DATABASE_HOST告诉Django连接哪一台主机的数据库服务器。如果数据库与Django安装于同一台计算机(即本机),可将此项保留空白。使用SQLite,也可保留空白。
2、数据库引擎设置
DATABASE_ENGINE告诉Django使用哪个数据库引擎
数据库引擎设置
设置数据库适配器
postgresqlPostgreSQLpsycopg版本1.x,
postgresql_psycopg2PostgreSQLpsycopg版本2.x,
mysqlMySQLMySQLdb,
sqlite3SQLitePython2.5+内建。其他,pysqlite,
ado_mssqlSQLServeradodbapi版本2.0.1+,MicrosoftSQLServer
oracleOraclecx_Oracle,
3、测试数据库配置
启动了一个Python交互界面:运行pythonmanage.pyshell命令
输入下面这些命令来测试你的数据库配置:
>>>fromdjango.dbimportconnection >>>cursor=connection.cursor()
如果没有显示什么错误信息,那么你的数据库配置是正确的.
如果显示错误则配置数据库失败,检查错误代码,常见错误:
错误信息:YouhaventsettheDATABASE_ENGINEsettingyet.
解决方案:设置正确的DATABASE_ENGINE配置
错误信息:EnvironmentvariableDJANGO_SETTINGS_MODULEisundefined.
解决方案:运行命令行pythonmanage.pyshell而不是python.
错误信息:Errorloading_____module:Nomodulenamed_____.
解决方案:你没有安装相关的数据库适配器(例如,psycopg或MySQLdb).
错误信息:_____isntanavailabledatabasebackend.
解决方案:设置正确的DATABASE_ENGINE配置也许是拼写错误?
错误信息:database_____doesnotexist
解决方案:设置DATABASE_NAME配置到一个已有的数据库,或者使用CREATEDATABASE语句
创建数据库。
错误信息:role_____doesnotexist
解决方案:修改DATABASE_USER配置到一个有效用户
错误信息:couldnotconnecttoserver
解决方案:确认DATABASE_HOST和DATABASE_PORT设置是正确的,并确认服务器是在运行
的。
第一个数据交换应用程序
1、创建项目转到mysite项目目录,执行命令创建books目录
pythonmanage.pystartappbooks
查看books文件目录中的文件:
books/ __init__.py models.py views.py
2、定义数据模型
打开models.py并输入下面的内容:
#-*-coding:utf-8-*- fromdjango.dbimportmodels fromdjango.contribimportadmin classPublisher(models.Model): name=models.CharField(max_length=30,blank=True) address=models.CharField(max_length=50) city=models.CharField(max_length=60) state_province=models.CharField(max_length=30) country=models.CharField(max_length=50) website=models.URLField() def__unicode__(self): returnself.name #默认排序设置 #classMeta: #ordering=["name"] #Admin声明标志了该类有一个管理界面''' classAdmin: pass classAuthor(models.Model): salutation=models.CharField(max_length=10) first_name=models.CharField(max_length=30) last_name=models.CharField(max_length=40) email=models.EmailField(max_length=30) #headshot=models.ImageField(upload_to='/tmp') def__unicode__(self): return'%s%s'%(self.first_name,self.last_name) #Admin声明标志了该类有一个管理界面''' classAdmin: pass classBook(models.Model): title=models.CharField(max_length=100) authors=models.ManyToManyField(Author) publisher=models.ForeignKey(Publisher) publication_date=models.DateField() num_page=models.IntegerField(blank=True,null=True) def__unicode__(self): return'Bookname:%s'%self.title
模型安装
再次编辑settings.py文件,找到INSTALLED_APPS设置,INSTALLED_APPS告诉Django项目哪些app处于激活状态,缺省情况下如下所示:
INSTALLED_APPS=( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', )
把INSTALLED_APPS设置中四个设置前面加#临时注释起来,
改缺省的MIDDLEWARE_CLASSES和TEMPLATE_CONTEXT_PROCESSORS设置,都注释起来。然后添加'mysite.books'到INSTALLED_APPS列表,现在看起来是这样:
MIDDLEWARE_CLASSES=( #'django.middleware.common.CommonMiddleware', #'django.contrib.sessions.middleware.SessionMiddleware', #'django.contrib.auth.middleware.AuthenticationMiddleware', #'django.middleware.doc.XViewMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS=() #... INSTALLED_APPS=( #'django.contrib.auth', #'django.contrib.contenttypes', #'django.contrib.sessions', #'django.contrib.sites', 'mysite.books', )
校验模型的有效性:
pythonmanage.pyvalidate
0errorsfound消息:表示一切正常
否则就是错误,检查数据模型是否正确。
生成SQL语句:
pythonmanage.pysqlallbooks
运行命令的结果是这样的:
BEGIN; CREATETABLE"books_publisher"( "id"serialNOTNULLPRIMARYKEY, "name"varchar(30)NOTNULL, "address"varchar(50)NOTNULL, "city"varchar(60)NOTNULL, "state_province"varchar(30)NOTNULL, "country"varchar(50)NOTNULL, "website"varchar(200)NOTNULL ); CREATETABLE"books_book"( "id"serialNOTNULLPRIMARYKEY, "title"varchar(100)NOTNULL, "publisher_id"integerNOTNULLREFERENCES"books_publisher"("id"), "publication_date"dateNOTNULL ); CREATETABLE"books_author"( "id"serialNOTNULLPRIMARYKEY, "salutation"varchar(10)NOTNULL, "first_name"varchar(30)NOTNULL, "last_name"varchar(40)NOTNULL, "email"varchar(75)NOTNULL, "headshot"varchar(100)NOTNULL ); CREATETABLE"books_book_authors"( "id"serialNOTNULLPRIMARYKEY, "book_id"integerNOTNULLREFERENCES"books_book"("id"), "author_id"integerNOTNULLREFERENCES"books_author"("id"), UNIQUE("book_id","author_id") ); CREATEINDEXbooks_book_publisher_idON"books_book"("publisher_id"); COMMIT;
代码描述:
A、自动生成的表名是app名称(books)和模型的小写名称(publisher,book,author)的组合
B、Django会站点添加一个ID主键,是可以修改的。
C、按约定规则,Django添加的"_id"后缀到外键字段名。
D、外键是用REFERENCES语句明确定义的。
E、这些CREATETABLE语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如:auto_increment(MySQL),serial(PostgreSQL),integerprimarykey(SQLite)可以自动处理。
同步数据库:
pythonmanage.pysyncdb
你将会看到这样的内容:
Creatingtablebooks_publisher Creatingtablebooks_book Creatingtablebooks_author Installingindexforbooks.Bookmodel
重启服务器:
重启Web服务器
pythonmanage.pyrunserver
数据访问类
pythonmanage.pyshell进入
1、获取所以数据
>>>frombooks.modelsimportPublisher >>>publisher_list=Publisher.objects.all() >>>publisher_list [<Publisher:lhj-588>,<Publisher:loker>]
2、插入数据
>>>frombooks.modelsimportPublisher >>>p=Publisher(name='Apress', ...address='2855TelegraphAve.', ...city='Berkeley', ...state_province='CA', ...country='U.S.A.', ...website='http://www.apress.com/') >>>p.save()
转换成SQL:
INSERTINTObook_publisher (name,address,city,state_province,country,website) VALUES ('Apress','2855TelegraphAve.','Berkeley','CA', 'U.S.A.','http://www.apress.com/');
3、修改数据
>>>frombooks.modelsimportPublisher >>>p=Publisher(name='Apress' ,...address='2855TelegraphAve.' ,...city='Berkeley' ,...state_province='CA' ,...country='U.S.A.' ,...website='http://www.apress.com/') >>>p.save() >>>p.id 3 >>>p.name='apressPublishing' >>>p.save()
后面执行的save()相当于下面的SQL语句:
UPDATEbook_publisherSET name='ApressPublishing', address='2855TelegraphAve.', city='Berkeley', state_province='CA', country='U.S.A.', website='http://www.apress.com' WHEREid=52;
4、过滤数据filter()
>>>frombooks.modelsimportPublisher >>>Publisher.objects.filter(country="U.S.A.",state_province="CA") [<Publisher:ApressPublishing>]
相当于SQL语句:
SELECT id,name,address,city,state_province,country,website FROMbook_publisher WHEREcountry='U.S.A.'ANDstate_province='CA';
5、获取单个对象
>>>frombooks.modelsimportPublisher >>>Publisher.objects.get(name="ApressPublishing")
[<Publisher:ApressPublishing>]
如果查询出多个对象,则会导致抛出异常。
6、数据排序order_by
>>>frombooks.modelsimportPublisher >>>Publisher.objects.order_by("name")
[<Publisher:ApressPublishing>,<Publisher:Addison-Wesley>,<Publisher:O'Reilly>]
相当于SQL:
SELECT id,name,address,city,state_province,country,website FROMbook_publisher ORDERBYname;
可以指定逆向排序
Publisher.objects.order_by("-name")
7、限制返回的数据
>>>frombooks.modelsimportPublisher
>>>Publisher.objects.all()[0]
<Publisher:Addison-Wesley>
>>>Publisher.objects.all()[0:2]
[<Publisher:Addison-Wesley>,<Publisher:ApressPublishing>,<Publisher:Addison-Wesley>]
8、删除对象.delete()
>>>frombooks.modelsimportPublisher
>>>p=Publisher.objects.get(name="Addison-Wesley")
>>>p.delete()
>>>Publisher.objects.all()
[<Publisher:ApressPublishing>,<Publisher:O'Reilly>]
>>>publishers.delete()
>>>Publisher.objects.all()
[]
修改数据库表结构
你需要查看manage.pysqlall的执行结果同用步骤:
A、修改数据模型
B、同步数据库:执行pythonmanage.pysyncdb
C、重启服务器:执行pythonmanage.pyrunserver
先修改在开发环境而不是发布服务器上修改
1、添加字段
在开发环境中执行下面的步骤:
把这个字段添加到你的模型中.
运行manage.pysqlall[yourapp]会看到模型的新的CREATETABLE语句。注意新的字段的列定义。
启动您的数据库交互shell(也就是psql或mysql,或者您也可以使用manage.pydbshell)。执行一个ALTERTABLE语句,添加您的新列
4.(可选)用manage.pyshell动ython交互式shell,并通过引入模型并选择表验证新的字段已被正确添加(比如,MyModel.objects.all()[:5])。
然后在发布服务器上执行下面的步骤:
启动你的数据库的交互式命令行;
执行ALTERTABLE语句,也就是在开发环境中第3步执行的语句;
添加字段到你的模型中。如果你在开发时使用了版本控制系统并checkin了你的修改,现在可以更新代码到发布服务器上了(例如,使用Subverison的话就是svnupdate)。
重启Web服务器以使代码修改生效
2、删除字段
从模型里删除一个字段可要比增加它简单多了。删除一个字段仅需要做如下操作:
从你的模型里删除这个字段,并重启Web服务器。
使用如下面所示的命令,从你的数据库中删掉该列:
3、删除Many-to-Many字段
因为many-to-many字段同普通字段有些不同,它的删除过程也不一样:
删除掉你的模型里的ManyToManyField,并且重启Web服务器。
使用如下面所示的命令,删除掉你数据库里的many-to-many表:
DROPTABLEbooks_books_publishers;
4、删除模型
完全删除一个模型就像删除一个字段一样简单。删除模型仅需要做如下步骤:
将此模型从你的models.py文件里删除,并且重启Web服务器。
使用如下的命令,将此表从你的数据库中删除:
DROPTABLEbooks_book;