一、ORM简介

ORM ,全称Object Relational Mapping,中文叫做对象关系映射,通过ORM我们可以通过类的方式去操作数据库,而不用再写原生的SQL语句。通过把表映射成类,把行作为实例,把字段作为属性,ORM在执行对象操作的时候最终还是会把对应的操作转换为数据库原生语句。

ORM 模型一般都是放在app的models.py文件中。每个app都可以拥有自己的模型,并且如果这个模型想要映射到数据库中,那么这个 app 必须要放在项目的settings.py文件的INSTALLED_APP 中进行安装。

二、ORM创建示例

1.创建一个项目base_orm_operation,再在这个项目中创建一个book的app,并将book放在项目的settings.py文件的INSTALLED_APP 中。

2.编写book app的models.py文件,字段类型先不用过多关注,后续再学习。

from django.db import models
class Book(models.Model):#以下四行,相当于定义了一个包含4个字段的表,字段名称分别为id、name、author和price
id=models.AutoField(primary_key=True)#int类型,主键,自增长,即使不写系统也会自动生成这样一个字段
name=models.CharField(max_length=100,null=False)#图书名称,varchar(100),不为空
author=models.CharField(max_length=100,null=False)#图书作者,varchar(100),不为空
price=models.FloatField(null=False,default=0)#图书价格,float,默认为为0
def __str__(self):#自定义返回结果样式
return '%s,%s,%s'%(self.name,self.author,self.price)
class Publisher(models.Model):
name=models.CharField(max_length=100,null=False)
address=models.CharField(max_length=100,null=False)

创建Book和Publisher模型

如果要自定义表名,需要在模型定义的时候添加。

class Book(models.Model)
……
class Meta:
db_table='book' #定义数据库存放的表名
verbose_name_plural = '书籍表' #定义django admin显示的表名

3.通过cmd窗口进入项目所在路径,使用makemigrations生成迁移脚本文件,python manage.py makemigrations。注意此时settings.py的中间件没有注释'django.middleware.csrf.CsrfViewMiddleware',否则会报加密需要csrf错误。

执行后会在app的migrations目录下生成一个0001_initial.py文件,文件内容如下,这个可以不用关注,这个是django内部处理的

# Generated by Django 2.1.4 on 2018-12-20 06:38
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name='Book',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=100)),
('author', models.CharField(max_length=100)),
('price', models.FloatField(default=0)),
],
),
migrations.CreateModel(
name='Publisher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('address', models.CharField(max_length=100)),
],
),
]

migrations目录下0001_initial.py文件

4.使用migrate将新生成的迁移脚本文件映射到数据库中,python manage.py migrate

由于是第一次执行migrate,django会将settings.py中已经安装的app模型映射到数据库中。

5.查看生成结果,在navicat的orm_intro数据库的表上右键-刷新,可看到生成了很多表。

由于在创建模型的时候没有指定表的名称,系统默认以app名称_类名称的小写  命名表,即新生成的表名为book_book,表结构如下

       

三、通过ORM操作数据库

在urls.py文件中添加映射路径

from book import views
urlpatterns = [path('', views.index),]

1.增加记录:save方法和create()方法

from .models import Book
from django.http import HttpResponse
def index(request):
book = Book(name='西游记',author='吴承恩',price=100)
book.save()
#book.objects.create(name='红楼梦',author='曹雪芹',price=56) 通过模型的objects的create方法生成记录,这种方法不需要再save
return HttpResponse("图书添加成功!")

在浏览器中输入http://127.0.0.1:8000/,显示“图书添加成功”,返回navicat刷新book_book表,可看到已经成功添加上一条数据。

可按照这个方法将四大名著的记录都添加进去,添加后如下

2.查询记录:所有的查询都是通过模型上的objects属性来完成的,也可以自定义查询对象。

①如果查询结果只有一条记录(即通过主键或者unique索引查询),可使用objects.get(attr=value),返回结果是一个model对象<class 'app01.models.book'>,并且只支持严格匹配。

book = Book.objects.get(pk=2)
print(book)
return HttpResponse('主键查询图书成功')

在浏览器中输入http://127.0.0.1:8000/,显示“主键查询图书成功”,并且pycharm工具显示如下

②返回一条或多条记录可使用objects.filter(attr=value),结果是一个queryset集合<class 'django.db.models.query.QuerySet'>,集合中的每一个对象为model对象,可支持关键字例如in、like查询。

book1=Book.objects.filter(author='曹雪芹')
book2=Book.objects.filter(name='西游记').first()
print(book1)
print(book2)
return HttpResponse('条件查询图书成功')

在浏览器中输入http://127.0.0.1:8000/,显示“主键查询图书成功”,并且pycharm工具显示如下

filter查询得到的结果是一个查询集合,即使匹配到的只有一个结果也会以集合形式显示,而first()得到的只是集合中的一个结果

③其他常用查询套件

book3=Book.objects.all() 查询所有记录

book4=Book.objects.first() 查询第一条记录

book5=Book.objects.last() 查询最后一套记录

