ORM字段
# Django中开启事务
事务的四大特性 ACID
1> 在with代码块中写的所有SQL语句都属于同一个事务;
2> 经验之谈: 在事务中,尽量只写sql语句,业务逻辑代码写在事务外面!!否则数据量一大,逻辑一复杂,会出错!!
from django.db import transaction
try:
with transaction.atomic():
pass
# -- sql1
# -- sql2
except Exception as e:
print(e)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# ORM常用类型及参数
# 常用字段类型
■ AutoFiled(primary_key=True) # -- 自增+主键
int自增列,必须填入参数primary_key=True
当model中如果没有自增列,则自动会创建一个列名为id的列.
■ CharFiled(max_length=32)
字符类型,必须提供max_length参数,max_length表示字符长度.
Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段
但是Django允许我们自定义新的字段,我们可以自定义对应于数据库的char类型,暂略.
★ Ps: 一般来说,虽然CharFiled对应的是varchar,但超过了255个字符我们就会使用TextField()
这都是经验之谈,具体为什么.可翻看官方文档.
https://docs.djangoproject.com/zh-hans/4.1/ref/databases/#mysql-notes
■ TextField()
可表示65535个字符. 若需要的比这个还多,就需要放到文件中去,写入文件的路径.
■ IntegerField()
一个整数类型,范围在-2147483648 to 2147483647.
一般不用它来存手机号(位数也不够),手机号会直接用字符串存.
■ DateField(auto_now=True,auto_now_add=True) - 年月日
日期字段,日期格式YYYY-MM-DD,相当于Python中的datetime.date()实例
Django的ORM中默认这两个属性都为False
若auto_now=True: 修改记录的时间..
"若用户表里有DateField的字段,并且auto_now=True,那么该字段可以不传值.会自动传当前时间."
若auto_now_add=True: 第一次入库的时间
■ DateTimeField(auto_now=True,auto_now_add=True) - 年月日时分秒
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例
■ BooleanField()
True/False,其实数据库是不支持真假的,实际在表中存的是0和1
■ EmailField()
■ DecimalField(max_digits=8, decimal_places=2) # 跟金额相关会用到它,金额会有小数
存储精确的小数!!!max_digits总共长度,decimal_places小数点后保留两位. 此处是整数部分6位,小数部分2位.
■ ForeignKey()
to: 要关联的表
to_field: 指定关联的表的字段
on_delete:
Django1.x里默认 on_delete=models.CASCADE 级联更新级联删除;在Django2.x里必须指定该参数.
可设置 on_delete=models.SET_NULL,有个前提,该外键需要设置允许为空.
... ...
注意!ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系.
Ps:外键字段、外键数据
■ OneToOneField()
■ ManyToManyField()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 常见字段参数
下面的是常见的字段类型都可以有的字段参数
■ blank、null
在mysql里,默认可以为空,在Django的ORM里默认不为空
Django中,默认blank=False、null=False
- null是针对数据库而言,如果null=True,表示数据库的该字段可以为空
那么在新建一个model对象的时候是不会报错的;
- blank是针对表单的,如果 blank=True,表示你的表单填写该字段的时候可以不填
比如admin后台界面下增加 model 一条记录的时候. <即用户在页面操作时,该字段值可以为空.>
■ unique
如果设置为unique=True 则该字段在此表中必须是唯一的
■ db_index
如果db_index=True 则代表着为此字段设置索引
■ default
为该字段设置默认值
■ verbose_name
对该字段的解释,在后台管理系统里使用的.
■ choices
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# choices参数
针对可能列举完的数据都适用于choices参数!!
app01.models.py
from django.db import models
class User(models.Model):
gender_choice = (
(1, '男'),
(2, '女'),
(3, '未知'),
)
# -- ★★★字段类型根据(1, '男')里第一个元素来决定,这里第一个元素1是int类型!!!
# 数据表中存的是整型数据.So,是IntegerField. 这里不传默认是3.
gender = models.IntegerField(choices=gender_choice, default=3)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
app01.tests.py
from django.test import TestCase
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day56.settings")
import django
django.setup()
from app01 import models
# models.User.objects.create(gender=1)
# models.User.objects.create(gender=2)
# models.User.objects.create(gender=3)
# models.User.objects.create(gender=4)
for i in range(1, 5):
res = models.User.objects.filter(pk=i).first()
# -- 在获取值的时候,固定句式: get_字段名_display()
# 1> 存的值不在choice范围内,原样返回
# 2> 存的值在choice范围中,返回元祖中对应的值!
print(res.gender, res.get_gender_display())
"""
1 男
2 女
3 未知
4 4 # -- 没有对应的就取数据表中的!
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 多对多的三种创建方式
基本不用全自动, 纯手动用sql查控制强!! 半自动方便..看个人喜好啦.
第三张表创建 | 正反向概念 | add、set等方法 | 扩展性 | |
---|---|---|---|---|
全自动 | 自动 | yes | yes | 差 |
纯手动 | 手动 | no | no | 优 |
半自动 | 手动 | yes | no | 优 |
第一种: 全自动
特点
1> Django会自动创建第三张表!
2> 可以利用正反向查询概念. 还可以利用add、set、remove、clear等方法.
3> 只会创建两个表的关系字段, 不会再额外添加字段, 可扩展性差.
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to="Author")
class Author(models.Model):
name = models.CharField(max_length=32)
1
2
3
4
5
6
7
2
3
4
5
6
7
第二种: 纯手动
特点:
1> 手动建表
2> 正反向的概念不能用. add、set、remove、clear等方法也不能用!
3> 第三张表可以根据自己的要求随意添加额外的字段.
class Book(models.Model):
title = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
"""id book_id author_id"""
# -- 提醒,给外键字段取名后面不用加 _id
book = models.ForeignKey(to='Book', on_delete=models.CASCADE)
author = models.ForeignKey(to='Author', on_delete=models.CASCADE)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
第三种: 半自动
特点:
1> 手动建表, 但要告诉orm第三张表是自己建的
2> 可以利用正反向的概念. 但add、set、remove、clear等方法不能用!
3> 第三张表可以根据自己的要求随意添加额外的字段.
在项目后续迭代更新中, 若有需求, 可向关系表中增加字段, 给自己留条后路..
但要告诉orm哪两个字段关联啦!
注意: through_fields中字段的顺序!!
class Book(models.Model):
title = models.CharField(max_length=32)
# -- authors是虚拟字段
# -- through参数:指定第三张表的表名!
# through_fields参数:指定哪两个字段关联!
book = models.ManyToManyField(
to="Author",
through='Book2Author',
# -- ★ 在Book类里, 'book'在前,'author'在后
through_fields=('book', 'author')
)
class Author(models.Model):
name = models.CharField(max_length=32)
# -- 当然多对多的关系也可以在Author表中设置外键!!
# authors = models.ManyToManyField(
# to="Book",
# through='Book2Author',
# # -- ★ 在Author类里, 'author'在前,'book'在后
# through_fields=('author','book')
# )
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = models.DateField()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28