Python开发入门与实战5-django模型
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模型的更多相关文章
- Python开发入门与实战6-表单
6. 表单 从简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的重要交互手段.本章介绍如何用Django如何对用户通过表单提交的数据进行访问. ...
- Python开发入门与实战1-开发环境
1.搭建Python Django开发环境 1.1.Python运行环境安装 Python官网:http://www.python.org/ Python最新源码,二进制文档,新闻资讯等可以在Pyth ...
- Python开发入门与实战8-基于Java的集成开发环境
8. 基于Java的Python的集成开发环境 目前为止我们所有的代码和例子都是通过Notepad文本编辑器来实现的,实际项目开发中这种编码模式效率较低(大虾除外),使用IDE集成开发环境常常大幅度的 ...
- Python开发入门与实战18-Windows Azure 虚拟机部署
18. 微软云虚拟机部署 上一章节我们介绍了如何在新浪云部署我们的在python django应用,本章我们来介绍如何Windows Azure上部署我们的应用. 18.1. 注册Windows Az ...
- Python开发入门与实战16-APACHE部署
16. Windows平台apache部署 本章节我们简要的描述一下如何在windows平台部署apache的django站点. Python Django 项目部署发布到windows apache ...
- Python开发入门与实战2-第一个Django项目
2.第一个Django项目 上一章节我们完成了python,django和数据库等运行环境的安装,现在我们来创建第一个django project吧,迈出使用django开发应用的第一步. 2.1.创 ...
- Python开发入门与实战13-基于模板的界面
13. 基于模板的界面 本章我们将继续基于库存的简单例子来阐述如何在python django中体现MVC的架构,根据djangobook说明: M:数据存取部分,由django数据库层处理,本章要讲 ...
- Python开发入门与实战12-业务逻辑层
12. Biz业务层 前面的章节我们把大量的业务函数都放在了views.py里,按照目前这一的写法,当我们编写的系统复杂较高时,我们的views.py将会越来越复杂,大量的业务函数包含其中使其成为一个 ...
- Python开发入门与实战4-模板页面
4.Django基于模板页面 在前一章中,HTML是直接被硬编码在 Python views.py代码中,如下: from django.http import HttpResponse import ...
随机推荐
- Notepad++的列编辑功能
转自:http://www.crifan.com/files/doc/docbook/rec_soft_npp/release/htmls/index.html http://www.crifan.c ...
- Posix消息队列
转载于:http://blog.csdn.net/zx714311728/article/details/53197196 1.消息队列 消息队列可以认为是一个消息链表,消息队列是随内核持续的.队列中 ...
- CentOS7安装memcached
三台linux服务器系统CentOS7 一台memcached IP:192.168.155.134 一台Apache IP:192.168.155.130 一台nginx IP:192.168.15 ...
- MySQL如何关联查询
总的来说,mysql认为任何一个查询都是一次关联,并不仅仅是一个查询需要用到两个表匹配才叫关联,所以,在mysql中,每一个查询,每一个片段(包括子查询,甚至单表select)都可能是关联.所以,理解 ...
- ubuntu下gcc、g++和gfortran版本切换
第一步:用 which gcc.which g++和which gfortran查看位置,我的显示结果为:/usr/bin/gcc:/usr/bin/g++和/usr/bin/gfortran 第二部 ...
- 【转】 Tomcat v7.0 Server at localhost was unable to start within 45
转载地址:http://www.jsjtt.com/java/JavaWebkaifa/58.html Starting Tomcat v7.0 Server at localhost' has en ...
- Python学习笔记-常用模块
1.python模块 如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失.因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作 ...
- 自己封装的json工具类
package com.develop.util; import java.util.ArrayList; import java.util.HashMap; import java.util.Ite ...
- [poj2828] Buy Tickets (线段树)
线段树 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must ...
- Cheatsheet: 2015 08.01 ~ 08.31
Java Beginner's Guide to MVC with Spring Framework Exploring the Spring Web MVC for Web Application ...