Django模型-数据库操作

前言

  前边记录的URLconf和Django模板全都是介绍页面展示的东西,也就是表现层的内容。由于Python先天具备简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站。 这篇开始,进入到了Django模型,也就是数据库操作。

自带 Sqlite3 数据库查询方式

为了简单,使用Python自带的Sqlite3数据库进行实例说明。

先看一个传统的数据库操作示例:

 1 from django.shortcuts import render
 2 import sqlite3
 3 from django.http import HttpResponse
 4
 5 # Create your views here.
 6 def publist(request):
 7     conn = sqlite3.connect(‘db.sqlite3‘)
 8     cur = conn.cursor()
 9     html = ‘<html><body>‘
10     for record in cur.execute(‘select * from books_publisher‘):
11         for item in record:
12             html=html + str(item) +‘||‘
13         html = html+‘<br />‘
14
15     html=html+‘</body></html>‘
16     conn.close()
17
18     #return HttpResponse(cur.execute(‘select * from books_publisher‘).fetchall())
19     return HttpResponse(html)

这是你想要自己处理,所以使用了两个嵌套循环,其实实例根本不需这样的。第7、8和18行即可(这个结果会不一样,是个字段的字符串连接)。

结果如下截图:

简单入门查看这里,vamei的Python入门系列-数据库

这个方法,有几个问题:

  • 将数据库连接参数硬行编码于代码之中。比如Mysql数据库
MySQLdb.connect(user=‘me‘, db=‘mydb‘, passwd=‘secret‘, host=‘localhost‘)
  • 重复同样的代码: 创建数据库连接、创建数据库游标、执行某个语句、然后关闭数据库
  • 切换数据库可能需要改变连接参数,甚至sql语句。

Django 数据库 API

正如你所期待的,Django数据库层正是致力于解决这些问题。 以下提前揭示了如何使用 Django 数据库 API 重写之前那个视图。

1 def publisher_list(request):
2     return  HttpResponse(Publisher.objects.order_by(‘name‘))

结果如下截图:

结果稍有不同,这些接下来会说。重点要说的是,这,有没有太简洁了!

上边两个地址配置urls.py如下

1 url(r‘^books/publist/$‘,publist),
2 url(r‘^books/publisherlist/$‘,publisher_list),

设置并保存数据库配置

这里不介绍这些了,有想看的请查看原文的数据库配置一节(因为文章介绍比较老,所以有可能和现在的项目是有区别的,请注意)

下边的内容都假设已经配置好了数据库。我的实例是基于Sqlite的,所以没做任何配置,当你执行某些数据库操作时,Django帮我们自动做好了这些。

在项目目录下执行 python manager.py shell (再说一次,这个 命令是以正确Django配置启用Python交互解释器的一种方法。这里,Django要去查找正确的数据库配置)

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

用于检测配置的数据库环境是否有异常。

第一个数据库应用程序

Django app

一个包含模型,视图和Django代码,并且形式为独立Python包的完整Django应用。

之前所有的实例我们是在一个project中进行的(还记得 python django-admin.py startproject mysite 吧)

那么 project 和 app 之间到底有什么不同呢?它们的区别就是一个是配置另一个是代码:

  • 一个project包含很多个Django app以及对它们的配置
  • 一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。

可以不用创建app,我们之前的站点已经说明了这点。但是系统对app有一个约定: 如果你使用了Django的数据库层(模型),你必须创建一个Django app。

创建app

他会创建一个books文件夹,里面包含如下文件

Django 紧紧地遵循MVC 模式的,由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),因此Django也被称为 MTV框架 。

在Python代码里定义模型

Django模型是用Python代码形式表述的数据在数据库中的定义。 对数据层来说它等同于 CREATE TABLE 语句,只不过执行的是Python代码而不是 SQL,而且还包含了比数据库字段定义更多的含义。 Django用模型在后台执行SQL代码并把结果用Python的数据结构来描述。 Django也使用模型来呈现SQL无法处理的高级概念。

