一、在视图中进行数据库查询的笨方法
例如:本例的视图中,使用pymysql数据库,取回一些记录,将他们提供给模板以显示一个网页
- views.py
from django.shortcuts import render_to_response
import pymysql
def book_list(request):
db = pymysql.connect(user='me', db='mydb', passwd='secret', host='localhost')
cursor = db.cursor()
cursor.execte('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'})
- 项目主目录下面的 init.py
# 原因:py3中没有MySQLdb模块,被pymysql模块代替了,但是django2中默认使用mysql模块为MySQLdb模块,所以需要如下设置
import pymysql
pymysql.install_as_MySQLdb()
上述代码的弊端
- 数据库连接参数硬编码于代码之中。理想情况下,这些参数应当保存在Django配置中
- 不得不重复同样的代码:创建数据库,创建数据库游游标,执行某个语句,然后关闭数据库。理想情况下,我们所需要应该只是指定所需的结果
- 如果要更换是巨款,不得不使用不同的数据库适配器,改变连接参数,根据SQL语句的类型可能还要修改SQL。理想情况下,应对所使用的数据库服务器进行抽象,这样一来只在一处修改即可变换数据库服务器。
二、利用Django数据库层API重写数据库查询
from django.shortcuts import render_to_response
from mysite.books.models import Book
def book_list(request):
books = Book.objects.order_by('name')
return render_to_response('book_list.html', {'names':'names'})
三、MTV开发模式
1.MVC
- Model:数据存取层,由Django数据库层处理
- View:选择显示哪些数据以及怎样显示的部分,由视图和模板处理
- Controller:根据用户输入委派视图的部分,由Django框架根据URLconf设置,对给定URL调用适当的Python函数
2.MTV
- Model:数据存取部分,该层处理与数据相关的所有事务:如何存取、如何验证有效性,包含哪些行为以及数据之间的关系等
- Template:表现层,该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示
- View:业务逻辑层,该层包含存取模型及调取恰当模板的相关逻辑。可以看做模型与模板之间的桥梁。
四、数据库配置
1. 配置数据库
- settings.py
DATABASES = {
'default': {
'ENGINE': '', # 数据库引擎
'HOST': '', # 数据库主机
'PORT': '', # 数据库端口
'NAME': '', # 数据库名字
'USER': '', # 用户名
'PASSWORD':'', # 密码
}
}
数据库的引擎必须是下面的一种
设置 | 数据库 | 所需适配器 |
---|---|---|
'django.db.backends.postgresql' | PostgreSQL | psycopg1.x 版本 |
'django.db.backends.postgresql_psycopg2' | PostgreSQL | psycopg2.x 版本 |
'django.db.backends.mysql' | MySQL | MySQLdb |
'django.db.backends.sqlite3' | SQLite | 如果使用Python2.5+则不需要适配器,否则需要使用pysqlite |
'django.db.backends.oracle' | Oracle | cx_Oracle |
注意: 无论是选择使用哪个数据库服务器,都必须下载和安装对应的数据库适配器
2. 测试数据库配置是否成功
- 1.进入python交互环境
python manage.py shell
- 2.测试数据库配置是否成功
from django.db import connection
cursor = connection.cursor()
如果没有显示什么错误信息,那么数据库配置是正确的。
3. 数据库配置错误信息
数据库配置错误信息五、Django应用程序
1.django中project和app的区别
区别:project是配置,app是代码
- project:包含很多Django app以及对它们的配置
技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息,安装app列表。
- app:一套Django功能的集合,通常包括模型和视图,按python的包结构的方式存在
例如,python本身内建有一些app,例如注释系统和自动管理界面。
app的一个关键点:它们是很容易移植到其他project和被多个project复用
系统对app有一个约定:如果你使用了Django的数据库层(模型),必须创建一个Django app。模型必须存放在apps中。
2.创建books app
python manage.py startapp books
# 或者以下代码
django-admin startapp books
3.在python代码里定义模型
MTV中M代码模型。Django模型是用python代码形式表述的数据在数据库中的定义。
对于数据层来说它等同于CREATE TABLE语句,只不过执行的是Python代码 而不是SQL,而且还包含了比数据库定义字段更多的含义。
django中使用python和SQL来定义数据模型的好处
自省(运行时自动识别数据库)会导致过载和有数据完整性问题。为了提供方便的数据访问API,Django需要以某种方式知道数据库层内部信息。
有两种实现方式
- 方式一:用python明确地定义数据模型
优点:把数据模型用代码的方式来表述让你可以很容易对它们进行版本控制。
缺点:python代码和数据库表的同步问题。如果你修改了一个Django模型,你要自己来修改数据库来保证和模型同步。
注意:Django提供了实用工具来从现有的数据库表中自动扫描生成模型,这对已有的数据库来说是非常快捷有用的,在笔记(十七)中会对此表述、
- 方式二:通过自省来自动侦测识别数据模型
第二种方式看起来更清晰,因为数据库表信息只存放在一个地方:数据库里,但是会带来一些问题。
- 第一,运行时扫描数据库会带来严重的系统过载。如果每个请求都要扫描数据库的表结构,或者即便是服务启动时做一次都是会带来不能接受的系统过载。
*第二,某些数据库,尤其是老版本的MySQL,并未完整存储那些精确的自省元数据。
- 只使用SQL的弊端
- SQL只能描述特定类型的数据字段。
例如,大多数数据库都没有专门的字段类型来描述Email地址、URL,而Django的模型可以做到这一点- SQL还有在不同数据库平台的兼容性问题。
发布web应用的时候,使用python模块描述数据库结构信息可以避免为MySQL,postgresSQL,sqlite等编写不同的create table。
六、Django应用程序中写一个模型
1.举例数据库结构
在本章和后续章节里,把注意力放在一个基本的书籍/作者/出版商数据库结构上。
假定下面的这些概念、字段和关系
- 一个作者有姓,有名及email地址
- 出版商有名称、地址、所在城市、省、国家、网站
- 书籍有书名和出版日期,有一个或多个作者(manytomany),只有一个出版商(onetoone),也被称为外键
2.用python代码来描述
- 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.CharField(max_length=30)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.OneToOneField(Publisher)
publication_date = models.DateField()
3.讲解代码
- 首先要注意的是每个数据模型都是django.db.models.Model的子类。它的父类Model包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。
- 每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。如CharField相当于数据库字段类型的varchar
- 除非你单独指明主键,否则Django会自动为每个模型生成一个自增长的整数主键字段。每个Django模型都要求有单独的主键id。
4. 模型安装
完成代码之后,需要在数据库中创建这些表。
Step1:在Django项目中激活模型
将books app添加到配置文件的已安装应用列表中
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'books',
]
Step2:创建数据库表
- 验证模型的有效性
python manage.py validate # django1.7-
python manage.py check # django1.7+
如果一切正常,会出现System check identified no issues (0 silenced).
如果出错,请检查你输入的模型代码。
- 生成CREATE TABLE语句
python manage.py sqlall books #django1.0版本
python manage.py makemigrations books #django1.8+
python manage.py sqlmigrate books 0001 # 查看生成的sql语句
5.基本数据访问
一旦你创建了模型,Django自动为这些模型提供了高级的Python API。运行python manage.py shell并输入下面的内容:
代码解读
- 首先,导入Publisher模型类,通过这个类我们可以包含出版社的数据表进行交互
- 接着,创建一个“Publisher”类的实例并设置了字段"name, address"等的值
- 调用该对象的save()方法,将对象保存到数据库中,Django会在后台执行一条insert语句
- 最后,使用Publisher.objects属性从数据库取出出版商的信息。
为模型添加unicode()方法
告诉python如何将对象以Unicode的方式显示出来
注意:对unicode()的唯一要求就是它要返回一个unicode对象 ,如__unicode__()
方法未返一个Unicode象,而返回比如说一个整型数字,那么Pytho将抛出一个TypeError
错误,并提示:”coercing to Unicode: need string or buffer, int found” 。
附加:什么是Unicode对象?
Unicode对象就是一个python字符串,可以处理上百万种不同类别的字符。
普通的python字符串是经过编码的,意思就是它们使用了某种编码方式(如ASCII,ISO-8859-1或者UTF-8)来编码。 如果你把奇特的字符(其它任何超出标准128个如0-9和A-Z之类的ASCII字符)保存在一个普通的
Python字符串里,你一定要跟踪你的字符串是用什么编码的,否则这些奇特的字符可能会在显示或者打印的时候出现乱码。 当你尝试要将用某种编码保存的数据结合到另外一种编码的数据中,或者你想要把它显示在已经
假定了某种编码的程序中的时候,问题就会发生。 我们都已经见到过网页和邮件被???弄得乱七八糟。 ??????或者其它出现在奇怪位置的字符:这一般来说就是存在编码问题了。但是Unicode对象并没有编码。它们使用Unicode,一个一致的,通用的字符编码集。 当你在Python中处理Unicode对象的时候,你可以直接将它们混合使用和互相匹配而不必去考虑编码细节。
Django 在其内部的各个方面都使用到了 Unicode 对象。 模型 对象中,检索匹配方面的操作使用的是Unicode 对象,视图 函数之间的交互使用的是 Unicode 对象,模板的渲染也是用的 Unicode 对象。 通常,我们不必担心编码是否正确,后台会处理的很好。注意,我们这里只是对Unicode对象进行非常浅显的概述,若要深入了解你可能需要查阅相关的资料。 这是一
个很好的起点:http://www.joelonsoftware.com/articles/Unicode.html。
tips:请确保你的每一个模型里都包含 unicode() 方法,这不只是为了交互时方便,也是因为 Django会在其他一些地方用 unicode() 来显示对象。
数据操作
-
插入和更新数据
-
选择对象
让我们来仔细看看 Publisher.objects.all() 这行的每个部分:
- 首先,我们有一个已定义的模型Publisher 。没什么好奇怪的: 你想要查找数据, 你就用模型来获得数据。
- 然后,是objects属性。它被称为管理器,我们将在第10章中详细讨论它。目前,我们只需了解管理器管理着所有针对数据包含、还有最重要的数据查询的表格级操作。
所有的模型都自动拥有一个objects 管理器;你可以在想要查找数据时使用它。
- 最后,还有all() 方法。这个方法返回返回数据库中所有的记录。尽管这个对象 看起来 象一个列表(list),它实际是一个 QuerySet 对象, 这个对象是数据库中一些记录的集合。附录C将详细描述QuerySet。现在,我们就先当它是一个仿真列表对象好了
-
数据过滤
- 获取单个对象
-
数据排序
尽管很灵活,但是每次都要用 order_by() 显得有点啰嗦。 大多数时间你通常只会对某些 字段进行排序。 在这种情况下,Django让你可以指定模型的缺省排序方式:
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 Meta:**
**ordering = ['name']**
class Meta,内嵌于 Publisher 这个类的定义中,你可以在任意一个 模型 类中使用 Meta 类,来设置一些与特定模型相关的选项。
-
连锁查询
-
限制返回的数据
- 更新多个对象
-
删除对象
网友评论