第五章:数据库交换开发篇

一、简要描述:

       Web 应用中,很多业务逻辑经常牵涉到与数据库的交互。 数据库驱动网站 在后台连接数据库服务器,从中取出一些数据,然后在 Web 页面用漂亮的格式展示这些数据。或者,站点也提供让访问者自行填充数据库的功能。

        只有使用

1、简单数据查询

    


from django.shortcuts import render_to_response
import MySQLdb

def book_list(request):
db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
cursor = db.cursor()
cursor.execute('SELECT name FROM books ORDER BY name')
names = [row[0] for row in cursor.fetchall()]
db.close()
return render_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': '', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}

  代码描述:

 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使用哪个数据库引擎

               数据库引擎设置
       设置                    数据库        适配器

      postgresql            PostgreSQL    psycopg 版本 1.x, 
  http://www.djangoproject.com/r/python-pgsql/1/.

  postgresql_psycopg2   PostgreSQL  psycopg 版本 2.x, 
  http://www.djangoproject.com/r/python-pgsql/.

  mysql                  MySQL            MySQLdb , 
  http://www.djangoproject.com/r/python-mysql/.
  sqlite3                 SQLite            Python 2.5+ 内建。 其他, pysqlite ,
  http://www.djangoproject.com/r/python-sqlite/.

  ado_mssql           SQL Server     adodbapi 版本 2.0.1+, Microsoft SQL Server
  http://www.djangoproject.com/r/python-ado/.

  oracle                  Oracle             cx_Oracle ,
  http://www.djangoproject.com/r/python-oracle/.

 3、测试数据库配置

 启动了一个 Python 交互界面 : 运行 python manage.py shell 命令

 输入下面这些命令来测试你的数据库配置:

 

>>> from django.db import connection
>>> cursor = connection.cursor()

如果没有显示什么错误信息,那么你的数据库配置是正确的.

如果显示错误则配置数据库失败,检查错误代码,常见错误:

 

错误信息:You havent set the DATABASE_ENGINE setting yet.

解决方案:设置正确的 DATABASE_ENGINE 配置

 

错误信息:Environment variable DJANGO_SETTINGS_MODULE is undefined.

解决方案:运行命令行 python manage.py shell 而不是 python .

 

错误信息:Error loading _____ module: No module named _____.

解决方案:你没有安装相关的数据库适配器 (例如, psycopgMySQLdb ).

 

错误信息:_____ isnt an available database backend.

解决方案:设置正确的 DATABASE_ENGINE 配置也许是拼写错误?

 

错误信息:database _____ does not exist

解决方案:设置 DATABASE_NAME 配置到一个已有的数据库,或者使用 CREATE DATABASE 语句

               创建数据库。

 

错误信息:role _____ does not exist

解决方案:修改 DATABASE_USER 配置到一个有效用户

 

错误信息:could not connect to server

解决方案:确认 DATABASE_HOSTDATABASE_PORT 设置是正确的,并确认服务器是在运行

               的。

 

第一个数据交换应用程序

 1、创建项目

  转到mysite项目目录,执行命令创建books目录

 

python manage.py startapp books

 查看books文件目录中的文件:

 

books/
__init__.py
models.py
views.py

 

 2、定义数据模型

  打开 models.py 并输入下面的内容:

  

# -*- coding:utf-8 -*-
from django.db import models
from django.contrib import admin

class Publisher(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):
return self.name
#默认排序设置
#class Meta:
# ordering = ["name"]

#Admin 声明标志了该类有一个管理界面'''
class Admin:
pass

