Django orm经常使用字段和字段参数

1.Object Relational Mapping(ORM)

1.1ORM介绍

ORM概念

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。python

简单的说,ORM是经过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。mysql

ORM在业务逻辑层和数据库层之间充当了桥梁的做用。git

ORM由来

让咱们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。程序员

几乎全部的软件开发过程当中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,咱们是面向对象的。当对象的信息发生变化的时候,咱们就须要把对象的信息保存在关系数据库中。sql

按照以前的方式来进行开发就会出现程序员会在本身的业务逻辑代码中夹杂不少SQL语句用来增长、读取、修改、删除相关数据,而这些代码一般都是重复的。shell

ORM的优点

ORM解决的主要问题是对象和关系的映射。它一般把一个类和一个表一一对应,类的每一个实例对应表中的一条记录,类的每一个属性对应表中的每一个字段。数据库

ORM提供了对数据库的映射,不用直接编写SQL代码,只需像操做对象同样从数据库操做数据。django

让软件开发人员专一于业务逻辑的处理,提升了开发效率。后端

ORM的劣势

ORM的缺点是会在必定程度上牺牲程序的执行效率。app

ORM用多了SQL语句就不会写了,关系数据库相关技能退化...

ORM总结

ORM只是一种工具,工具确实能解决一些重复,简单的劳动。这是不能否认的。

但咱们不能期望某个工具能一劳永逸地解决全部问题,一些特殊问题仍是须要特殊处理的。

可是在整个软件开发过程当中须要特殊处理的状况应该都是不多的,不然所谓的工具也就失去了它存在的意义。

1.2Django中的ORM

Django项目使用MySQL数据库

1. 在Django项目的settings.py文件中,配置数据库链接信息:

 

复制代码
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "你的数据库名称",  # 须要本身手动建立数据库
        "USER": "数据库用户名",
        "PASSWORD": "数据库密码",
        "HOST": "数据库IP",
        "POST": 3306
    }
}
复制代码

 

2. 在Django项目的__init__.py文件中写以下代码,告诉Django使用pymysql模块链接MySQL数据库:

a) python2须要安装mysql-python:

  pip install mysql-python

b) python3须要安装pymysql:

 

import pymysql

pymysql.install_as_MySQLdb()

mysql命令回顾

登陆mysql数据库:mysql –uroot –p

查看有哪些数据库:show databases

建立数据库:create database test2 charset=utf8; #切记:指定编码

使用数据库:use test2;

查看数据库中的表:show tables;

Model

在Django中model是你数据的单1、明确的信息来源。它包含了你存储的数据的重要字段和行为。一般,一个模型(model)映射到一个数据库表,

基本状况:

  • 每一个模型都是一个Python类,它是django.db.models.Model的子类。
  • 模型的每一个属性都表明一个数据库字段。
  • 综上所述,Django为您提供了一个自动生成的数据库访问API,详询官方文档连接

 

 

快速入门

下面这个例子定义了一个 Person 模型,包含 first_name 和 last_name

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

 

first_name 和 last_name 是模型的字段。每一个字段被指定为一个类属性,每一个属性映射到一个数据库列。

上面的 Person 模型将会像这样建立一个数据库表:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

 

一些说明:

  • 表myapp_person的名称是自动生成的,若是你要自定义表名,须要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL做为后端数据库时。
  • id字段是自动添加的,若是你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 便可。若是Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。
  • 本示例中的CREATE TABLE SQL使用PostgreSQL语法进行格式化,但值得注意的是,Django会根据配置文件中指定的数据库后端类型来生成相应的SQL语句。
  • Django支持MySQL5.5及更高版本。

软删除标记:

删除数据时不作真正的删除,而是把标记数据设置为1表示删除,目的是防止重要的数据丢失

1.3 模型类生成表

1) 生成迁移文件

命令:python manage.py makemigrations

2) 执行迁移生成表

命令:python mange.py migrate

根据迁移文件生成表。

生成表名的默认格式:

应用名_模型类名小写

