5.Django模型

  在当今的Web 应用中,主观逻辑经常牵涉到与数据库的交互,数据库驱动网站。在后台连接数据库服务器,从中取出一些数据,然后在 Web 页面用各种各样的格式展示这些数据。这个网站也可能会向访问者提供修改数据库数据的方法。

  本章深入介绍了该功能: Django 数据库层。本例我们使用Python安装包自带的SQLite数据库来演示Django如何访问数据库。

5.1.SQLite数据库

  首先我们使用数据库访问工具Navicat premium来在mysite目录下创建SQLite数据库文件。Navicat premium下载地址http://navicat-premium.softonic.cn/

运行Navicat premium工具,在主界面的菜单中选择文件->新建连接-SQLite如下图:

  在对话框中选择新建SQLite3数据库文件,数据库文件名命名为:MyDB.db后点击确定按钮。如下图:

  数据库文件连接后,界面展开如下图:

5.2. 执行SQL的访问数据库模式

  现在我们可以通过执行SQL的方式来访问数据库,获取数据并更新到我们的动态页面中,修改views.py把current_datetime视图获取时间的方式修改为通过执行SQL “select datetime() as now”读取数据库的时间,修改后代码如下:

from django.shortcuts import render_to_response

import sqlite3

def current_datetime(request):

  db = sqlite3.connect('C:\My Files\Python Projects\mysite\Mydb.db')

  cursor = db.cursor()

  cursor.execute('select datetime() as now')

  now = [row[0] for row in cursor.fetchall()]

  db.close()

  return render_to_response('current_datetime.html', {'current_date': now})

  如上代码,我是经过代码重构,current_datetime实现了读取数据库的当前时间,但是这种把SQL与业务逻辑完全绑定的开发模式会存为将来维护和升级的噩梦。业务变更导致的业务逻辑调整,进而需要调整到SQL代码,最后就与数据库设计深度绑定,尤其切换数据库时由于各个数据库支持的SQL不完全一致,应用的迁移将花费的代价更大。

  好在Django提供了自己的对象持久化模型,实现了对象模型到数据库表的映射机制,接下来我们进入Django的对象模型来实现数据库数据的读取。

5.3. 通过模型访问数据库模式

  Django 紧紧地遵循这种 MVC 模式,可以称得上是一种 MVC 框架。MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式。

5.3.1. 数据库配置

  我们来看看 Django 数据库模型层的功能吧。 首先,需要做些初始配置;需要告诉Django使用什么数据库以及如何连接数据库。本例我们使用SQLite数据库文件系统来存储数据。

  如前面章节提到的 TEMPLATE_DIRS 一样,数据库配置也是在Django的配置文件settings.py里。默认生成的数据库配置如下:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', '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.
}
}

  修改配置文件如下:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends. sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': ' C:\My Files\Python Projects\mysite\MyDB.db', # 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.
}
}

  完成设置并保存之后我们测试一下配置。 同样,在“mysite”项目目录下执行前面提到的“python manage.py shell”环境来进行测试。

输入下面的命令来测试数据库配置是否正确:

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

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

5.4. 第一个应用程序

  数据库连接正常工作后,让我们来创建一个 Django app,一个包含模型,视图和Django代码,并且形式为独立Python包的完整Django应用。

在这里先解释说明一些术语,初学者可能会混淆它们。在第二章我们已经创建了一个project,那么 project 和 app 之间不同之处是什么呢?它们的区别就是一个是配置另一个是业务代码

一个project包含很多个Django app。project的作用是提供这些应用统一配置文件,比如前面定义数据库连接信息, 需要装载的app列表,TEMPLATE_DIRS等。

一个app是一套业务功能的集合,通常包括模型和视图,按Python的包结构的方式存在。app的一个关键点是它们是很容易移植到其他project和被多个project复用。

Django系统对app有一个约定: 要使用Django的数据库层(模型),必须创建一个Django app,模型存放在apps中。在 “mysite” 项目文件下输入下面的命令来创建“inventory”的app,本例将以简单出入库业务来说明Django的模型。