第一个模型

定义一个基本的 书籍/作者/出版商 数据库结构。

第一步是用Python代码来描述它们。 打开由‘startapp’命令创建的models.py 并输入下面的内容:

 1 from django.db import models
 2
 3 class Publisher(models.Model):
 4     name = models.CharField(max_length=30)
 5     address = models.CharField(max_length=50)
 6     city = models.CharField(max_length=60)
 7     state_province = models.CharField(max_length=30)
 8     country = models.CharField(max_length=50)
 9     website = models.URLField()
10
11 class Author(models.Model):
12     first_name = models.CharField(max_length=30)
13     last_name = models.CharField(max_length=40)
14     email = models.EmailField()
15
16 class Book(models.Model):
17     title = models.CharField(max_length=100)
18     authors = models.ManyToManyField(Author)
19     publisher = models.ForeignKey(Publisher)
20     publication_date = models.DateField()

每个数据模型都是 django.db.models.Model 的子类。它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。属性名就是字段名,它的类型(例如CharField )相当于数据库的字段类型 (例如 varchar )。例如, Publisher 模块等同于下面这张表(用PostgreSQL的 CREATE TABLE 语法描述):

1 CREATE TABLE "books_publisher" (
2     "id" serial NOT NULL PRIMARY KEY,
3     "name" varchar(30) NOT NULL,
4     "address" varchar(50) NOT NULL,
5     "city" varchar(60) NOT NULL,
6     "state_province" varchar(30) NOT NULL,
7     "country" varchar(50) NOT NULL,
8     "website" varchar(200) NOT NULL
9 );

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

最后需要注意的是,我们并没有显式地为这些模型定义任何主键。 除非你单独指明,否则Django会自动为每个模型生成一个自增长的整数主键字段,每个Django模型都要求有单独的主键id

模型安装

再次编辑 settings.py 文件, 找到 INSTALLED_APPS 设置。 INSTALLED_APPS 告诉 Django 项目哪些 app 处于激活状态。

使用‘#‘注释掉该项配置里面的默认项,同时注释掉MIDDLEWARE_CLASSES的默认设置条目,因为这些条目是依赖于刚才我们刚在INSTALLED_APPS注释掉的apps。

添加‘mysite.books‘到INSTALLED_APPS,如下

 1 INSTALLED_APPS = (
 2 ##    ‘django.contrib.admin‘,
 3 ##    ‘django.contrib.auth‘,
 4 ##    ‘django.contrib.contenttypes‘,
 5 ##    ‘django.contrib.sessions‘,
 6 ##    ‘django.contrib.messages‘,
 7 ##    ‘django.contrib.staticfiles‘,
 8     ‘mysite.books‘,
 9 )
10
11 MIDDLEWARE_CLASSES = (
12 ##    ‘django.contrib.sessions.middleware.SessionMiddleware‘,
13 ##    ‘django.middleware.common.CommonMiddleware‘,
14 ##    ‘django.middleware.csrf.CsrfViewMiddleware‘,
15 ##    ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,
16 ##    ‘django.contrib.messages.middleware.MessageMiddleware‘,
17 ##    ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,
18 )

‘mysite.books‘指示我们正在编写的books app。 INSTALLED_APPS 中的每个app都使用 Python的路径描述,包的路径,用小数点“.”间隔。

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

如果我将上边settings.py中INSTALLED_APPS中添加的‘mysite.books‘改成’books‘则会出错,原因是路径错误(这个要看你的app创建的路径)

模型确认没问题了,运行下面的命令来生成 CREATE TABLE 语句

python manage.py sqlall books

在这个命令行中, books 是app的名称。 和你运行 manage.py startapp 中的一样