1.4经过模型类操做数据表

进入项目shell的命令:

python manage.py shell

如下为在相互shell终端中演示的例子:

首先导入模型类:

from booktest.models import BookInfo,HeroInfo

1) 向booktest_bookinfo表中插入一条数据。

b = BookInfo() #定义一个BookInfo类的对象

b.btitle ='天龙八部' #定义b对象的属性并赋值

b.bpub_date = date(1990,10,11)

b.save() #才会将数据保存进数据库

2) 查询出booktest_bookinfo表中id为1的数据。

b = BookInfo.objects.get(id=1)

3) 在上一步的基础上改变b对应图书的出版日期。

b.bpub_date = date(1989,10,21)

b.save() #才会更新表格中的数据

4) 紧接上一步,删除b对应的图书的数据。

b.delete() #才会删除

5) 向booktest_heroInfo表中插入一条数据。

h = HeroInfo()

h.hname = '郭靖'
h.hgender = False

h.hcomment = ‘降龙十八掌

b2 = BookInfo.objects.get(id=2)

h.hbook = b2  #给关系属性赋值,英雄对象所属的图书对象

h.save()

6) 查询图书表里面的全部内容。

BookInfo.objects.all()

HeroInfo.objects.all()

1.5后台管理

1) 本地化

语言时区的本地化。

修改settings.py文件。

2) 建立管理员

命令:python manage.py createsuperuser

3) 注册模型类

在应用下的admin.py中注册模型类。

告诉djang框架根据注册的模型类来生成对应表管理页面。

b = BookInfo()

str(b) __str__

4) 自定义管理页面

自定义模型管理类。模型管理类就是告诉django在生成的管理页面上显示哪些内容。

1.6模型类属性命名限制

1)不能是python的保留关键字。

2)不容许使用连续的下划线,这是由django的查询方式决定的。

3)定义属性时须要指定字段类型,经过字段类型的参数指定选项,语法以下:

属性名=models.字段类型(选项)

 

2.Django ORM 经常使用字段和参数

2.1经常使用字段

AutoField

自动增加的IntegerField,一般不用指定,不指定时Django会自动建立属性名为id的自动增加属性

IntegerField

一个整数类型,范围在 -2147483648 to 2147483647。

CharField

字符类型,必须提供max_length参数, max_length表示字符长度。

BooleanField

布尔字段,值为True或False

TextField

大文本字段,通常超过4000个字符时使用

DecimalField(max_digits=None, decimal_places=None)

十进制浮点数。参数max_digits表示总位。参数decimal_places表示小数位数

FloatField

浮点数。参数同上

 

DateField:([auto_now=False, auto_now_add=False])

日期。

1)参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它老是使用当前日期,默认为false。

2) 参数auto_now_add表示当对象第一次被建立时自动设置当前时间,用于建立的时间戳,它老是使用当前日期,默认为false。

3)参数auto_now_add和auto_now是

相互排斥的,组合将会发生错误

 

TimeField

时间,参数同DateField

 

DateTimeField

日期时间,参数同DateField

日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至关于Python中的datetime.datetime()实例。

 

FileField

上传文件字段

 

ImageField

继承于FileField,对上传的内容进行校验,确保是有效的图片

 