>>> python manage.py startapp inventory

  增加子目录及子目录inventory 包含文件如下图:

inventory /
__init__.py
models.py
tests.py
views.py

5.4.1. 第一个模型

  在本章和后续章节里,我们将实现一个基本的库存管理(库存/出入库)的数据库结构上,这也是一个作者遇到过的比较典型关于业务及业务事务的例子。

库存管理涉及的基本概念、字段和关系:

    物料:物料编号、物料名称、备注。

    物料库存:物料编号、物料名称、库存数量。

    入库单:入库单编号、入库时间、操作人,物料编码、物料名称、入库数量。

  注意:本模型为便于阐述简化设计入库单为单一物料入库单,后面的章节我们会逐步扩展这一模型以符合实际的需要。

  物料与物料库存是一个one-to-one关系, 对于入库单模型来说其与物料的关系是many-to-many关系。

  接下来我们用Python代码来描述它们。 打开由创建的inventory \models.py 并输入下面的内容:

from django.db import models

# Create your models here.

class Item(models.Model):
ItemId = models.AutoField(primary_key=True)
ItemCode = models.CharField(max_length=50)
ItemName = models.CharField(max_length=50)
Remark = models.CharField(max_length=200) class Inventory (models.Model):
InventoryId = models.AutoField(primary_key=True)
Item = models.ForeignKey(Item, null=False)
Amount = models.IntegerField(null=True) class InStockBill(models.Model):
InStockBillId = models.AutoField(primary_key=True)
InStockBillCode = models.CharField(max_length=40)
InStockDate = models.DateTimeField(null=True)
Operator = models.CharField(max_length=40)
Item = models.ForeignKey(Item, null=False)
Amount = models.IntegerField(null=True)

5.4.2. 装载模型

  完成上面的模型代码后,现在让我们通过Django在数据库中创建这些表。第一步是在 Django 项目中装载这些模型。 将 inventory app 添加到配置文件的装载应用列表中即可。

  编辑 settings.py 文件, 找到 INSTALLED_APPS 设置。 INSTALLED_APPS 告诉 Django 项目需要装载哪些 app模型。 缺省生成代码在后面添加“inventory”到“INSTALLED_APPS”的末尾,注意:只配置应用名称,没有项目名称,代码如下:

INSTALLED_APPS = (
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.sites',
#'django.contrib.messages',
#'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'inventory',
)

  现在我们可以创建数据库表了。 首先,用下面的命令验证模型的有效性:

python manage.py validate

validate 命令检查你的模型的语法和逻辑是否正确。 如果一切正常,你会看到 0 errors found 消息。如果出错,根据错误信息来帮助你修正你的模型。

python manage.py sqlall inventory

  执行之后,输出如下:

BEGIN;
CREATE TABLE "inventory_item" (
"ItemId" integer NOT NULL PRIMARY KEY,
"ItemCode" varchar(50) NOT NULL,
"ItemName" varchar(50) NOT NULL
);
CREATE TABLE "inventory_inventory" (
"InventoryId" integer NOT NULL PRIMARY KEY,
"Item_id" integer NOT NULL REFERENCES "inventory_item" ("ItemId"),
"Amount" integer
);
CREATE TABLE "inventory_instockbill" (
"InStockBillId" integer NOT NULL PRIMARY KEY,
"InStockBillCode" varchar(40) NOT NULL,
"InStockDate" datetime,
"Operator" varchar(40) NOT NULL,
"Item_id" integer NOT NULL REFERENCES "inventory_item" ("ItemId"),
"Amount" integer
);
CREATE INDEX "inventory_inventory_70e6447b" ON "inventory_inventory" ("Item_id");
CREATE INDEX "inventory_instockbill_70e6447b" ON "inventory_instockbill" ("Item_id");
COMMIT;

  

sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来,这样你可以看到Django究竟会做些什么。

Django提供了一种更为简易的提交SQL语句至数据库的方法:“syncdb”命令

python manage.py syncdb

  syncdb 命令是同步你的模型到数据库的一个简单方法。 它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。

表创建结果如下图:

5.4.3.数据访问

  运行 python manage.py shell 并输入下面的内容试试看