注意:

  • 自动生成的表名是app名称( books )和模型的小写名称 ( publisher , book , author )的组合
  • Django为每个表格自动添加加了一个 id 主键
  • Django添加 "_id" 后缀到外键字段名(外键是用 REFERENCES 语句明确定义或者(以及)多对多自动生成的关系对应表中的外键)
  • CREATE TABLE 语句会根据你的数据库而调整sql语句

不知你发现没,表books_book_authors中只有一个外键定义,按理应该还有一个book_id的外键

"book_id" integer NOT NULL REFERENCES "books_book" ("id"),

这里没有生成,不知道为什么?有知道的大牛园友,请指教

这就是models.py定义的数据模型对应的sql语句。sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来,这样你可以看到Django究竟会做些什么。我们可以拷贝这些语句到数据库客户端执行,不过Django为我们提供了一种更简易的方式:‘syncdb‘命令

python manage.py syncdb

syncdb 命令是同步你的模型到数据库的一个简单方法。 它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并 不能将模型的修改或删除同步到数据库;如果你修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。如果你再次运行 python manage.py syncdb ,什么也没发生,因为你没有添加新的模型或者 添加新的app。因此,运行python manage.py syncdb总是安全的,因为它不会重复执行SQL语句。

基本数据访问

创建模型之后,Django自动为这些模型提供了高级的Python API。 运行 python manage.py shell,运行如下代码

>>> from books.models import Publisher
>>> p1 = Publisher(name=‘Apress‘, address=‘2855 Telegraph Avenue‘,
...     city=‘Berkeley‘, state_province=‘CA‘, 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: Publisher object>, <Publisher: Publisher object>]
  • 首先,导入Publisher模型类, 通过这个类我们可以与包含 出版社 的数据表进行交互。
  • 接着,创建一个`` Publisher`` 类的实例并设置了字段‘name, address‘等的值。
  • 调用该对象的 save() 方法,将对象保存到数据库中。 Django 会在后台执行一条 INSERT 语句。
  • 最后,使用‘Publisher.objects‘属性从数据库取出出版商的信息,这个属性可以认为是包含出版商的记录集。 这个属性有许多方法,这里先介绍调用‘Publisher.objects.all()‘方法获取数据库中‘Publisher‘类的所有对象。这个操作的幕后,Django执行了一条SQL ‘SELECT‘ 语句。

当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用 save() 方法。

如果不想分成创建对象,save到数据库 这样两步完成,可以使用如下语句:

 >>> p1 = Publisher.objects.create(name=‘Apress‘,
...     address=‘2855 Telegraph Avenue‘,
...     city=‘Berkeley‘, state_province=‘CA‘, country=‘U.S.A.‘,
...     website=‘http://www.apress.com/‘)
>>> p2 = Publisher.objects.create(name="O‘Reilly",
...     address=‘10 Fawcett St.‘, city=‘Cambridge‘,
...     state_province=‘MA‘, country=‘U.S.A.‘,
...     website=‘http://www.oreilly.com/‘)
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Publisher object>, <Publisher: Publisher object>]

添加模块的字符串表现

当我们打印整个publisher列表时,我们没有得到想要的有用信息,而是像下面这样

[<Publisher: Publisher object>, <Publisher: Publisher object>]

我们可以简单解决这个问题,只需要为Publisher 对象添加一个方法 __unicode__() 。 __unicode__() 方法告诉Python如何将对象以unicode的方式显示出来

 1 class Publisher(models.Model):
 2     name = models.CharField(max_length=30)
 3     address = models.CharField(max_length=50)
 4     city = models.CharField(max_length=60)
 5     state_province = models.CharField(max_length=30)
 6     country = models.CharField(max_length=50)
 7     website = models.URLField()
 8
 9     def __unicode__(self):
10         return u‘name:%s , address: %s ||‘ % (self.name,self.address)

再执行Publisher.objects.all()

>>> Publisher.objects.all()
[<Publisher: name:Apress , address: 2855 Telegraph Avenue ||>, <Publisher: name:
Apress , address: 10 Fawcett St. ||>, <Publisher: name:Apress , address: 2855 Te
legraph Ave. ||>]

请确保每一个模型里都包含 __unicode__() 方法,这不只是为了交互时方便,也是因为 Django会在其他一些地方用 __unicode__() 来显示对象。

数据的增删改查

插入

创建实例对象,调用save()即可插入数据

更新

>>> p.name = ‘Apress Publishing‘
>>> p.save()

注意,这个save() 并不是只更新修改过的那个字段,所有的字段都会被更新!类似于:

UPDATE books_publisher SET
    name = ‘Apress Publishing‘,
    address = ‘2855 Telegraph Ave.‘,
    city = ‘Berkeley‘,
    state_province = ‘CA‘,
    country = ‘U.S.A.‘,
    website = ‘http://www.apress.com‘
WHERE id = 3;

而如下方式即可做到单列更新:用结果集(QuerySet)对象的update()方法

>>> Publisher.objects.all().update(country=‘USA‘)

类似于:

UPDATE books_publisher
SET country= ‘USA‘

查找

>>> Publisher.objects.all()

所有的模型都自动拥有一个 objects 管理器,用于获取数据库记录,返回对应模型。

all()返回所有记录。

1、过滤方法filter

filter() 接受多个参数

>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: name:Apress , address: 2855 Telegraph Ave. ||>]

