5、Django_ORM_创建数据库模型类、常用字段属性和选项、元数据、创建数据

ORM

ORM:对象关系映射,详情看上一章

  • ORM种类
    1.DB First:数据库中先创建数据库表结构,然后根据表结构生成类
    2.Code First:先写代码,然后执行代码创建数据库表结构
  • 主流的ORM都是Code First,Django也是如此。所以,学习Django的ORM,分成下面两步
    1.创建Model的子类,数据库模型类,然后根据该类自动创建对应的数据库表
    2.根据该类,对数据库表中的数据进行增删改查操作
    PS.数据库名需要提前创建,django不能创建数据库,django连接数据库时,需要配置数据库名字等参数
一、创建数据库模型类/Model
  • 注意
    1.每个应用的数据库模型类,都需要在该应用的models.py文件中定义
    2.继承modeles.Model,为它的子类
    3.一个数据库模型类都相当于一个数据库表/Table
    4.在数据库模型类定义它的类属性,相当于数据库表中的一个字段
    5.如果不自定义自增主键,那么会默认创建一个ID列,为自增主键
    6.默认创建的数据库类名为:应用名的小写_数据库模型类小写
    polls/models.py
from django.db import models


class UserInfo(models.Model):
    username = models.CharField(max_length=32)  # 用户名
    password = models.CharField(max_length=64)  # 密码
  • 注册App/应用
    1.执行python manage.py makemigrations,提示:django.db.utils.OperationalError: (1046, 'No database selected')
    原因:执行该命令后,Django会去寻找所有的models,但是却不知道寻找哪个,所以需要指定
    2.到settings.py注册App
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls'  # 注册APP/应用
]
  • 数据库迁移:执行命令,生成表结构
python manage.py  makemigrations    # 生成migrations临时文件
python manage.py  migrate           # 根据migrations直接生成数据库

结果:


数据迁移文件
生成表结构成功
  • 连接mysql数据库
    settings.py中设置mysql数据库的配置(默认是连接sqlite)
    PS.使用的是mysqlclient,详情见上一章
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 指定引擎
        'NAME': 'django_db',  # databases名
        'USER': 'root',  # 数据库登录账号
        'PASSWORD': 'root',  # 登录密码
        'HOST': 'localhost',  # 数据库IP
        'PORT': 3306  # 端口
    }
}

到此。创建成功(同时也创建了一些其他表)
创建表成功

二、模型类的字段属性和选项
  • 模型类属性命名限制
    1.不可以是python的保留关键字
    2.不可以使用连续的_,因为django的查询方式不支持
    3.定义属性的时候,需要指定字段的类型,可通过字段类型的参数来制定选项,语法:属性名 = models.字段类型(必参、选项)
a、 单个模型时、常用的字段

1.自增长字段

xx = models.AutoField()  # 自增长
xx = models.BigAutoField()  # 自增长,允许可增长的数字更大

2.二进制数据

xx = models.BinaryField()

3.布尔型

xx = models.BooleanField()  # 不允许为空
xx = models.NullBooleanField()  # 允许为空

4.整型

xx = models.PostitiveSmallIntegerField()  # 正整数、最多可存储大小为5个字节
xx = models.SmallIntegerField()  # 整数、6个字节
xx = models.PositiveIntegerField()  # 正整数、10个字节
xx = models.IntegerField()  # 整数、11个字节
xx = models.BigIntegerField()  # 整数、20个字节

5.字符串

xx = models.CharField()  #  对应sql的vachar
xx = models.TextField()  #  对应sql的longtext

6.时间日期类型

xx = models.DateField()  # 年月日
xx = models.DateTimeField()  # 年月日时分秒
xx = models.DurationField()  # int,底层是python timedelta

7.浮点型

xx = models.FloatField()  # float
xx = models.DecimalField()  # 需指定整数的位数、小数的位数

8.其他字段

xx = models.EmailField()  # 邮箱
xx = models.ImageField()  #
xx = models.FileFiled()  # 文件
xx = models.FilePathField()  # 文件路径
xx = models.URLField()
xx = models.UUIDField()
xx = models.GenericIPAddressField()  # ipv4、ipv6地址
b、 多个模型时、关系型字段
  • OneToOneField:一对一
  • ForeignKey:多对一
  • ManyToManyField:多对多;默认或自定义中间表

polls.pymodels.py
PS.还必须有一些参数,这里还没写入

class A(models.Model):
    onetoone = models.OneToOneField(Admin)  # A表和Admin表是一对一关系


class B(models.Model):
    foreign = models.ForeignKey(A)  # B表和A表是多对一关系