book6=Book.objects.all()[1:3] 查询索引下标为1至2的记录

book7=Book.objects.all().values('name','price')  取values指定的列,结果显示为字典,<QuerySet [{'name': '三国演义', 'price': 52}, {'name': '水浒传', 'price': 38}···]>

book8=Book.objects.all().values_list('name','price')  取values指定的列,结果显示为列表,<QuerySet [('三国演义', 52), ('水浒传', 38)···]>

通过filter和all取出来的结果可通过for进行循环迭代

查询记录总结:

①通过objects.filter()和objects.all() 得到的结果为QuerySet,QuerySet中的每一个值为模型对象

②通过objects.get()、Book.objects.first()、objects.last() 得到的结果为模型对象

③通过①取出再进行values()或values_list(),得到的结果为QuerySet,但QuerySet中的每一个值为字典或元组

3.修改记录

①通过对象.属性修改再调用对象.save()方法、或者QuerySet的update方法进行修改

#使用get查询的结果为模型对象,必须通过对象.属性来更新,不能使用update方法,否则会报错AttributeError: 'book' object has no attribute 'update'
book = Book.objects.get(pk=2)
book.price=45
book.save()
print(book)
return HttpResponse('图书修改成功') #使用filter查询的结果为QuerySet,必须通过update来更新,不能使用对象.属性,否则无法更新成功,并且QuerySet没有save()方法
#update语句的返回值为受影响的行数
Book.objects.filter(name='西游记').update(price=100)

在浏览器中输入http://127.0.0.1:8000/,显示“图书修改成功”,并且pycharm工具显示如下

②两种修改方法的区别

通过对象.属性修改再调用对象.save()方法,会对查询记录的每一个字段重新赋值,而使用update方法只会修改指定的列

如果需要查看通过ORM操作模型对象的语句转换成的数据库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',
},
}
}

将模型操作转化为数据库sql

添加上述部分后,可在pycharm的下方输出查看到如下内容,上面一条为使用对象.save()方法进行的修改,下面一条为使用update方法进行的修改

#UPDATE `app_book` SET `name` = '红楼梦', `price` = 1, `publishdate` = '2011-12-05', `author` = '曹雪芹' WHERE `app_book`.`id` = 7; args=('红楼梦', 1, '2011-12-05', '曹雪芹', 7)
#UPDATE `app_book` SET `price` = 100 WHERE `app_book`.`id` = 7; args=(100, 7)

4.删除记录delete,删除之前也需要先查询,再删除

book=Book.objects.get(pk=2)#或者book=Book.objects.filter(pk=2)
book.delete()
return HttpResponse('删除图书成功,请检查表中是否还有该记录')

在浏览器中输入http://127.0.0.1:8000/,显示“删除图书成功,请检查表中是否还有该记录”,到navicat中刷新表,可看到上述记录已经删除。

四、ORM常用字段类型

AutoField(Field)
- int自增列,必须填入参数 primary_key=True BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True 注:如果model中没有自增列,模型会自动创建一个列名为id的自增列;也可以自定义自增列。 SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767 IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647 BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field)
- 布尔值类型 NullBooleanField(Field):
- 可以为空的布尔值 CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度 TextField(Field)
- 文本类型 EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字 UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹 FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field)
- 浮点型 DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度 BinaryField(Field)
- 二进制类型

ORM字段

null                数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键。加速查找,列值唯一,且不为空
unique 数据库中字段是否可以建立唯一索引。加速查找,列值唯一
db_index 数据库中字段是否可以建立索引。加速查找
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)

ORM字段的参数

在定义字段类型时,如果没有设置null=True,默认为null=False,即默认字段不为空

AutoField:必须输入参数primary_key=True,数据库层面为int 类型,自增长,如果不指定主键,模型会自动生成一个叫做 id 的自增长的主键。如果需要指定一个其他名字并且自增长的主键,也可以使用AutoField。

BigAutoField:类似AutoField,数据范围更大

BooleanField字段:模型层面值为True或False(数据库层面值为1或0,类型tinyint),并且不接受null=True,即该字段不能为空

NullBooleanField字段:值为True或False,但可以为空

CharField:模型层面为字符串,数据库层面为varchar,使用时必须指定max_length=n,如果n超过254不建议使用,以TextField代替

TextField:文本类型,数据库层面是longtext

EmailField:数据库层面为varchar,默认最大长度为254个字节,在数据库层面并不会限制字符串一定要满足邮箱格式,只是以后在使用ModelForm等表单相关操作的时候会验证邮箱格式

IntegerField:整型,值的区间是 -2147483648—2147483647 。

FloatField:浮点类型

BigIntegerField:大整型,值的区间是 -9223372036854775808—9223372036854775807

PositiveIntegerField:正整型,值的区间是 0——2147483647 。

SmallIntegerField:小整型,值的区间是 -32768——32767 。

正小整型,值的区间是 0——32767

UUIDField:只能存储 uuid 格式的字符串。 uuid 是一个32位的全球唯一的字符串,一般用来作为主键,使用ModelForm等表单相关操作的时候会验证

