Django-ORM
Object Relational Mapping,对象关系映射,为了解决面向对象与关系数据库存在的互不匹配的技术。
ORM的优势
ORM解决的主要问题是对象和关系的映射。它通常将一个类和一张表一一对应,类的每个实例对应表中的一条记录,类的每个属性对应表中的每个字段。
ORM提供了对数据库的映射,不用直接编写SQL代码,只需操作对象就能对数据库操作数据。
让软件开发人员专注于业务逻辑的处理,提高了开发效率。
ORM的劣势
ORM的缺点是会在一定程度上牺牲程序的执行效率。
ORM的操作是有限的,也就是ORM定义好的操作是可以完成的,一些复杂的查询操作是完成不了。
ORM用多了SQL语句就不会写了,关系数据库相关技能退化...
使用mysql数据库的流程
-
创建一个mysql数据库;
-
在settings.py中配置数据库:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 引擎 'NAME': '数据库名', # 数据库名称 'HOST': 'IP地址', # IP 'PORT': 3306, # 端口号 'USER': '用户名', # 用户名 'PASSWORD': '密码' # 密码 } }
-
使用pymysql模块连接mysql数据库。
写在与settings同级目录下的
__init__.py
中import pymysql pymysql.install_as_MySQLdb()
-
写对应关系,在app下的models.py中写类,定义数据表。
class User(models.Model): username = models.CharField(max_length=32) # username varchar(32) password = models.CharField(max_length=32) # password varchar(32)
-
执行数据库迁移的命令
python36 manage.py makemigrations # 记录下models.py的变更记录 python manage.py migrate # 变更记录同步到数据库
-
所有要实现的功能放在views.py中,如果要用数据库,应该将数据库的models导入到该文件
from django.shortcuts import render,redirect from app01 import models def login(request): if request.method == 'GET': return render(request,'login.html') elif request.method == "POST": # 获取提交数据 user = request.POST.get("username") pwd = request.POST.get("password") # ret = models.inf.objects.get(username=user,password=pwd) # get方法有一个特点是查不到数据或者查到多个数据时,会报错 ret = models.inf.objects.filter(username=user,password=pwd) if ret: return redirect("/home/") else: return render(request,'login.html') def home(request): return render(request,'home.html')
注意
进行查询操作时
ret = models.User.objects.get(username=user, ) # 找不到就报错 找到多个也报错 ret = models.User.objects.filter(username=user, ) # 过滤筛选,获取满足条件的所有的对象,存放在列表中
常用数据类型
常用字段
AutoField
自增的整形字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django自动创建。
一个model不能有两个AutoField字段。
IntegerField
一个整数类型。数值的范围是 -2147483648 ~ 2147483647。
CharField
字符类型,必须提供max_length参数。max_length表示字符的长度。
DateField
日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例。
参数:
-
auto_now:每次修改时修改为当前日期时间。
-
auto_now_add:新创建对象时自动添加当前日期时间。
auto_now和auto_now_add和default参数是互斥的,不能同时设置。
DatetimeField
日期时间字段,格式为YYYY-MM-DD HH:MM:ss[.uuuuuu],相当于Python中的datetime.datetime的实例。
TextField
大字符串类型,文本类型
BooleanField
布尔值类型
DecimalField
十进制小数,其中:
-
max_digists设置小数的总长度
-
decimal_places设置的是小数位的长度
常用字段参数
-
null = True 数据库的该字段可以为空
-
blank = True admin校验时允许输入为空
-
default 设置默认值
-
unique 唯一索引
-
verbose_name admin中显示字段名称
-
choices = ((True,'男'),(False,'女')) Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
表的参数Model Meta
class Person(models.Model): pid = models.AutoField(primary_key=True) # 主键 name = models.CharField(max_length=32, db_column='username', unique=True, verbose_name='姓名', help_text='填写有效姓名') # varchar(32) age = models.IntegerField(null=True, blank=True) birth = models.DateTimeField(auto_now=True) phone = MyCharField(max_length=11, null=True, blank=True) gender = models.BooleanField(default=True, choices=((True, '男'), (False, '女'))) class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 db_table = "person" # admin中显示的表名称 verbose_name = '个人信息' # verbose_name加s verbose_name_plural = '所有用户信息' # 联合索引 index_together = [ ("name", "age"), # 应为两个存在的字段 ] # 联合唯一索引 unique_together = (("name", "age"),) # 应为两个存在的字段
admin
-
创建一个超级用户
python36 manage.py createsuperuser 根据提示输入用户名和密码 Username (leave blank to use 'aries'): Email address: Password: Password (again): 其中密码要求长度至少是8位的字母数字组合
-
注册
在app下的admin.py中进行注册
from django.contrib import admin from app01 import models admin.site.register(models.表名)
-
找到对应的表做增删改查
字段与参数汇总
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 AutoField(Field) 2 - int自增列,必须填入参数 primary_key=True 3 4 BigAutoField(AutoField) 5 - bigint自增列,必须填入参数 primary_key=True 6 7 注:当model中如果没有自增列,则自动会创建一个列名为id的列 8 【举例】 9 from django.db import models 10 11 class UserInfo(models.Model): 12 # 自动创建一个列名为id的且为自增的整数列 13 username = models.CharField(max_length=32) 14 15 class Group(models.Model): 16 # 自定义自增列 17 nid = models.AutoField(primary_key=True) 18 name = models.CharField(max_length=32) 19 20 SmallIntegerField(IntegerField): 21 - 小整数 -32768 ~ 32767 22 23 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 24 - 正小整数 0 ~ 32767 25 26 IntegerField(Field) 27 - 整数列(有符号的) -2147483648 ~ 2147483647 28 29 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 30 - 正整数 0 ~ 2147483647 31 32 BigIntegerField(IntegerField): 33 - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 34 35 BooleanField(Field) 36 - 布尔值类型 37 38 NullBooleanField(Field): 39 - 可以为空的布尔值 40 41 CharField(Field) 42 - 字符类型 43 - 必须提供max_length参数, max_length表示字符长度 44 45 TextField(Field) 46 - 文本类型 47 48 EmailField(CharField): 49 - 字符串类型,Django Admin以及ModelForm中提供验证机制 50 51 IPAddressField(Field) 52 - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 53 54 GenericIPAddressField(Field) 55 - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 56 - 参数: 57 protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 58 unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" 59 60 URLField(CharField) 61 - 字符串类型,Django Admin以及ModelForm中提供验证 URL 62 63 SlugField(CharField) 64 - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) 65 66 CommaSeparatedIntegerField(CharField) 67 - 字符串类型,格式必须为逗号分割的数字 68 69 UUIDField(Field) 70 - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 71 72 FilePathField(Field) 73 - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 74 - 参数: 75 path, 文件夹路径 76 match=None, 正则匹配 77 recursive=False, 递归下面的文件夹 78 allow_files=True, 允许文件 79 allow_folders=False, 允许文件夹 80 81 FileField(Field) 82 - 字符串,路径保存在数据库,文件上传到指定目录 83 - 参数: 84 upload_to = "" 上传文件的保存路径 85 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 86 87 ImageField(FileField) 88 - 字符串,路径保存在数据库,文件上传到指定目录 89 - 参数: 90 upload_to = "" 上传文件的保存路径 91 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 92 width_field=None, 上传图片的高度保存的数据库字段名(字符串) 93 height_field=None 上传图片的宽度保存的数据库字段名(字符串) 94 95 DateTimeField(DateField) 96 - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 97 98 DateField(DateTimeCheckMixin, Field) 99 - 日期格式 YYYY-MM-DD 100 101 TimeField(DateTimeCheckMixin, Field) 102 - 时间格式 HH:MM[:ss[.uuuuuu]] 103 104 DurationField(Field) 105 - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 106 107 FloatField(Field) 108 - 浮点型 109 110 DecimalField(Field) 111 - 10进制小数 112 - 参数: 113 max_digits,小数总长度 114 decimal_places,小数位长度 115 116 BinaryField(Field) 117 - 二进制类型 118 null 数据库中字段是否可以为空 119 db_column 数据库中字段的列名 120 default 数据库中字段的默认值 121 primary_key 数据库中字段是否为主键 122 db_index 数据库中字段是否可以建立索引 123 unique 数据库中字段是否可以建立唯一索引 124 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 125 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 126 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 127 128 verbose_name Admin中显示的字段名称 129 blank Admin中是否允许用户输入为空 130 editable Admin中是否可以编辑 131 help_text Admin中该字段的提示信息 132 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 133 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 134 135 error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 136 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 137 如:{'null': "不能为空.", 'invalid': '格式错误'} 138 139 validators 自定义错误验证(列表类型),从而定制想要的验证规则 140 from django.core.validators import RegexValidator 141 from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ 142 MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 143 如: 144 test = models.CharField( 145 max_length=32, 146 error_messages={ 147 'c1': '优先错信息1', 148 'c2': '优先错信息2', 149 'c3': '优先错信息3', 150 }, 151 validators=[ 152 RegexValidator(regex='root_\d+', message='错误了', code='c1'), 153 RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), 154 EmailValidator(message='又错误了', code='c3'), ] 155 )
ORM操作
常用操作
-
all() 查询所有结果
-
get(**kwargs) 返回与所给条件向匹配的对象,返回结果有且只有一个,如果满足条件的对象超过一个或者没有符合条件的对象就报错
-
filter(**kwargs) 返回一个包含了所有满足条件的对象的列表,可以为空
-
exclude(**kwargs) 返回一个包含了所有不满足条件的对象的列表
-
values(*field) 返回一个特殊的QuerySet,获取对象的字段和对应的值,是一个可迭代的字典列表;如果没有设置参数,则返回数据库每一行的字段以及对应的值;设置了参数,则返回每一行该字段以及对应的值
-
value_list(*field) 获取对象的字段的值;没有设置参数时,返回每一行的记录;设置参数时,则返回该字段所对应的值
-
order_by(*field) 对查询结果进行排序,可以设置多个参数,当遇到重复情况时从左至右依次生效
-
reverse() 对已排序的结果进行反向,要注意的前提一定是已经排过序的QuerySet对象
-
distinct() 从返回的结果中进行去重;还可以对带参数的values的结果进行去重
-
count() 对返回的对象进行计数
-
first() 返回查询结果的第一个元素,获取不到返回none
-
last() 返回查询结果的最后一个元素,获取不到返回none
-
exists() 判断查询结果是否包含数据,有就返回True,无则返回False
小总结
返回QuerySet对象的操作
all filter exclude values(获得的是以集合为元素的列表) values_list(获得的是以元组为元素的列表) order_by reverse distinct
返回对象
get first last
返回布尔值
exists
返回数字
count
【示例】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 3 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings") 4 import django 5 6 django.setup() 7 8 from app01 import models 9 10 # all 获取所有的数据 QuerySet 对象列表 11 ret = models.Person.objects.all() 12 13 # get 获取一个满足条件的数据 存在且唯一 对象 14 ret = models.Person.objects.get(pk=1) 15 16 # filter 获取所有满足条件的数据 QuerySet 对象列表 17 ret = models.Person.objects.filter(pk=100) 18 19 # exclude 获取所有不满足条件的数据 QuerySet 对象列表 20 ret = models.Person.objects.exclude(pk=100) 21 22 # order_by 按照字段进行排序 QuerySet 对象列表 默认升序 -降序 23 ret = models.Person.objects.all().order_by('age','-pid') 24 25 # reverse 对一个已经排序QuerySet进行翻转 倒叙 26 ret = models.Person.objects.all().order_by('age','-pid').reverse() 27 28 # values() 获取对象的字段名和字段值 没有参数 所有字段 QuerySet 29 # 有参数 获取指定字段 30 ret= models.Person.objects.all().values('pid','name') 31 32 # values_list() 获取对象的字段值 没有参数 所有字段 QuerySet 33 # 有参数 获取指定字段 34 ret= models.Person.objects.all().values_list('name','pid',) 35 36 # distinct 去重 37 ret = models.Person.objects.values('age').distinct() 38 39 # count() 计数 40 ret = models.Person.objects.all().count() 41 42 # first last 获取第一个或最后一个元素 获取不到就是none 43 ret = models.Person.objects.all().last() 44 45 # exists 判断数据是否存在 布尔值 46 ret = models.Person.objects.filter(pk=100).exists()
单表查询的双下划线条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ret = models.Person.objects.filter(pk__gt=1) # greater than 大于 2 ret = models.Person.objects.filter(pk__lt=5) # less than 小于 3 ret = models.Person.objects.filter(pk__gte=1) # greater than equal 大于等于 4 ret = models.Person.objects.filter(pk__lte=5) # less than equal 小于等于 5 6 ret = models.Person.objects.filter(pk__range=[1,5]) # 范围 1到5 7 8 ret = models.Person.objects.filter(pk__in=[1,5,7,9]) # 范围 9 10 ret = models.Person.objects.filter(name__contains='alex') # like 11 ret = models.Person.objects.filter(name__icontains='aLex') # like ignore 忽略大小写 12 13 ret = models.Person.objects.filter(name__startswith='a') # 以什么开头 14 ret = models.Person.objects.filter(name__istartswith='a') # 以什么开头 ignore 忽略大小写 15 16 ret = models.Person.objects.filter(name__endswith='x') # 以什么结尾 17 ret = models.Person.objects. filter(name__iendswith='a') # 以什么结尾 ignore 忽略大小写 18 19 ret = models.Person.objects.filter(birth__year='2020') # birth字段year是2020 20 ret = models.Person.objects.filter(birth__contains='2020-10')# birth字段含有2020-10的 21 22 ret = models.Person.objects.filter(age__isnull=False) # age不为空,这里的空指的是为Null的情况,不能判断''空字符串