python学习笔记--Django入门三 Django 与数据库的交互:数据建模

时间:2021-09-02 13:31:18

把数据存取逻辑、业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的 Model-View-Controller (MVC)模式。在这个模式中, Model 代表数据存取层,View 代表的是系统中选择显示什么和怎么显示的部分,Controller 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。

由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在 MTV 开发模式中:

  M 代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如何存取、如何确认有效性、包含哪些行为以及数据之间的关系等。

  T 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。

  V代表View,业务逻辑层。这一层包含访问模型的逻辑和按照模板显示。你可以认为它是模型和模板的桥梁。

数据库配置

修改配置文件 settings.py

DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

mysql多实例可以指定用户

DATABASE_HOST = '/data/3306/mysql.sock'

高版本的Django连接数据库配置有所不同,参考原版文档:

python学习笔记--Django入门三  Django 与数据库的交互:数据建模

如果你只是建造一个简单的web站点,那么可能你只需要一个app就可以了。如果是复杂的象 电子商务之类的Web站点,你可能需要把这些功能划分成不同的app,以便以后重用。

系统对app有一个约定:如果你使用了Django的数据库层(模型),你 必须创建一个django app。模型必须在这个app中存在。因此,为了开始建造 我们的模型,我们必须创建一个新的app。

转到 mysite 项目目录,执行下面的命令来创建一个新app叫做books:

python manage.py startapp books

在 mysite 目录下创建了一个 books 的文件夹

books/
__init__.py
models.py
views.py

创建你的第一个模型

在Django中使用该数据库布局的第一步是将其表述为Python代码。在通过“startapp”命令创建的“models.py”文件中,输入如下代码:

from django.db import models

class Publisher(models.Model):
name = models.CharField(max_length=30)
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() class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField() class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。 属性名就是字段名,它的类型(例如 CharField )相当于数据库的字段类型 (例如 varchar )。例如, Publisher 模块等同于下面这张表(用PostgreSQL的 CREATE TABLE 语法描述):

CREATE TABLE "books_publisher" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar() NOT NULL,
"address" varchar() NOT NULL,
"city" varchar() NOT NULL,
"state_province" varchar() NOT NULL,
"country" varchar() NOT NULL,
"website" varchar() NOT NULL
);

其中:

SERIAL是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的一个别名。

在整数列定义中,SERIAL DEFAULT VALUE是NOT NULL AUTO_INCREMENT UNIQUE的一个别名。

注:上面NOT NULL是不可为空,AUTO_INCREMENT是递增,指定起始值为1用AUTO_INCREMENT=1语句,不指定默认也为1。

UNIQE是不可重复的意思,取值不能与已经存在的数据重复。

“每个数据库表对应一个类”这条规则的例外情况是多对多关系。 在我们的范例模型中, Book 有一个 多对多字段 叫做 authors 。 该字段表明一本书籍有一个或多个作者,但 Book 数据库表却并没有 authors 字段。 相反,Django创建了一个额外的表(多对多连接表)来处理书籍和作者之间的映射关系。

模型安装

一个project包含很多个Django app以及对它们的配置。

技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息, 安装的app列表, TEMPLATE_DIRS,等等。

一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。

例如,Django本身内建有一些app,例如注释系统和自动管理界面。 app的一个关键点是它们是很容易移植到其他project和被多个project复用。

完成这些代码之后,现在让我们来在数据库中创建这些表。要完成该项工作,第一步是在 Django 项目中 激活 这些模型。将 books app 添加到配置文件的已 installed apps 列表中即可完成此步骤。

再次编辑 settings.py 文件, 找到 INSTALLED_APPS 设置。 INSTALLED_APPS 告诉 Django 项目哪些 app 处于激活状态。缺省情况下如下所示:

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

检查试会报错:

TypeError: __init__() got an unexpected keyword argument ‘maxlength’

应该是以前的版本是应该用maxlength,但是新版本里面使用max_length

在vim中替换    :%s/maxlength/max_length/g

然后再次报错:

Error: One or more models did not validate:
books.author: "headshot": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .

那就开始安装这个库:

pip install PIL

DEPRECATION: Python 2.6 is no longer supported by the Python core team, please upgrade your Python. A future version of pip will drop support for Python 2.6
Collecting PIL
Could not find a version that satisfies the requirement PIL (from versions: )
No matching distribution found for PIL

只能升级python了

升级到了2.7版本,还是报错,干脆升级到3.X看看情况:使用souhu的源还是比较快

wget http://mirrors.sohu.com/python/3.3.3/Python-3.3.3.tar.bz2

在编译前先在/usr/local建一个文件夹python3.3 .3(作为Python的安装路径,以免覆盖老的版本)

mkdir -p /usr/local/python-3.3.3

在解压缩后的目录下编译安装

./configure --prefix=/usr/local/python-3.3.3
make && make install

将原来/usr/bin/python链接改为别的名字

mv /usr/bin/python /usr/bin/python_old

再建立新版本python的链接

