一、ORM介绍
1.什么是ORM ? ORM 全拼Object-Relation Mapping.
中文意为 对象-关系映射.
在MVC/MVT设计模式中的Model模块中都包括ORM
2.ORM优势
(1)只需要面向对象编程, 不需要面向数据库编写代码.
对数据库的操作都转化成对类属性和方法的操作.
不用编写各种数据库的sql语句.
(2)实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
不在关注用的是mysql、oracle...等.
通过简单的配置就可以轻松更换数据库, 而不需要修改代码.
3.ORM劣势
相比较直接使用SQL语句操作数据库,有性能损失.
根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
4.ORM和数据库关系:
在Django中model是你数据的单一、明确的信息来源。它包含了你存储的数据的重要字段和行为。通常,一个模型(model)映射到一个数据库表.
基本情况:
每个模型都是一个Python类,它是django.db.models.Model的子类。
模型的每个属性都代表一个数据库字段。
综上所述,Django为您提供了一个自动生成的数据库访问API。
二、ORM用法
1.字段类型
属性名
- 不允许使用python的保留关键字
- 不允许使用mysql的保留关键字
- 不允许使用连续的下划线,因为Django的查询语法就是连续的下划线
字段类型 | 描述 | MySQL类型 |
AutoField | 自动增长的IntegerField, 不指定时Django会自动创建属性名为id的自动增长属性 | INT AUTO_INCREMENT |
BigAutoField | | |
Binary | 二进制 | |
BooleanField | 布尔字段,值为True或False | |
NullBooleanField | 支持Null、True、False三种值 | |
CharField(max_length=20) | 字符串,max_length表示最大字符个数 | VARCHAR(20) |
TextFiled | 大文本字段,一般超过4000个字符时使用 | LONGTEXT |
IntegerField | 整数
PositiveSmallIntegerField | 5个字节 | SmallInteger | 6个字节 | PositiveIntegerField | 10个字节 | IntegerField | 11个字节 | BigIntegerField | 20个字节 |
| INT |
DecimalField(max_digits=None, decimal_places=None) | 可以指定精度的十进制浮点数
- 参数max_digits表示总位数
- 参数decimal_places表示小数位数
| DECIMAL |
FloatField | 浮点数 | FLOAT |
DateField([auto_now=False, auto_now_add=False]) | 日期
- 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
- 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
- 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误
| DATE |
DurationField | int类型, python timedelta 实现 | |
DateTimeField | 日期时间,参数同DateField | DATETIME |
FileField | 上传文件字段,以二进制的形式 | |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 | |
Email | 邮箱 | |
URL | URL | |
GenericIPAddress | IP地址 | |
UUID | UUID | |
2.字段选项:
- null:如果为True,表示允许为空,默认值是False
- blank:如果为True,则该字段允许为空白,默认值是False
- 对比:null是数据库范畴的概念,blank是表单验证范畴的
- db_column:字段的名称,如果未指定,则使用属性的名称(只限于数据库表中的名字,操作数据库还是类属性的名字)
- db_index:若值为True, 则在表中会为此字段创建索引,默认值是False(为了优化查询速度 )
- default:默认值,这可以是值或可调用对象。如果可调用,则每次创建新对象时都会调用它。
- primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用
- unique:如果为True, 这个字段在表中必须有唯一值,这个值不能重复,默认值是False
- 关系型字段类型:关联表中使用
注意:Django会自动为表创建主键字段
如果使用选项设置某属性为主键字段后,Django不会再创建自动增长的主键字段
3.关系字段类型
- OneToOneField:一对一,将字段定义在任意一端中
- ForeignKey:一对多,将字段定义在多的一端中
- ManyToManyField:多对多,将字段定义在任意一端中
-
class Article(models.Model):
class A(models.Model):
oneToOne = models.OneToOneField(Article,related_name="one")
class B(models.Model):
foreign = models.ForeignKey(A,on_delete=models.CASCADE) # 级联删除
# foreign = models.ForeignKey(A,on_delete=models.PROTECT)
# foreign = models.ForeignKey(A,on_delete=models.SET_NULL,null=True,blank=True) # 删除置空
# foreign = models.ForeignKey(A,on_delete=models.SET_DEFAULT,default=0)
# foreign = models.ForeignKey(A,on_delete=models.DO_NOTHING)
# foreign = models.ForeignKey(A,on_delete=models.SET)
class C(models.Model):
manyToMany = models.ManyToManyField(B)
4. 元数据
class addressInfo(models.Model):
address = models.CharField(max_length=200,null=True,blank=True,verbose_name="地址")
pid = models.ForeignKey('self',null=True,blank=True,verbose_name="自关联")
note = models.CharField(max_length=200,null=True,blank=True,verbose_name="说明")
def __str__(self):
return self.address
class Meta:
# 定义元数据
db_table = 'address'
ordering = 'pid' # 指定按照说明字段排序
verbose_name = "省市县地址信息"
verbose_name_plural = verbose_name
# abstract = True #抽象 ,不生成表
permissions = (('定义好的权限','权限说明'),)
unique_together = ('address','note')
app_label = 'courses' # 表前缀 courses_
# db_tablespace 定义数据库表空间的名称
5.生成数据库的方法
在应用的models.py 下新增class对象后,执行命令: python manage.py makemigrations 生成数据库迁移文件
然后执行 python manage.py migrate 将当前的migration文件内容持久化到数据库中
如果要删除一张表,要先删除 django_migrations表中的新增记录
然后删除migrations夹下的 py文件,最后删除models.py下的class
6.Django导入数据
通过脚本导入: Course.objects.bulk_create( )
导入json 的方式: 执行命令: python manage.py loaddata data.json
三、Models API
假设有class A
A.objects.all(); # select * from A
A.objects.get(id=1) # select * from A where id=1
A.objects.filter(age__gte=20) # select * from A where age>=20
A.objects.filter(id__in=[1,2,3]) # select * from A where id in (1,2,3)
A.objects.filter(name__icontains='A') # select * from A where name like '%A%'
A.objects.all()[:1] #
A.objects.all().order_by('-age') # select * from A order by age desc ;
#查看执行的原生SQL
print(str(A.objects.filter(age__gte=20).order_by('-age').query))
# 返回新QuerySet API
A.objects.all().exclude(id=1)
A.objects.all().exclude(id=1).reverse()
A.objects.all().extra(select={"name":"nickname"}) # nickname as name 取别名
A.objects.all().only('nickname','age') # 只查两个列
A.objects.all().select_related('B') # 查询A时同时关联查询出B ,外键查询
A.objects.filter(age__lt=30).prefetch_related('C') # 多对多关联查询
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)