AutoField(Field)
        - int自增列,必须填入参数 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必须填入参数 primary_key=True

        注:当model中若是没有自增列,则自动会建立一个列名为id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自动建立一个列名为id的且为自增的整数列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定义自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整数 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整数 0 ~ 32767
    IntegerField(Field)
        - 整数列(有符号的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整数 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布尔值类型

    NullBooleanField(Field):
        - 能够为空的布尔值

    CharField(Field)
        - 字符类型
        - 必须提供max_length参数, max_length表示字符长度

    TextField(Field)
        - 文本类型

    EmailField(CharField):
        - 字符串类型,Django Admin以及ModelForm中提供验证机制

    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   上传图片的宽度保存的数据库字段名(字符串)

    DateTimeField(DateField)
        - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 时间格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

    FloatField(Field)
        - 浮点型

    DecimalField(Field)
        - 10进制小数
        - 参数:
            max_digits,小数总长度
            decimal_places,小数位长度

    BinaryField(Field)
        - 二进制类型

字段合集
字段集合

 

 

2.2自定义字段(了解为主)

class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED'

自定义char类型字段:

复制代码
class FixedCharField(models.Field):
    """  自定义的char类型的字段类 """ def __init__(self, max_length, *args, **kwargs): super().__init__(max_length=max_length, *args, **kwargs) self.length = max_length def db_type(self, connection): """  限定生成数据库表的字段类型为char,长度为length指定的值 """ return 'char(%s)' % self.length class Class(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=25) # 使用上面自定义的char类型的字段 cname = FixedCharField(max_length=25)
复制代码

建立的表结构:

 

附ORM字段与数据库实际字段的对应关系

对应关系:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
对应关系

2.3字段参数

null

用于表示某个字段能够为空。

primary_key

若为True,则该字段会成为模型的主键字段,默认值是False,通常做为AutoField的选项使用

unique

若是设置为unique=True 则该字段在此表中必须是惟一的 ,默认值是False

db_index

若是db_index=True 则表明着为此字段设置数据库索引,默认值是False

db_column

字段的名称,若是未指定,则使用属性的名称

default

为该字段设置默认值。

blank

 

若是为True,则该字段容许为空白,默认值是False

对比:null是数据库范畴的概念,blank是后台管理页面表单验证范畴的。

经验:

当修改模型类以后,若是添加的选项不影响表的结构,则不须要从新作迁移,商品的选项中defaultblank不影响表结构。

时间字段独有

DatetimeField、DateField、TimeField这个三个时间字段,均可以设置以下属性。

auto_now_add

配置auto_now_add=True,建立数据记录的时候会把当前时间添加到数据库。

auto_now

配置上auto_now=True,每次更新数据记录的时候会更新该字段。

3.关系字段

3.1ForeignKey

外键类型在ORM中用来表示外键关联关系,通常把ForeignKey字段设置在 '一对多'中'多'的一方。

ForeignKey能够和其余表作关联关系同时也能够和自身作关联关系。

3.1.2字段参数

to

设置要关联的表

to_field

设置要关联的表的字段

related_name

反向操做时,使用的字段名,用于代替原反向查询时的'表名_set'。

例如:

复制代码
class Classes(models.Model): name = models.CharField(max_length=32) class Student(models.Model): name = models.CharField(max_length=32) theclass = models.ForeignKey(to="Classes")
复制代码

当咱们要查询某个班级关联的全部学生(反向查询)时,咱们会这么写:

models.Classes.objects.first().student_set.all()

当咱们在ForeignKey字段中添加了参数 related_name 后,

class Student(models.Model): name = models.CharField(max_length=32) theclass = models.ForeignKey(to="Classes", related_name="students")

当咱们要查询某个班级关联的全部学生(反向查询)时,咱们会这么写:

models.Classes.objects.first().students.all()

related_query_name

反向查询操做时,使用的链接前缀,用于替换表名。

on_delete

当删除关联表中的数据时,当前表与其关联的行的行为。

on_delete=None,               # 删除关联表中的数据时,当前表与其关联的field的行为
on_delete=models.CASCADE,     # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING,  # 删除关联数据,什么也不作
on_delete=models.PROTECT,     # 删除关联数据,引起错误ProtectedError
# models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL,    # 删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空,一对一同理)
# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值,一对一同理)
on_delete=models.SET,         # 删除关联数据,
 a. 与之关联的值设置为指定值,设置:models.SET(值)
 b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

 

models.CASCADE

删除关联数据,与之关联也删除

models.DO_NOTHING

删除关联数据,引起错误IntegrityError

models.PROTECT

删除关联数据,引起错误ProtectedError

models.SET_NULL

删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空)

models.SET_DEFAULT

删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值)

models.SET

删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