filter() 根据关键字参数来转换成 WHERE SQL语句。

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = ‘U.S.A.‘
AND state_province = ‘CA‘;

注意 这里的‘=‘都是精确查找。

下边是模糊检索方式

>>> Publisher.objects.filter(name__contains="press")
[<Publisher: name:Apress , address: 2855 Telegraph Avenue ||>, <Publisher: name:
Apress , address: 10 Fawcett St. ||>, <Publisher: name:Apress , address: 2855 Te
legraph Ave. ||>]

在 name 和 contains 之间有双下划线。在 name 和 contains 之间有双下划线。

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name LIKE ‘%press%‘;

还有一些其他的查找类型,比如 icontains(大小写无关的LIKE),startswithendswith, 还有range(SQLBETWEEN查询)等

2、获取单个对象get

>>> Publisher.objects.get(country="U.S.A.")
<Publisher: name:Apress , address: 2855 Telegraph Ave. ||>

当get方法获取到结果不为一个时(0个或者大于1个)会抛出异常

排序order_by()

>>> Publisher.objects.order_by("address")
[<Publisher: name:Apress , address: 10 Fawcett St. ||>, <Publisher: name:Apress
, address: 2855 Telegraph Ave. ||>, <Publisher: name:Apress , address: 2855 Tele
graph Avenue ||>]

order_by()也可以接受多个参数,第二个字段会在第一个字段的值相同的情况下被使用到

Publisher.objects.order_by("state_province", "address")

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

>>> Publisher.objects.order_by("-address")
[<Publisher: name:Apress , address: 2855 Telegraph Avenue ||>, <Publisher: name:
Apress , address: 2855 Telegraph Ave. ||>, <Publisher: name:Apress , address: 10
 Fawcett St. ||>]
class Meta
 1 class Publisher(models.Model):
 2     name = models.CharField(max_length=30)
 3     address = models.CharField(max_length=50)
 4     city = models.CharField(max_length=60)
 5     state_province = models.CharField(max_length=30)
 6     country = models.CharField(max_length=50)
 7     website = models.URLField()
 8
 9     def __unicode__(self):
10         return u‘name:%s , address: %s ||‘ % (self.name,self.address)
11
12     class Meta:
13         ordering=[‘-name‘]

class Meta内嵌于 Publisher 这个类的定义中,如果你设置了这个选项,那么除非你检索时特意额外地使用了 order_by(),否则,当你使用 Django 的数据库 API 去检索时,Publisher对象的相关返回值默认地都会按 name 字段排序。