class C(models.Model):
    manytomany = models.ManyToManyField(B)  # C表和B表是多对多关系
c、字段参数
  • 1.所有字段都有的参数
db_column="value"  # 给字段设置名称,不使用默认名
primary_key = False/True  # 该字段是否是主键,默认是False
verbose_name='备注名'  # 设置字段的备注名
unique=True/False  # 字段是否是唯一键,字段的数据在表中是唯一的
/* 下面这两个值要一致 */
null=True/False  # 在数据库中,该字段是否可为空,默认不可为空
blank=True/False  #  在前端表单中,该字段是否可为空

db_index = True/False  # 字段设置索引
help_text = 'value'  # 字段帮助文本
editable=True/False  # 是否可对字段值进行编辑,默认是True
default = 'value'  # 设置字段的默认值

# 对应数据库的枚举类型,一般用于可选并且有限的字段,可以提高数据库的查询效率以及节省空间;
# 可以通过self.get_字段名_display()获取元组的第一个值(0, 1, 2)对应的字符串('保密','男','女')
choices=((0, '保密'), (1, '男'), (2, '女')):
  • 2.个别字段具有的参数
# 1.字符串字段
Char = models.CharField(max_leng = 100)  # 设置最大长度为100,为utf8的长度

# 2.日期字段
Date = models.DateField(unique_for_data=True/False)  # 字段日期是否唯一
Date = models.DateField(unique_for_month=True/False)  # 字段月份是否唯一
''' 下面两个字段建议每个模型都加上,以便于后面的排序操作'''
Date = models.DateField(auto_now=True/False)  # 更新的时间(进行更新数据操作时,这个就是更新的时间)
Date = models.DateField(auto_now_add=True/False)  # 新增的时间(进行新增数据操作时,这个就是新增的时间)

# 3.浮点型
Decimal = models.DecimalField(max_digits=4, decimal_places=2)  # 分别是:总共4个位数,小数点2个位数。比如:12.12, 11.31
  • 3.关系型字段具有的参数
## 1. # 指定主表的外键;用于外键反向关联查询,通过副表查询到主表的信息(反向关联名称)
related_name = 'value' 
# 比如:
class A(models.Model):
    onetoone = models.OneToOneField(Admin, related_name = 'one')  # 字表是A,副表是Admin。现在Admin可通过one这个外键字段,查询到A的相关关系

# 2. 当外键关联的的对象被删除时,Django将模仿on_delete参数定义的SQL来执行对应的操作
# 比如:
class B(models.Model):
    foreign = models.ForeignKey(A, on_delete=行为)  
"""
on_delete的值/六种对应的行为:

1.on_delete.models.CASCADE:模拟SQL的ON_DELETE_CASCADE约束,将定义有外键的模型对象同时删除(是当前版本Django的默认操作)
删除级联:比如说A表的一些字段被删除了,那么B表关联到这些字段的数据也会被删除【常用】
class B(models.Model):
    foreign = models.ForeignKey(A, on_delete=行为) 

2.on_delete.PROTECT:阻止1的删除操作,但是抛出ProtectedError异常
被关联的字段被删除后,就抛出ProtectedError异常

3.on_delete.SET_NULL:将外键字段设置为null,只有当字段设置了null=True、blank=True时,才可以使用该行为【常用】
删除置空,当副表中的记录被删除时,子表对应的字段的值设置为null
class B(models.Model):
    foreign = models.ForeignKey(A, on_delete=行为, null = True, blank=True) 

4.on_delete.SET_DEFAULT:将外键字段设置为默认值,只有当字段设置了default参数时,才可以使用
class B(models.Model):
    foreign = models.ForeignKey(A, on_delete=行为, default=1) 

5.on_delete.DO_NOTHING:什么都不处理

6.on_delete.SET(xx):xx可以是一个传递给SET()的值或者一个回调函数的返回值,大小写敏感
"""

related_name解释

  • 4.自关联
    一个数据表中,字段A关联字段B。
    比如说:地址的省市县,这三个地区从3个不同的模型获取数据,然后使用一对多的外键进行关联。但是这样是不合理的,比较合理的方法是使用自关联来实现:自关联例子