复制代码
def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id", on_delete=models.SET(func) )
复制代码

db_constraint

是否在数据库中建立外键约束,默认为True。

 

3.2OneToOneField

一对一字段。

一般一对一字段用来扩展已有字段。

示例

一对一的关联关系多用在当一张表的不一样字段查询频次差距过大的状况下,将本能够存储在一张表的字段拆开放置在两张表中,而后将两张表创建一对一的关联关系。

复制代码
class Author(models.Model):
    name = models.CharField(max_length=32)
    info = models.OneToOneField(to='AuthorInfo')
    

class AuthorInfo(models.Model):
    phone = models.CharField(max_length=11)
    email = models.EmailField()

 

复制代码

3.2.1字段参数

to

设置要关联的表。

to_field

设置要关联的字段。

on_delete

同ForeignKey字段。

3.3ManyToManyField

用于表示多对多的关联关系。在数据库中经过第三张表来创建关联关系。

3.3.1字段参数

to

设置要关联的表

related_name

同ForeignKey字段。

related_query_name

同ForeignKey字段。

symmetrical

仅用于多对多自关联时,指定内部是否建立反向操做的字段。默认为True。

举个例子:

class Person(models.Model): name = models.CharField(max_length=16) friends = models.ManyToManyField("self")

此时,person对象就没有person_set属性。

class Person(models.Model): name = models.CharField(max_length=16) friends = models.ManyToManyField("self", symmetrical=False)

此时,person对象如今就可使用person_set属性进行反向查询。

through

在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。

但咱们也能够手动建立第三张表来管理多对多关系,此时就须要经过through来指定第三张表的表名。

through_fields

设置关联的字段。

db_table

默认建立第三张表时,数据库中表的名称。

3.3.2多对多关联关系的三种方式 

方式一:自行建立第三张表

复制代码
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="书名")


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")


# 本身建立第三张表,分别经过外键关联书和做者
class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")
复制代码

方式二:经过ManyToManyField自动建立第三张表

复制代码
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="书名")


# 经过ORM自带的ManyToManyField自动建立第三张表
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")
    books = models.ManyToManyField(to="Book", related_name="authors")
复制代码

方式三:设置ManyToManyField并指定自行建立的第三张表

复制代码
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="书名")


# 本身建立第三张表,并经过ManyToManyField指定关联
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="做者姓名")
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
    # through_fields接受一个2元组('field1','field2'):
    # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。


class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")
复制代码

 

注意:

当咱们须要在第三张关系表中存储额外的字段时,就要使用第三种方式。

可是当咱们使用第三种方式建立多对多关联关系时,就没法使用set、add、remove、clear方法来管理多对多的关系了,须要经过第三张表的model来管理多对多关系。

3.4元信息(class Meta)

ORM对应的类里面包含另外一个Meta类,而Meta类封装了一些数据库的信息。主要字段以下:

db_table

ORM在数据库中的表名默认是 app_类名,能够经过db_table能够重写表名。

index_together

联合索引。

unique_together

联合惟一索引。

ordering

指定默认按什么字段排序。

只有设置了该属性,咱们查询到的结果才能够被reverse()。

3.5管理器

BookInfo.objects.all()->objects是一个什么东西呢?

答:objects是Django帮我自动生成的管理器对象,经过这个管理器能够实现对数据的查询。

objects是models.Manger类的一个对象。自定义管理器以后Django再也不帮咱们生成默认的objects管理器。

自定义模型管理器类

 

1) 自定义一个管理器类,这个类继承models.Manger类。

 

2)再在具体的模型类里定义一个自定义管理器类的对象

 

 

自定义管理器类的应用场景

 

1) 改变查询的结果集。

 

好比调用BookInfo.books.all()返回的是没有删除的图书的数据。

 

2) 添加额外的方法。

 

管理器类中定义一个方法帮咱们操做模型类对应的数据表

 

使用self.model()就能够建立一个跟自定义管理器对应的模型类对象

 

 

相关文章
相关标签/搜索