第三篇数据库与ORM
第三篇 数据库与ORM
1 新建数据库
在终端cmd中
mysql –uroot –p 输入密码 SQL语句
creat database s9;
2 数据库的配置
2.1 Django默认支持sqlite,mysql,oracle,postgresql数据库
①sqlite
django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3
②mysql
引擎名称:django.db.backends.mysql
2.2 mysql驱动程序
- MySQLdb(mysql python)
- mysqlclient
- MySQL
- PyMySQL(纯python的mysql驱动程序)
2.3 在Django的项目中会默认使用sqlite数据库,在settings里有如下设置:
如果我们想要更改数据库,需要修改如下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'books', #你的数据库名称 'USER': 'root', #你的数据库用户名 'PASSWORD': '', #你的数据库密码 'HOST': '', #你的数据库主机,留空默认为localhost 'PORT': '', #你的数据库端口 } }
修改代码
注意:
NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 USER和PASSWORD分别是数据库的用户名和密码。 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。 然后,启动项目,会报错:no module named MySQLdb 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的__init__,在里面写入: import pymysql
pymysql.install_as_MySQLdb() 问题解决!
3 ORM表模型
表(模型)的创建:
实例:我们来假定下面这些概念,字段和关系
作者模型:一个作者有姓名。
作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。
出版商模型:出版商有名称,地址,所在城市,省,国家和网站。
书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键
from django.db import models<br>
class Publisher(models.Model):
name = models.CharField(max_length=, verbose_name="名称")
address = models.CharField("地址", max_length=)
city = models.CharField('城市',max_length=)
state_province = models.CharField(max_length=)
country = models.CharField(max_length=)
website = models.URLField() class Meta:
verbose_name = '出版商'
verbose_name_plural = verbose_name def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=)
def __str__(self):
return self.name class AuthorDetail(models.Model):
sex = models.BooleanField(max_length=, choices=((, '男'),(, '女'),))
email = models.EmailField()
address = models.CharField(max_length=)
birthday = models.DateField()
author = models.OneToOneField(Author) class Book(models.Model):
title = models.CharField(max_length=)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
price=models.DecimalField(max_digits=,decimal_places=,default=)
def __str__(self):
return self.title
表
分析代码:
<1> 每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。
<2> 每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。
<3> 模型之间的三种关系:一对一,一对多,多对多。
一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;
一对多:就是主外键关系;(foreign key)
多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)
4 ORM之增(create,save)
from app01.models import * #create方式一: Author.objects.create(name='Alvin') #create方式二: Author.objects.create(**{"name":"alex"}) #save方式一: author=Author(name="alvin")
author.save() #save方式二: author=Author()
author.name="alvin"
author.save()
重点来了------->那么如何创建存在一对多或多对多关系的一本书的信息呢?(如何处理外键关系的字段如一对多的publisher和
多对多的authors)
#一对多(ForeignKey): #方式一: 由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
# 字段设定对应值:
Book.objects.create(title='php',
publisher_id=, #这里的2是指为该book对象绑定了Publisher表中id=2的行对象
publication_date='2017-7-7',
price=) #方式二:
# <> 先获取要绑定的Publisher对象:
pub_obj=Publisher(name='河大出版社',address='保定',city='保定',
state_province='河北',country='China',website='http://www.hbu.com')
OR pub_obj=Publisher.objects.get(id=) # <>将 publisher_id= 改为 publisher=pub_obj #多对多(ManyToManyField()): author1=Author.objects.get(id=)
author2=Author.objects.filter(name='alvin')[]
book=Book.objects.get(id=)
book.authors.add(author1,author2)
#等同于:
book.authors.add(*[author1,author2])
book.authors.remove(*[author1,author2])
#-------------------
book=models.Book.objects.filter(id__gt=)
authors=models.Author.objects.filter(id=)[]
authors.book_set.add(*book)
authors.book_set.remove(*book)
#-------------------
book.authors.add()
book.authors.remove()
authors.book_set.add()
authors.book_set.remove() #注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
# 如果第三张表是自己创建的:
class Book2Author(models.Model):
author=models.ForeignKey("Author")
Book= models.ForeignKey("Book")
# 那么就还有一种方式:
author_obj=models.Author.objects.filter(id=)[]
book_obj =models.Book.objects.filter(id=)[] s=models.Book2Author.objects.create(author_id=,Book_id=)
s.save()
s=models.Book2Author(author=author_obj,Book_id=)
s.save()
5 ORM之删(delete)
>>> Book.objects.filter(id=1).delete() 固定搭配
(3, {'app01.Book_authors': 2, 'app01.Book': 1})
我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除
6 ORM之改(update和save)
注意
<1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。
<2>模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。
#---------------- update方法直接设定对应属性----------------
models.Book.objects.filter(id=3).update(title="PHP")
##sql:
##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3) #--------------- save方法会将所有属性重新设定一遍,效率低-----------
obj=models.Book.objects.filter(id=3)[0]
obj.title="Python"
obj.save()
# SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price",
# "app01_book"."color", "app01_book"."page_num",
# "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1;
#
# UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556,
# "publisher_id" = 1 WHERE "app01_book"."id" = 3;
此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
7 ORM之查
查询API
# 查询相关API: # <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 # <2>all(): 查询所有结果 # <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()-------- # <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 # <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 # <6>order_by(*field): 对查询结果排序 # <7>reverse(): 对查询结果反向排序 # <8>distinct(): 从返回结果中剔除重复纪录 # <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 # <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。 # <11>first(): 返回第一条记录 # <12>last(): 返回最后一条记录 # <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False
注意
---------------了不起的双下划线(__)之单表条件查询---------------- # models.Tb1.objects.filter(id__lt=, id__gt=) # 获取id大于1 且 小于10的值
#
# models.Tb1.objects.filter(id__in=[, , ]) # 获取id等于11、、33的数据
# models.Tb1.objects.exclude(id__in=[, , ]) # not in
#
# models.Tb1.objects.filter(name__contains="ven")
# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
# models.Tb1.objects.filter(id__range=[, ]) # 范围bettwen and
#
# startswith,istartswith, endswith, iendswith,c
pbkdf2_sha256$24000$hqsR2nOYiOFz$d59H8mBPEl58Qzfh4KTn4Z+ZOjE3WkkBFY1b7rHVpXE=
第三篇数据库与ORM的更多相关文章
- javaweb回顾第三篇数据库访问
前言:本篇主要针对数据库的操作,在这里不适用hibernate或者mybatis,用最原始的JDBC进行讲解,通过了解这些原理以后更容易理解和学习hibernate或mybatis. 1:jdbc的简 ...
- python【第十二篇下】操作MySQL数据库以及ORM之 sqlalchemy
内容一览: 1.Python操作MySQL数据库 2.ORM sqlalchemy学习 1.Python操作MySQL数据库 2. ORM sqlachemy 2.1 ORM简介 对象关系映射(英语: ...
- Django进阶Model篇—数据库操作(ORM)
一.数据库配置 django 默认支持sqlite.mysql.oracle.postgresql数据库,像db2和sqlserver之类的数据库需要第三方的支持,具体详见https://docs.d ...
- TDSQL|三篇论文入选国际顶会SIGMOD,厉害了腾讯云数据库
好消息!6月13日,腾讯云数据库三篇论文再次入选数据库行业顶会SIGMOD,被SIGMOD 2022 Research Full Paper(研究类长文)收录. 本次被收录的研究成果中,新型数据结构设 ...
- 三种数据库访问——Spring3.2 + Hibernate4.2
前三篇随笔中介绍了 用原生的JDBC访问数据库.一种高效的数据库连接池druid.用Spring的JDBC框架访问数据库. 本文继续介绍第三种数据库访问的解决方案:Spring3.2 + Hibern ...
- 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://w ...
- (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...
- 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 第三篇 Entity Framework Plus 之 Query Cache
离上一篇博客,快一周,工作太忙,只能利用休息日来写一些跟大家分享,Entity Framework Plus 组件系列文章,之前已经写过两篇 第一篇 Entity Framework Plus 之 A ...
随机推荐
- HTML有2种路径的写法:绝对路径和相对路径
HTML有2种路径的写法:绝对路径和相对路径 2016年11月30日 17:51:20 Bolon0708 阅读数 21775 版权声明:本文为博主原创文章,未经博主允许不得转载. https:/ ...
- element ui表格表头顺序错乱的问题
因为在项目中两个表格共用了同一个组件, 但由于表头不完全相同, 就通过v-if来控制表头的显示隐藏,没想到造成了表头顺序的错乱, 经过多方查找资料,最后找到了解决方法: 即为每一列el-table-c ...
- [Codeforces #608 div2]1271D Portals
Description You play a strategic video game (yeah, we ran out of good problem legends). In this game ...
- CH12 动态内存
动态分配的对象的生命期与它们在哪里创建的五官,只有显示地释放时,这些对象才被销毁 静态内存用来保存局部static对象.类static数据成员以及定义在任何函数之外的变量,栈内存用来保存定义在函数内的 ...
- SPringBootJPA的使用快速开发
一文搞懂如何在 Spring Boot 中正确使用 JPA JPA 这部分内容上手很容易,但是涉及到的东西还是挺多的,网上大部分关于 JPA 的资料都不是特别齐全,大部分用的版本也是比较落后的.另外, ...
- BugFix系列---开篇介绍
这个系列的文章,主要目的在于积累总结实际开发中遇到的错误,记录下来自己的解决思路,用来提升自己. 不出意外,应该会持续不断的记录更新,在整个开发openstack的过程中,抓住机会吸取开源界大牛的 ...
- VM ubuntu18.04.01虚拟机没办法联网
sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service ...
- Jmeter测试入门——分析HBase访问服务性能瓶颈
开启HBase服务 新建线程组,设定线程数为10: 设定请求方法和请求参数: 查看请求的返回结果: 查看服务响应的性能分析结果: 可能出问题的地方:Phoenix.数据库连接池(操作Phoenix)
- vue :is 属性
为什么使用 :is ?DOM模板解析说明: 当使用DOM作为模板时(例如,将el选项挂载到一个已知的元素上),你会受到HTML的一些限制,因为Vue只有在浏览器解析和标准化HTML后才能获取模板内容. ...
- spring core:@AliasFor的派生性
spring对Annotation的派生性应用可谓炉火纯青,在spring core:@Component的派生性讲过支持层次上派生性,而属性上派生的需求则借助了@AliasFor,它是从spring ...