class Author(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 声明标志了该类有一个管理界面'''
class Admin:
pass

class Book(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 'Book name :%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_CLASSESTEMPLATE_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',
)

 

校验模型的有效性:

python manage.py validate

0 errors found 消息:表示一切正常

否则就是错误,检查数据模型是否正确。

 

生成SQL语句:

python manage.py sqlall books

 运行命令的结果是这样的:

BEGIN;
CREATE TABLE "books_publisher" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"address" varchar(50) NOT NULL,
"city" varchar(60) NOT NULL,
"state_province" varchar(30) NOT NULL,
"country" varchar(50) NOT NULL,
"website" varchar(200) NOT NULL
);
CREATE TABLE "books_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
"publication_date" date NOT NULL
);
CREATE TABLE "books_author" (
"id" serial NOT NULL PRIMARY KEY,
"salutation" varchar(10) NOT NULL,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL,
"headshot" varchar(100) NOT NULL
);
CREATE TABLE "books_book_authors" (
"id" serial NOT NULL PRIMARY KEY,
"book_id" integer NOT NULL REFERENCES "books_book" ("id"),
"author_id" integer NOT NULL REFERENCES "books_author" ("id"),
UNIQUE ("book_id", "author_id")
);
CREATE INDEX books_book_publisher_id ON "books_book" ("publisher_id");
COMMIT;


代码描述:

   A、自动生成的表名是app名称( books )和模型的小写名称( publisher , book , author )的组合
   B、Django会站点添加一个ID主键,是可以修改的。

   C 、按约定规则,Django添加的"_id"后缀到外键字段名。

    D、外键是用 REFERENCES 语句明确定义的。

    E、这些 CREATE TABLE 语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如: auto_increment (MySQL), serial (PostgreSQL), integer primary key (SQLite) 可以自动处理。

同步数据库:

python manage.py syncdb

 

你将会看到这样的内容:

Creating table books_publisher
Creating table books_book
Creating table books_author
Installing index for books.Book model

 

 

重启服务器:

 重启Web服务器

 

python manage.py runserver

 

 

数据访问类

  python manage.py shell 进入

 

 1、获取所以数据

>>> from books.models import Publisher
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: lhj-588>, <Publisher: loker>]

2、插入数据

>>> from books.models import Publisher
>>>p = Publisher(name='Apress',
... address='2855 Telegraph Ave.',
... city='Berkeley',
... state_province='CA',
... country='U.S.A.',
... website='http://www.apress.com/')
>>> p.save()

转换成SQL:

INSERT INTO book_publisher
(name, address, city, state_province, country, website)
VALUES
('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA',
'U.S.A.', 'http://www.apress.com/');

 

3、修改数据

>>> from books.models import Publisher
>>>p = Publisher(name='Apress'
,... address='2855 Telegraph Ave.'
,... city='Berkeley'
,... state_province='CA'
,... country='U.S.A.'
,... website='http://www.apress.com/')
>>> p.save()
>>> p.id
3
>>> p.name ='apress Publishing'
>>> p.save()


 后面执行的 save() 相当于下面的SQL语句:

UPDATE book_publisher SET
name = 'Apress Publishing',
address = '2855 Telegraph Ave.',
city = 'Berkeley',
state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'
WHERE id = 52;

4、过滤数据  filter()

>>> from books.models import Publisher
>>>Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress Publishing>]

相当于SQL语句:

SELECT
id, name, address, city, state_province, country, website
FROM book_publisher
WHERE country = 'U.S.A.' AND state_province = 'CA';

 

5、获取单个对象

>>> from books.models import Publisher
>>>Publisher.objects.get(name="Apress Publishing")
[<Publisher: Apress Publishing>]

如果查询出多个对象,则会导致抛出异常。

6、数据排序 order_by

>>> from books.models import Publisher
>>>Publisher.objects.order_by("name")
[<Publisher: Apress Publishing>, <Publisher: Addison-Wesley>, <Publisher: O'Reilly>]

相当于SQL:

SELECT
id, name, address, city, state_province, country, website
FROM book_publisher
ORDER BY name;

可以指定逆向排序

Publisher.objects.order_by("-name")
 
7、限制返回的数据
 
>>>from books.models import Publisher
>>>Publisher.objects.all()[0]
<Publisher: Addison-Wesley>
>>>Publisher.objects.all()[0:2]
[<Publisher: Addison-Wesley>, <Publisher: Apress Publishing>, <Publisher: Addison-Wesley>]

8、删除对象.delete()
>>>from books.models import Publisher
>>>p = Publisher.objects.get(name="Addison-Wesley")
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>, <Publisher: O'Reilly>]
>>>publishers.delete()
>>> Publisher.objects.all()
[]

 

 

 

修改数据库表结构

你需要查看 manage.py sqlall 的执行结果 

  同用步骤:

  A、修改数据模型

  B、同步数据库:执行python manage.py syncdb

  C、重启服务器:执行python manage.py runserver

先修改在开发环境而不是发布服务器上修改

1、添加字段

在开发环境中执行下面的步骤:

  1. 把这个字段添加到你的模型中.

  1. 运行 manage.py sqlall [yourapp] 会看到模型的新的 CREATE TABLE 语句。注意新的字段的列定义。

  1. 启动您的数据库交互shell(也就是 psqlmysql , 或者您也可以使用 manage.py dbshell )。 执行一个 ALTER TABLE 语句,添加您的新列

    4. (可选)用 manage.py shell 动ython交互式shell,并通过引入模型并选择表验证新的字段已被正确添加(比如, MyModel.objects.all()[:5] )。

然后在发布服务器上执行下面的步骤: 

  1. 启动你的数据库的交互式命令行;

  1. 执行 ALTER TABLE 语句,也就是在开发环境中第3步执行的语句;

  1. 添加字段到你的模型中。如果你在开发时使用了版本控制系统并checkin了你的修改,现在可以更新代码到发布服务器上了(例如,使用Subverison的话就是 svn update )。

  1. 重启Web服务器以使代码修改生效

2、删除字段

从模型里删除一个字段可要比增加它简单多了。删除一个字段仅需要做如下操作:

从你的模型里删除这个字段,并重启Web服务器。

使用如下面所示的命令,从你的数据库中删掉该列:

3、删除 Many-to-Many 字段

 

因为many-to-many字段同普通字段有些不同,它的删除过程也不一样:

删除掉你的模型里的 ManyToManyField ,并且重启Web服务器。

使用如下面所示的命令,删除掉你数据库里的many-to-many表:

DROP TABLE books_books_publishers;

4、删除模型

 

完全删除一个模型就像删除一个字段一样简单。删除模型仅需要做如下步骤:

将此模型从你的 models.py 文件里删除,并且重启Web服务器。

使用如下的命令,将此表从你的数据库中删除:

DROP TABLE books_book;


 

 

 

 

 

 

posted @ 2011-11-01 16:29  lhj588  阅读(724)  评论(0编辑  收藏  举报