ln -s /usr/local/python3.3.3/bin/python3 /usr/bin/python

安装好之后,需要重新安装setuptools , pip ,MySQLdb, Django

但是经历了好多,发现对这些的支持都有问题,索性,换一个方法来做:

还是用系统自带的python2.6.6 , 其他的插件,不用pip来安装,直接下载先来自己安装

Imaging-1.1.7

python setup.py install  然后就搞定了

继续问题前的操作

python manage.py validate

看到 0 errors found 消息,一切正常。继续:

运行下面的命令来生成 CREATE TABLE 语句:

python manage.py sqlall books
BEGIN;
CREATE TABLE `books_publisher` (
`id` integer AUTO_INCREMENT 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_author` (
`id` integer AUTO_INCREMENT 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` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`title` varchar(100) NOT NULL,
`publisher_id` integer NOT NULL,
`publication_date` date NOT NULL
)
;
ALTER TABLE `books_book` ADD CONSTRAINT `publisher_id_refs_id_4cdc253fc5b274bb` FOREIGN KEY (`publisher_id`) REFERENCES `books_publisher` (`id`);
CREATE TABLE `books_book_authors` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`book_id` integer NOT NULL,
`author_id` integer NOT NULL,
UNIQUE (`book_id`, `author_id`)
)
;
ALTER TABLE `books_book_authors` ADD CONSTRAINT `book_id_refs_id_5565ddfcfbcf262` FOREIGN KEY (`book_id`) REFERENCES `books_book` (`id`);
ALTER TABLE `books_book_authors` ADD CONSTRAINT `author_id_refs_id_1f0e145e09e7e386` FOREIGN KEY (`author_id`) REFERENCES `books_author` (`id`);
CREATE INDEX `books_book_publisher_id` ON `books_book` (`publisher_id`);
COMMIT;

sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来。运行 syncdb 命令

python manage.py syncdb
Creating table books_publisher
Creating table books_book
Creating table books_author
Installing index for books.Book model

成功创建了表

基本数据访问

添加一个方法 __unicode__() 到 Publisher 对象。 __unicode__() 方法告诉Python要怎样把对象unicode的方式显示出来.

普通的python字符串是经过编码的,意思就是它们使用了某种编码方式(如ASCII,ISO-8859-1或者UTF-8)来编码。

但是Unicode对象并没有编码。它们使用Unicode,一个一致的,通用的字符编码集。 当你在Python中处理Unicode对象的时候,你可以直接将它们混合使用和互相匹配而不必去考虑编码细节。

from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
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 Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField() **def __unicode__(self):**
**return u'%s %s' % (self.first_name, self.last_name)** class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField() **def __unicode__(self):**
**return self.title**
 
>>> from books.models import Publisher
>>> p1 = Publisher(name='Addison-Wesley', address='75 Arlington Street',
... city='Boston', state_province='MA', country='U.S.A.',
... website='http://www.apress.com/')
>>> p1.save()
>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
... city='Cambridge', state_province='MA', country='U.S.A.',
... website='http://www.oreilly.com/')
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list [<Publisher: Addison-Wesley>, <Publisher: O'Reilly>]
 

所有的数据库查找都遵循一个通用模式:调用模型的管理器来查找数据。

数据过滤

如果想要获得数据的一个子集,我们可以使用 filter() 方法:SQL缺省的 = 操作符是精确匹配的

Publisher.objects.filter(country="U.S.A.", state_province="CA")

这个 __contains 部分会被Django转换成 LIKE SQL语句

Publisher.objects.filter(name__contains="press")

等同于:

SELECT
id, name, address, city, state_province, country, website
FROM book_publisher
WHERE name LIKE '%press%';

获取单个对象

使用 get() 方法:

Publisher.objects.get(name="Apress Publishing")

数据排序

用 order_by() 来 排列返回的数据:

Publisher.objects.order_by("name")

还可以指定逆向排序,在前面加一个减号 - 前缀:

Publisher.objects.order_by("-name")

每次都要用 order_by() 显得有点啰嗦。 大多数时间你通常只会对某些 字段进行排序。在这种情况下,Django让你可以指定模型的缺省排序方式:

class Publisher(models.Model):
name = models.CharField(maxlength=30)
address = models.CharField(maxlength=50)
city = models.CharField(maxlength=60)
state_province = models.CharField(maxlength=30)
country = models.CharField(maxlength=50)
website = models.URLField() def __str__(self):
return self.name class Meta:
ordering = ["name"]

这个 ordering = ["name"] 告诉Django如果没有显示提供 order_by() , 就缺省按名称排序。

可以同时做这 过滤和排序

Publisher.objects.filter(country="U.S.A.").order_by("-name")

限制返回的数据

只想显示第一个

Publisher.objects.all()[0]

删除对象

调用对象的 delete() 方法:

p = Publisher.objects.get(name="Addison-Wesley")
p.delete()

后边的数据库操作比较繁琐,就等用的时候再学习更新吧