>>> from inventory.models import Item
>>> itm1 = Item(ItemCode='',ItemName='螺帽')
>>> itm1.save()

  我们查看数据库看发生了什么,物料数据被保存到数据库中了,如下图:

  我们在数据库工具端增加一条记录:000,螺杆如下图:

  接下来再命令行窗口中录入如下命令:

>>> items =Item.objects.all()
>>> print items[1].ItemName
螺杆
>>>

  我们通过Item.objects.all()获取了所有的Item列表数据(当前只有两条)。

>>> itm2 = Item.objects.get(ItemId = 2)
>>> print itm2.ItemName
螺杆
>>> itm2.ItemName=u'5mm螺杆'
>>> itm2.save()
>>>

  修改对象属性后,保存数据,对象属性会同步到相应的数据行。

5.4.3.1. 保存有外键关联的模型

  我们创建一个入库单对象,并尝试如何正确的保存该对象到数据库中,命令如下:

>>> from inventory.models import Item
>>> from inventory.models import InStockBill
>>> inStock = InStockBill(InStockBillCode='',InStockDate='2014-11-01',Operator='张三',Amount=10)
>>> inStock.save()

  在没有赋值给InStockBill属性Item的情况下我们直接调用保存函数会报错,数据不能正常提交到数据库中。

>>> inStock.Item =  1

  我们直接给inStock.Item 赋值1(Itemid=1的物料在我们的例子中是前面保存进数据库的“螺母”),也会报错,虽然在数据库里,InStockBill表外键关系存储的是关联表的主键。需要inStock.Item赋值为一个具体的Item模型才能正常的提交数据。Django在这里已经把表映射为对象了。注:本例中入库单保存成功的同时,应该更新库存表数据(入库单将导致该物料库存数量增加)后面我们将在业务事物章节说明。

>>> item1 = Item.objects.get(ItemId=1)
>>> inStock.Item =item1
>>> inStock.save()
>>>

  这里我们会看见数据保存到数据库中后,入库时间变成了2014-10-31 16:00:00,这是因为settings.py时区设置为:TIME_ZONE = 'America/Chicago'的缘故,把USE_TZ = True修改为即可USE_TZ = False:

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = False

5.4.4. 数据排序

  在你的 Django 应用中,你或许希望根据某字段的值对检索结果排序,比如说,按字母顺序。 那么,使用 order_by() 这个方法就可以搞定了。

>>> itms = Item.objects.all()
>>> print itms[0].ItemCode
003 >>> itms = Item.objects.order_by('ItemCode')
>>> print itms[0].ItemCode
000

  Django指定模型的缺省排序方式,在模型配置中配置

class Item(models.Model):
ItemId = models.AutoField(primary_key=True)
ItemCode = models.CharField(max_length=50)
ItemName = models.CharField(max_length=50) class Meta:
ordering = ['ItemCode']

5.4.5. 数据删除

>>> itm2 = Item.objects.get(ItemId = 2)
>>> itm2.delete()
>>>

5.5. 小结

本章我们通过一个简单的实例模型例子来说Django模型如何创建、配置和访问数据库等。并通过Python环境演示了模型的装载、访问、查询、保存、排序和删除等操作。

下一章我们将介绍Django是如何实现通过客户端向服务端提交数据——表单。

