ORM 概念
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。 ORM在业务逻辑层和数据库层之间充当了桥梁的作用。
ORM 与 DB 的对应关系
ORM 面向对象和关系型数据库的一种映射,通过操作对象的方式操作数据库数据,不支持对库的操作,只能操作表 对应关系: 类 --> 表 对象 --> 数据行 属性 --> 字段
Model 模块 在Django中model是你数据的单一、明确的信息来源。它包含了你存储的数据的重要字段和行为。通常, 一个模型(model)映射到一个数据库表。
基本情况:
每个模型都是一个Python类,它是django.db.models.Model的子类。 模型的每个属性都代表一个数据库字段。 综上所述,Django为您提供了一个自动生成的数据库访问API,详询官方文档
一、数据库环境搭建
1、mysql中新建一个数据库
sql语法:
CREATE DATABASE [IF NOT EXISTS] <数据库名>
[[DEFAULT] CHARACTER SET <字符集名>]
[[DEFAULT] COLLATE <校对规则名>];
或者推荐用Navicat直接创建,视图化,简单粗暴。
2、安装mysqlclient
打开cmd命令行
pip install mysqlclient
pass:有的同学安装可能会失败,请参考我的另一篇文章:mysqlclient安装失败如何解决
3、打开django的seeting设置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'root', # 数据库用户密码
'NAME': 'test' # 数据库名字
}
}
4、检查是否配置成功
pycharm terminal中执行
python manage.py dbshell
可进入mysql虚拟中断,表示配置成功
二、ORM表模型
1、在jango中,所有的模型必须继承
from django.db.models import Model
这个类,字段类型需要使用models模块中定义好的字段类型。
#案例说明
from django.db import models
# Create your models here.
class PhoneField(models.Field): # 自定义的char类型的字段类
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(PhoneField, self).__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection): # 限定生成数据库表的字段类型为char,长度为max_length指定的值的字符串
return 'char(%s)' % self.max_length
class Student(models.Model):
s_name = models.CharField(max_length=64,help_text="学生姓名")
s_sex = models.IntegerField(choices=((0,'男'),(1,'女')), help_text="性别")
s_phone = PhoneField(max_length=11,help_text="手机号")
# auto_now_add=True 在每一次数据被添加进去的时候,记录当前时间
create_time = models.DateTimeField(auto_now_add=True)
# auto_now=True 在每一次数据被保存的时候,记录当前时间
update_time = models.DateTimeField(auto_now=True)
class Meta:
db_table='student' # 指定表名
2、模型中常用属性
字段 | 描述 | 示例 |
---|---|---|
AutoField | int自增列,必须填入参数 primary_key=True | id=models.AutoField(primary_key=True) |
BigAutoField | bigint自增列,必须填入参数 primary_key=True | id=models.BigAutoField(AutoField) |
BinaryField | 二进制类型 | |
BooleanField | 数据库存为True–> 1 False–> 0 | |
CharField | 字符类型,必须提供max_length参数。max_length表示字符的长度 | name = models.CharField(max_length=32) |
DateField | date | |
DateTimeField | 日期时间 | birth = models.DateTimeField(auto_now_add=True) |
DecimalField | 十进制的小数 | money= models.DecimalField(max_digits=15,decimal_places=3) |
DurationField | 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 | |
FloatField | 浮点型 | |
IntegerField | 一个整数类型。数值的范围是 -2147483648 ~ 2147483647。 | age = models.IntegerField() |
BigIntegerField | 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 | |
IPAddressField | char(15) | |
NullBooleanField | 可以为空的布尔值 | |
OneToOneField | integer | |
PositiveIntegerField | 正整数 0 ~ 2147483647 | |
PositiveSmallIntegerField | 正小整数 0 ~ 32767 | |
SmallAutoField | smallint AUTO_INCREMENT | |
SmallIntegerField | 小整数 -32768 ~ 32767 | |
TextField | 比较长的字符串 | |
TimeField | 时间格式 HH:MM[:ss[.uuuuuu]] |
3、django提供的一些特殊属性
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
- e_mail = models.EmailField(max_length=255, unique=True)
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 上传图片的宽度保存的数据库字段名(字符串)
4、自定义字段
示例:我们发现上边没有固定长度的字符串类型,但是手机号字段一般都是定长11位的字符串,所以我们需要自定义一些字段类型
from django.db import models
class PhoneField(models.Field): # 自定义的char类型的字段类
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(PhoneField, self).__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection): # 限定生成数据库表的字段类型为char,长度为max_length指定的值的字符串
return 'char(%s)' % self.max_length
5、Field的常用参数:
参数 | 含义 |
---|---|
null | 数据库中字段是否可以为空#注意 数据库的null 和’'空字符是两种情况 |
db_column | 数据库中字段的列名 |
default | 数据库中字段的默认值 |
primary_key | 数据库中字段是否为主键 |
db_index | 数据库中字段是否可以建立索引 |
unique | 数据库中字段是否可以建立唯一索引 |
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 | 自定义错误验证(列表类型),从而定制想要的验证规则 |
6、模型中Meta配置:
对于一些模型级别的配置。我们可以在模型中定义一个类,叫做Meta。然后在这个类中添加一些类属性来控制模型的作用。比如我们想要在数据库映射的时候使用自己指定的表名,而不是使用模型的名称。那么我们可以在Meta类中添加一个db_table的属性。示例代码如下:
class Book(models.Model):
name = models.CharField(max_length=20,null=False)
desc = models.CharField(max_length=100,name='description',db_column="description1")
class Meta:
db_table = 'book_model'
以下将对Meta类中的一些常用配置进行解释。
元类信息 | 含义 |
---|---|
db_table | # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 |
verbose_name | admin中显示的表名称 |
verbose_name_plural | 所有用户信息 |
index_together | 联合索引 |
unique_together | 联合唯一索引 |
6、外键和表关系
外键:
在MySQL中,表有两种引擎,一种是InnoDB,另外一种是myisam。如果使用的是InnoDB引擎,是支持外键约束的。外键的存在使得ORM框架在处理表关系的时候异常的强大。因此这里我们首先来介绍下外键在Django中的使用。
类定义为class ForeignKey(to,on_delete,**options)。第一个参数是引用的是哪个模型,第二个参数是在使用外键引用的模型数据被删除了,这个字段该如何处理,比如有CASCADE、SET_NULL等。这里以一个实际案例来说明。比如有一个User和一个Article两个模型。一个User可以发表多篇文章,一个Article只能有一个Author,并且通过外键进行引用。那么相关的示例代码如下:
class User(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey("User",on_delete=models.CASCADE)
以上使用ForeignKey来定义模型之间的关系。即在article的实例中可以通过author属性来操作对应的User模型。这样使用起来非常的方便。示例代码如下:
article = Article(title='abc',content='123')
author = User(username='张三',password='111111')
article.author = author
article.save()
# 修改article.author上的值
article.author.username = '李四'
article.save()
为什么使用了ForeignKey后,就能通过author访问到对应的user对象呢。因此在底层,Django为Article表添加了一个属性名_id的字段(比如author的字段名称是author_id),这个字段是一个外键,记录着对应的作者的主键。以后通过article.author访问的时候,实际上是先通过author_id找到对应的数据,然后再提取User表中的这条数据,形成一个模型。
如果想要引用另外一个app的模型,那么应该在传递to参数的时候,使用app.model_name进行指定。以上例为例,如果User和Article不是在同一个app中,那么在引用的时候的示例代码如下:
# User模型在user这个app中
class User(models<