URLField:类似于 CharField ,只不过只能用来存储 url 格式的字符串。并且默认的 max_length 是200,使用ModelForm等表单相关操作的时候会验证是否是URL格式

更多字段及ORM操作参见http://www.cnblogs.com/wupeiqi/articles/6216618.html

status_choices = ( (1,'未处理'),(2,'处理中'),(3,'已处理') )
status = models.IntegerField(choices=status_choices,default=1),对于一条记录来说,这个字段存储的值是1、2或3

在模板页面,Model.status显示的是数据库中的数字,可通过Model.get_status_display来显示数字对应的文字。

django创建ORM模型、通过ORM模型操作单个表、ORM模型常用字段的更多相关文章

  1. Django创建并连接数据库(实现增删改查)--ORM框架雏形

    第一步:要先创建数据库(orm是不能创建数据库的) 第二步:settings里面指定连接到哪个数据库 DATABASES = { #默认使用的是sqlite3数据库 'default': { 'ENG ...

  2. django模型:为已存在的表建立模型

    为已经存在的表建立模型:参考https://blog.csdn.net/opera95/article/details/78200024 为已经存在的表建立模型1.python manage.py i ...

  3. SQL Server并发操作单个表时发生在page页面级的死锁

    最近遇到的死锁问题都发生在并发操作单张表上,比较有意思,就模拟了重现了一下.根据非聚集索引为条件,删除某一个表的数据,类似于这么一个语句,delete from table where noclust ...

  4. Mysql查询的一些操作(查表名,查字段名,查当月,查一周,查当天)

    查询数据库中所有表名 select table_name from information_schema.tables where table_schema='tools' and table_typ ...

  5. Django模型层之更多操作

    Django模型层之更多操作 一 .ORM字段 1.1 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为 ...

  6. Django框架之ORM常用字段

    一.ORM介绍 1.ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过 ...

  7. tornado 06 数据库—ORM—SQLAlchemy——基本内容及操作

    tornado 06 数据库—ORM—SQLAlchemy——基本内容及操作 一. ORM #在服务器后台,数据是要储存在数据库的,但是如果项目在开发和部署的时候,是使用的不同的数据库,该怎么办?是不 ...

  8. 06 ORM常用字段 关系字段 数据库优化查询

    一.Django ORM 常用字段和参数 1.常用字段 models中所有的字段类型其实本质就那几种,整形varchar什么的,都没有实际的约束作用,虽然在models中没有任何限制作用,但是还是要分 ...

  9. 对Jscript操作注册表接口的一点不解

    作者:朱金灿 来源:http://blog.csdn.net/clever101 要操作注册表需要通过ActiveX控件调用WScript.shell对象,通过该对象的一些方法来操作.Wshshell ...

随机推荐

  1. np.Linear algebra学习

    转自:https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.linalg.html 1.分解 //其中我觉得可以的就是svd奇异值分解吧 ...

  2. 强制SVN上传代码时添加日志

    因SVN不能像Git一样,审核代码之后才合入到主版本.为了使开发人员养成良好的上传习惯,强制要求上付时必须写明上传内容. 可以通过以下方法设置 1,在SVN服务器上找到源码仓库路径,找到下面文件夹:C ...

  3. nginx反向代理 支持WebSocket

    WebSocket(简称WS)协议的握手和HTTP是兼容的,通过HTTP/1.1中协议转换机制,客户端可以传递名为“Upgrade” 头部信息将连接从HTTP连接升级到WebSocket连接 那么反向 ...

  4. js监听页面放大缩小

    <!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>d ...

  5. 多么痛的领悟---关于RMB数据类型导致的元转分分转元的bug

    关于金额的数据类型,以及元转分分转元之间这种转换,以及元和分的比较,我相信很多人都踩过坑. 反正我是踩过. 而且,昨天和今天又重重的踩了两脚. 代付查询接口,支付中心给溢+响应的报文里,amount的 ...

  6. 读写App.config配置文件的方法

    我们经常会希望在程序中写入一些配置信息,例如版本号,以及数据库的连接字符串等.你可能知道在WinForm应用程序中可以利用Properties.Settings来进行类似的工作,但这些其实都利用了Ap ...

  7. jdbc连接oracle的几种格式

    1. SID的方式.已经不推荐使用这种方式了. jdbc:oracle:thin:[<user>/<password>]@<host>[:<port>] ...

  8. 假如java类里的成员变量是自身的对象

    假如java类里的成员变量是自身的对象,则新建该类对象时内存中怎么分配空间,我感觉似乎死循环了. 不过我想的肯定是错的,因为很多类的成员变量是自身对象,并且绝对无错,举个例子: Class A{ pr ...

  9. 强化学习--Actor-Critic---tensorflow实现

    完整代码:https://github.com/zle1992/Reinforcement_Learning_Game Policy Gradient  可以直接预测出动作,也可以预测连续动作,但是无 ...

  10. Attention Is All You Need 一些好的资料

    The encoders are all identical in structure (yet they do not share weights). Each one is broken down ...