三、元数据Meta
  • 什么是元数据
    在每个Model类下面都有个元数据Meta类,在该类中,封装了数据表的一些信息,称之为模型的元数据。
  • 常用的元数据(官方文档说明有25个元数据)
        fields = ('xx', 'yy')  # 需要序列/反序列化校验的字段
        exclude = ('xx', 'yy')  # 不需要序列/反序列化校验的字段
        verbose_name = '省市县地址'  # 后台显示的名称
        db_table = 'addressainfo'  # 定义当前数据表的表名,不使用默认名称。mysql的tablename一般设置成小写字母
        ordering =['pid']  # 升序排序,根据pid升序排序,前面加-代表降序:['-pid'];先按照pid降序,再按照time升序:['-pid', 'time']
        unique_together = ('address', 'note')  # 设置表的联合唯一键,值可以是一元元组、二元元祖((),())联合约束。比如说unique_together = (('name', 'address'), ):数据库中所有表里只会出现一个address+note,比如说只能有一个张三,广东省
        verbose_name_plural = verbose_name  # verbose_name的父级,一般设置一致
        ''' 这些会影响到表的数据结构'''
        abstract = True  # 当前模型为抽象类。抽象类本身不会实际生成数据表,只会被用于其他类继承使用
        permissions = (('定义好的权限', '权限说明'))  # 添加权限
        managed = False  # 是否按照Django的既定规则去管理本Model类,默认是True
        app_label = 'polls'  # 指明当前Model所属的应用,如果所属的应用没有在settings.py注册,则此处需要进行声明
        db_tablespace = '' # 定义数据库表空间的名字。默认值是工程的DEFAULT_TABLESPACE设置
  • 拿之前创建的AddressInfo为例子:
    1.定义AddressInfo的元数据
class AddressInfo(models.Model):
    """ 省市县地址信息 """
    address = models.CharField(max_length=100, null=True, blank=True, verbose_name='地址')
    pid = models.ForeignKey('AddressInfo', on_delete=models.CASCADE, null=True, blank=True, verbose_name='自关联')
    note = models.CharField(max_length=20, null=True, blank=True, verbose_name='说明')  # 无用字段,用于演示联合唯一键

    def __str__(self):
        """ 给不同的Model对象返回个可读的字符串 """
        return self.address

    class Meta:
        """ 定义元数据 """
        verbose_name = '省市县地址'  # 后台显示的名称
        db_table = 'AddressInfo'  # 定义当前数据表的表名,不使用默认名称
        ordering =['pid']  # 升序排序,根据pid升序排序
        verbose_name_plural = verbose_name  # verbose_name的父级,一般设置一致
        unique_together = ('address', 'note')  # 设置表的联合唯一键,值可以是一元元组、二元元祖((),())联合约束

        ''' 这些会影响到表的数据结构,先注释不执行'''
        # abstract = True  # 继承自哪个Model类,如果本Model类是基类,则为True,可不设置
        # permissions = (('定义好的权限', '权限说明'))  # 添加权限
        # managed = False  # 是否按照Django的既定规则去管理本Model类,默认是True
        # app_label = 'polls'  # 指明当前Model所属的应用,默认是当前应用
        # db_tablespace = '' # 定义数据库表空间的名字

2.迁移数据库

四、生成数据表中的数据
  • 创建和保存对象
#### 方法1
# 1.创建模型类对象,此时sql还未执行
one_value = Userinfo(username='hello', password='hi')
# 2.调用save方法,执行sql语句,生成数据
one_value.save()

#### 方法2
# 执行sql语句,生成数据
Userinfo.objects.create(username='hi', password='hello')
  • 保存外键字段
    保存外键字段和保存普通字段一样,只不过给外键字段赋值的时候要注意类型要正确
  • 保存多对多字段
    需要调用add()方法,而不是直接给属性赋值,不过不需要调用save()方法
from .model.animal import Animal
from .model.cat import Cat

animal = Animal.objects.get(pk = 1)
cat1 = Cat.objects.create(named='xiaomi')  
cat2 = Cat.objects.create(named='xiaohei')

animal.cats.add(cat1, cat2)    # 保存多对多字段
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Django 准备 “虚拟环境为什么需要虚拟环境:到目前位置,我们所有的第三方包安装都是直接通过 pip inst...
    33jubi阅读 1,316评论 0 5
  • ORM的概述 1.什么是ORM?ORM,即Object-Relational Mapping(对象关系映射),它的...
    NewForMe阅读 1,400评论 0 1
  • 文章内容大部分参考官方文档,以作者理解叙述Django中模型是你的数据的唯一的,确定的信息源.它包含你所存储数据所...
    da_yu阅读 2,047评论 0 3
  • 点我查看本文集的说明及目录。 本项目相关内容包括: 实现过程: CH7 创建在线商店 CH8 管理支付和订单 CH...
    学以致用123阅读 3,525评论 0 6
  • 在次翻开自己的年计划,是时候开始准备了,五个月的时候快到了,感慨时间可真快,我的赶快抓紧时间完成计划,明天就开始收...
    啊貴阅读 111评论 0 0