Python开发入门与实战5-django模型的更多相关文章

  1. Python开发入门与实战6-表单

    6. 表单 从简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的重要交互手段.本章介绍如何用Django如何对用户通过表单提交的数据进行访问. ...

  2. Python开发入门与实战1-开发环境

    1.搭建Python Django开发环境 1.1.Python运行环境安装 Python官网:http://www.python.org/ Python最新源码,二进制文档,新闻资讯等可以在Pyth ...

  3. Python开发入门与实战8-基于Java的集成开发环境

    8. 基于Java的Python的集成开发环境 目前为止我们所有的代码和例子都是通过Notepad文本编辑器来实现的,实际项目开发中这种编码模式效率较低(大虾除外),使用IDE集成开发环境常常大幅度的 ...

  4. Python开发入门与实战18-Windows Azure 虚拟机部署

    18. 微软云虚拟机部署 上一章节我们介绍了如何在新浪云部署我们的在python django应用,本章我们来介绍如何Windows Azure上部署我们的应用. 18.1. 注册Windows Az ...

  5. Python开发入门与实战16-APACHE部署

    16. Windows平台apache部署 本章节我们简要的描述一下如何在windows平台部署apache的django站点. Python Django 项目部署发布到windows apache ...

  6. Python开发入门与实战2-第一个Django项目

    2.第一个Django项目 上一章节我们完成了python,django和数据库等运行环境的安装,现在我们来创建第一个django project吧,迈出使用django开发应用的第一步. 2.1.创 ...

  7. Python开发入门与实战13-基于模板的界面

    13. 基于模板的界面 本章我们将继续基于库存的简单例子来阐述如何在python django中体现MVC的架构,根据djangobook说明: M:数据存取部分,由django数据库层处理,本章要讲 ...

  8. Python开发入门与实战12-业务逻辑层

    12. Biz业务层 前面的章节我们把大量的业务函数都放在了views.py里,按照目前这一的写法,当我们编写的系统复杂较高时,我们的views.py将会越来越复杂,大量的业务函数包含其中使其成为一个 ...

  9. Python开发入门与实战4-模板页面

    4.Django基于模板页面 在前一章中,HTML是直接被硬编码在 Python views.py代码中,如下: from django.http import HttpResponse import ...

随机推荐

  1. usermod

    环境: [root@vm-xiluhua][/]# cat /etc/redhat-release CentOS Linux release (Core) usermod usage:(本人使用的版本 ...

  2. Normalize.css 初识

    一. 用来干嘛的 一个现代的.准备好了支持 HTML5 技术,并且要替代 CSS Reset 处理样式的理念. Normalize.css 使浏览器渲染所有元素更加一致,并且符合现代标准.它只是针对那 ...

  3. (转)Could not create the view: An unexpected exception was thrown. 电脑突然断电,myeclipse非正常关闭,出现错误

    问题:电脑突然断电,myeclipse非正常关闭,“Package Explorer”非正常显示,出现错误“Could not create the view: An unexpected excep ...

  4. 为linux系统添加虚拟内存swap分区

    阿铭linux学习笔记之swap分区 一.作用: swap分区是交换分区,在系统物理内存不足时与swap进行交换,对web服务器的性能影响极大,通过调整swap分区大小来提升服务器的性能,节省资源费用 ...

  5. nRF52系列来袭,Nordic的低功耗蓝牙方案大有可为

      坐落在北欧的挪威不像他的邻居芬兰那样,可以先后依靠NOKIA和愤怒的小鸟在世界科技界享有盛名.在一般人看来,挪威除了一个逐渐式微的Opera浏览器以外,并没有更多拿得出手的科技企业.而事实证明这只 ...

  6. Creating Custom Login Screen In Oracle Forms 10g

    Below is the example plsql unit to validate login credentials and after successful validation open a ...

  7. 使用VB6制作RTD函数

    以前模仿大神在vs里使用c#实现RTD函数功能.(真是很生僻的东东啊)C#制作RTD参考:大神博客跳转.最近想VB里能不能做?就试着做了做,好像基本成了,整套代码有些毛病,勉强能算个样子,暂时不打算再 ...

  8. 利用backtrace和objdump进行分析挂掉的程序

    转自:http://blog.csdn.net/hanchaoman/article/details/5583457 汇编不懂,先把方法记下来. glibc为我们提供了此类能够dump栈内容的函数簇, ...

  9. Statement returned more than one row, where no more than one was expected

    Statement returned more than one row, where no more than one was expected <resultMap id="Stu ...

  10. 《BI项目笔记》创建多维数据集Cube(1)

    有两个事实表,因此就有两个度量值组,并且向导将为非维度键的事实表中的每一个数值列创建一个度量值.由于我们这里不需要那么多,所以只选择部分度量值.另外要注意,度量值的名称源于事实表中的列,所有名称由可能 ...