5.Django模型

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

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

5.1.SQLite数据库

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

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

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

  数据库文件链接后,界面展开以下图:数据库

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

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

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的对象模型来实现数据库数据的读取。session

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

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

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='003',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='20141101001',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是如何实现经过客户端向服务端提交数据——表单。