删除delete()

>>> Publisher.objects.filter(country=‘USA‘).delete()

前边所有获取单条记录、多条记录均可以在返回的结果集后进行删除。

链式操作

>>> Publisher.objects.filter(id=52).update(name=‘Apress Publishing‘)

限制结果

>>> Publisher.objects.order_by(‘name‘)[0:4]
[<Publisher: name:Apress , address: 2855 Telegraph Avenue ||>, <Publisher: name:
Apress , address: 10 Fawcett St. ||>, <Publisher: name:Apress , address: 2855 Te
legraph Ave. ||>]

超过索引不会报错。但是不支持Python的负索引。

小结

传统的Python数据库操作,Django app创建,Django的数据库 API,增删改查操作等。

  

Django模型-数据库操作,布布扣,bubuko.com

时间: 2024-10-05 05:50:18

Django模型-数据库操作的相关文章

django models 数据库操作

django models 数据库操作 创建模型 实例代码如下 from django.db import models class School(models.Model): pass class Message(models.Model): pass class Teacher(models.Model): pass class Student(models.Model): GENDER_CHOICES = ( ('male', "男"), ('female', "女&q

Django与数据库操作

Django与数据库操作 数据库连接的方法 web 框架 django --- 自己内部实现 (ORM) + pymysql(连接) Flask,tornado --- pymysql SQLArchemy (ORM) ORM 操作简单 (只把对象和类的操作 生成对应的sql语句) 创建,修改 数据表的时候简单 速度比原生的sql慢 -- 先转换成sql语句 原生sql执行会快 脚本运行Django的ORM操作数据库 import os,sys import django sys.path.ap

Django基础--数据库操作

Django中的模型(model)本质是数据库中的表(table),当作为开发者时,总会涉及到数据库的操作,而Django中也提供了一些函数,实现sql语句中的增删改查: 惯例,先看模型: 1 # coding:utf-8 2 import django.utils.timezone as timezone 3 from django.db import models 4 from blast_service.models import DiskInfo 5 # Create your mode

django学习-数据库操作接口API--(CRUD)

初试API(数据库操作接口CRUD) 现在我们进入交互式python命令行,尝试一下django为你创建的各种API,通过以下命令打开python命令行: py -3 manage.py shell进入python命令行 D:\django\mysite>py -3 manage.py shell Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32 Type &quo

django的数据库操作回顾

1.数据库操作 - 单表操作 - all - filter models.tb.objects.filter(id=123) dic = {'id': 123, 'age__gt': 3} models.tb.objects.filter(**dic) - count - order_by ... - 一对多 # id name 1 河北 2 广东 3 山东 class Province(models.Model): name = models.CharField(max_length=32,)

Django之数据库操作

1.创建model表,在setting中添加app名称.配置数据 from django.db import models class userinfo(models.Model): #如果没有models.AutoField,默认会创建一个id的自增列 name = models.CharField(max_length=30) email = models.EmailField() memo = models.TextField() 运行:python manage.py makemigra

django的数据库操作-16

目录 增 1.save 2.create 查 1.基本查询 2.过滤查询 3. F对象 4. Q对象 5. 聚合函数 6. 排序 7. 关联查询 8. 关联+过滤查询 删 改 1. save 2. update Django的manage工具提供了shell命令,已经帮助我们配置好当前工程的运行环境(如连接好数据库等),我们会在自带终端中执行测试python语句. manage.py 所在目录执行命令 python manage.py shell 这打开了一个交互式命令行. 导入模型类 from

django 的数据库操作

Python代码 class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __unicode__(self): return self.name class Author(models.Model): name = models.CharField(max_length=50) email = models.EmailField() def __unico

Django笔记-数据库操作(多对多关系)

1.项目结构 2.关键代码: data6.settings.py INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog', ) DATABASES = { 'default': {