ORM是Object Relational Mapping的简称,中文翻译为对象关系模型,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术,ORM在业务逻辑层和数据库层之间充当了桥梁的做用。html
让咱们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。python
几乎全部的软件开发过程当中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,咱们是面向对象的。当对象的信息发生变化的时候,咱们就须要把对象的信息保存在关系数据库中。mysql
按照以前的方式来进行开发就会出现程序员会在本身的业务逻辑代码中夹杂不少SQL语句用来增长、读取、修改、删除相关数据,而这些代码一般都是重复的git
每一个模型都是一个Python类,它是django.db.models.Model的子类。程序员
ORM解决的主要问题是对象和关系的映射,按照规定的语法写,自动翻译成对应的SQL语句.sql
1.不用本身写SQL语句
2. 开发效率高数据库
ORM的缺点是会在必定程度上牺牲程序的执行效率。django
ORM用多了SQL语句就不会写了,关系数据库相关技能退化...后端
1. 操做数据表 ===> 建立表/删除表/修改表
操做models.py里面的类
2. 操做数据行 ===> 数据的增删改查
不能建立数据库,本身动手建立数据库数组
Django项目如何使用ORM链接MySQL
1. 手动建立数据库
2. 在settings.py里面,配置数据库的链接信息
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'booksystem', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': 'root', } }
3. 在项目/__init__.py告诉Django用pymysql模块代替MySQLdb来链接MySQL数据库
import pymysql pymysql.install_as_MySQLdb()
4. 在app/models.py里面定义类
# 做者类 class Author(models.Model): id = models.AutoField(primary_key=True) # 自增的ID主键 name = models.CharField(max_length=16, null=False, unique=True) book = models.ManyToManyField(to="Book") # 建立做者表和书籍表多对多的关系 # 多对多的关系会在数据库中另建立一个新的对应关系表,只存放id的对应关系 def __str__(self): return "<Author object>: {}".format(self.name)
5. 执行两个命令
在哪儿执行?
在项目的根目录(有manage.py文件的那个目录)
下面这个例子定义了一个 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 );
一些说明:
- int自增列,必须填入参数 primary_key=True
- 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)
- 小整数 -32768 ~ 32767
- 正小整数 0 ~ 32767
- 整数列(有符号的) -2147483648 ~ 2147483647
- 正整数 0 ~ 2147483647
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
- 布尔值类型
- 能够为空的布尔值
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
- 文本类型
- 字符串类型,Django Admin以及ModelForm中提供验证机制
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
- 字符串类型,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"
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、链接符(减号)
- 字符串类型,格式必须为逗号分割的数字
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 容许文件 allow_folders=False, 容许文件夹
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
- 日期格式 YYYY-MM-DD
参数(上面两个都能用):
auto_now_add = True 建立数据行时(对象)就会把当前时间添加到数据库 auto_now = True 每次修改数据行(对象)时会把当前时间添加到数据库中
- 时间格式 HH:MM[:ss[.uuuuuu]]
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
- 浮点型
- 10进制小数
- 参数:
max_digits,小数总长度 decimal_places,小数位长度
- 二进制类型
当你想将一些共有信息放进其它一些model的时候,抽象化类是十分有用的。 你编写完基类以后,在 Meta类中设置 abstract=True
, 这个模型就不会被用来建立任何数据表。 取而代之的是,当它被用来做为一个其余model的基类时,它的字段将被加入那些子类中。 若是抽象基类和它的子类有相同的字段名,那么将会出现error(而且Django将抛出一个exception)。
一个例子
from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() class Meta: abstract = True class Student(CommonInfo): home_group = models.CharField(max_length=5)
Student
模型将有三个字段:name
、age
和 home_group
。 CommonInfo
模型没法像通常的Django模型同样使用,由于它是一个抽象基类。 它没法生成一张数据表或者拥有一个管理器,而且不能实例化或者直接储存。
许多应用场景下, 这种类型的模型继承刚好是你想要的。 它提供了一种在Python层面排除常见信息的方法,同时仍然只在数据库层面为每一个子模型建立一个数据库表。
meta继承:
当一个抽象基类被建立的时候, Django把你在基类内部定义的 Meta 类做为一个属性使其可用。 若是子类没有声明本身的Meta类, 它将会继承父类的Meta。若是子类想要扩展父类的Meta类,它能够子类化它。 例如:
from django.db import models class CommonInfo(models.Model): # ... class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # ... class Meta(CommonInfo.Meta): db_table = 'student_info'
Django确实会对抽象基类的Meta类作一个调整:在设置Meta属性以前,Django会设置abstract=False
。 这意味着抽象基类的子类自己不会自动变成抽象类。固然,你可让一个抽象基类继承自另外一个抽象基类, 你只要记得每次都要显式地设置 abstract=True
。
Django还定义一系列字段来描述数据库之间的关联。
ForeignKey(多对一)
多对一关系。要求两个位置参数:模型相关的类和on_delete
选项。 (on_delete
实际上并非必需的,但不提供它会给出已废弃的警告。 在Django 2.0中将须要它。)
若要建立递归关联关系 ——————— 一个对象与本身具备多对一关联关系 — 请使用models.ForeignKey('self', on_delete=models.CASCADE)
。
引用关系(三种状况)
若是你须要关联到一个还没有定义的模型,你可使用模型的名字而不用模型对象自己:
from django.db import models class Car(models.Model): manufacturer = models.ForeignKey( 'Manufacturer', # 同一个应用下的表直接使用名字便可,不一样应用的要'app_name'.'table_name'(即便用app名加表名) on_delete=models.CASCADE, ) # ... class Manufacturer(models.Model): # ... pass
抽象模型上定义的这种关联关系在模型子类化为具体模型时解析,而且不相对于抽象模型的app_label
:
from django.db import models class AbstractCar(models.Model): manufacturer = models.ForeignKey('Manufacturer', on_delete=models.CASCADE) class Meta: abstract = True
from django.db import models from products.models import AbstractCar class Manufacturer(models.Model): pass class Car(AbstractCar): pass # Car.manufacturer将指向这里的`production.Manufacturer`。
若要引用在其它应用中定义的模型,你能够用带有完整标签名的模型来显式指定。 例如,若是上面的Manufacturer
模型是在一个名为production
的应用中定义的,你应该这样使用它:
class Car(models.Model): manufacturer = models.ForeignKey( 'production.Manufacturer', on_delete=models.CASCADE, )
这种称为懒惰关系的引用在解析两个应用程序之间的循环导入依赖关系时可能颇有用。
在幕后,Django 会在字段名上添加"_id"
来建立数据库中的列名。 在上面的例子中,Car
模型的数据库表将会拥有一个manufacturer_id
列。 (你能够经过指定db_column
来显式更改)可是,除非你编写自定义SQL,不然代码不该该处理数据库列名。 你应该永远只处理你的模型对象中的字段名称。
ForeignKey
会自动建立数据库索引。 你能够经过设置db_index
为False
来取消。 若是你建立外键是为了一致性而不是用来Join,或者若是你将建立其它索引例如部分或多列索引,你也许想要避免索引的开销。
参数
ForeignKey.
to
ForeignKey.
on_delete
当删除由ForeignKey
引用的对象时,Django将模拟由on_delete
参数指定的SQL约束的行为。
自1.9版以来已弃用 on_delete
将成为Django 2.0中必需的参数。 在旧版本中,默认为CASCADE。
CASCADE
PROTECT
ProtectedError
以阻止被引用对象的删除,它是
django.db.IntegrityError
的一个子类。
SET_NULL
删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空)
SET_DEFAULT
SET
()
ForeignKey
为传递给
SET()
的值,若是传递的是一个可调用对象,则为调用后的结果。
在大部分情形下,传递一个可调用对象用于避免models.py 在导入时执行查询:
models.SET(值)
class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id", on_delete=models.SET(func), )
DO_NOTHING
不采起任何动做。 若是您的数据库后端强制引用完整性,除非手动添加SQL ON DELETE
约束,不然将致使IntegrityError
到数据库字段。
ForeignKey.
limit_choices_to
当这个字段使用ModelForm
或者Admin 渲染时(默认状况下,查询集中的全部对象均可以使用),为这个字段设置一个可用的选项。 它能够是一个字典、一个Q
对象或者一个返回字典或Q
对象的可调用对象。
# 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) |
反向操做时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()。它仍是related_query_name
的默认值。
若是你不想让Django 建立一个反向关联,请设置related_name
为 '+'
或者以'+'
结尾。 例如,下面这行将肯定User
模型将不会有到这个模型的返回关联:
user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='+', )
反向操做时,使用的链接前缀,用于替换【表名】 如:
models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
用于过滤器或者value,不直接用于.后面
ForeignKey.
to_field
关联到的关联对象的字段名称。 默认地,Django 使用关联对象的主键。 若是引用其余字段,该字段必须具备unique=True
。
ForeignKey.
db_constraint
控制是否在数据库中为这个外键建立约束。 默认值为True
,这几乎是你想要的;将此设置为False
可能对数据完整性很是不利。 即使如此,有一些场景你也许想要这么设置:
若是被设置成False
,访问一个不存在的关联对象将抛出 DoesNotExist
异常。
ManyToManyField(多对多)
ManyToManyField
(to, **options)[source]
一个多对多关联。关联的对象能够经过字段的RelatedManager
添加、删除和建立。
数据库表示
在幕后,Django 建立一个中间表来表示多对多关系。 默认状况下,这张中间表的名称使用多对多字段的名称和包含这张表的模型的名称生成。 由于某些数据库支持的表的名字的长度有限制,这些表的名称将自动截短到64 个字符并加上一个惟一性的哈希值。 这意味着你可能会看到像author_books_9cdf4
这样的表名;这是彻底正常的。 你可使用db_table
选项手工提供中间表的名称。
参数
ManyToManyField.
to
ManyToManyField.to_filed
ManyToManyField.on_delete
ManyToManyField.
related_name
ManyToManyField.
related_query_name
上面几个属性参考foreignerkey的参数便可相同。
ManyToManyField.
limit_choices_to
与ForeignKey.limit_choices_to
相同。
ManyToManyField
对于使用through
参数自定义中间表的limit_choices_to
不生效。
ManyToManyField.
symmetrical
只用于与自身进行关联的ManyToManyField。 例以下面的模型:
from django.db import models class Person(models.Model): friends = models.ManyToManyField("self")
当Django 处理这个模型的时候,它定义该模型具备一个与自身具备多对多关联的ManyToManyField
,所以它不会向person_set
类添加Person
属性。 Django 将假定这个ManyToManyField
字段是对称的 —— 若是我是你的朋友,那么你也是个人朋友。
若是你但愿与self
进行多对多关联的关系不具备对称性,能够设置symmetrical
为False
。 这会强制让Django 添加一个描述器给反向的关联关系,以使得ManyToManyField
的关联关系不是对称的。
ManyToManyField.
through (使用本身指定的第三方表
)
Django 会自动建立一个表来管理多对多关系。 不过,若是你但愿手动指定中介表,可使用through
选项来指定Django 模型来表示你想要使用的中介表。
这个选项最多见的使用场景是当你想要关联更多的数据到关联关系的时候。
若是你没有显式指定through
的模型,仍然会有一个隐式的through
模型类,你能够用它来直接访问对应的表示关联关系的数据库表。 它由三个字段来连接模型。
若是源模型和目标不一样,则生成如下字段:
id
:关系的主键。<containing_model>_id
:声明了ManyToManyField
的模型的id
<other_model>_id
: 被ManyToManyField
所指向的模型的id
若是ManyToManyField
的源模型和目标模型相同,则生成如下字段:
id
:关系的主键。from_<model>_id
:源模型实例的id
。to_<model>_id
:目标模型实例的id
。这个类可让一个给定的模型像普通的模型那样查询与之相关联的记录。
ManyToManyField.
through_fields
只能在指定了自定义中间模型的时候使用。 Django 通常状况会自动决定使用中间模型的哪些字段来创建多对多关联。 可是,考虑以下模型:
from django.db import models class Person(models.Model): name = models.CharField(max_length=50) class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField( Person, through='Membership', through_fields=('group', 'person'), ) class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) inviter = models.ForeignKey( Person, on_delete=models.CASCADE, related_name="membership_invites", ) invite_reason = models.CharField(max_length=64)
Membership
有两个 foreign keys指向 Person
(person
and inviter
), 这样会致使关系不清晰,Django不知道使用哪个外键。 在这种状况下,你必须使用through_fields
明确指定Django 应该使用哪些外键,就像上面例子同样。
through_fields
接受一个2元数组 ('field1', 'field2')
, 其中 field1
是指向定义了ManyToManyField
的那个model的 foreign key的名字(在本例中就是group
,它本身定义了M2M字段,同时也在中间模型中被ForeignKey所指向 ), and field2
就是目标模型的foreign key 的名字 (person
in this case).
当中间模型具备多个外键指向多对多关联关系模型中的任何一个(或两个),你必须 指定through_fields
。 这通用适用于recursive relationships,当用到中间模型而有多个外键指向该模型时,或当你想显式指定Django 应该用到的两个字段时。
递归的关联关系使用的中间模型始终定义为非对称的,也就是symmetrical=False
—— 因此具备源和目标的概念。 这种状况下,'field1'
将做为管理关系的源,而'field2'
做为目标。
ManyToManyField.
db_table
为存储多对多数据而建立的表的名称。 若是没有提供,Django 将基于定义关联关系的模型和字段假设一个默认的名称。
ManyToManyField.
db_constraint
控制中间表中的外键是否建立约束。 默认值为True
,这几乎是你想要的;将此设置为False
可能对数据完整性很是不利。 即使如此,有一些场景你也许想要这么设置:
不能够同时传递db_constraint
和 through
。
OneToOneField(一对一)
OneToOneField
(to, on_delete, parent_link=False, **options)[source]
一对一关联关系。 概念上讲,这个字段相似ForeignKey
设置了unique=True
,不一样的是关联关系的另外一边会直接返回单个对象。选定了之后别的不能选了,不像多对一,别的还能选
何时用一对一?
当 一张表的某一些字段查询的比较频繁,另一些字段查询的不是特别频繁,把不怎么经常使用的字段,单独拿出来作成一张表,而后用过一对一关联起来。
一对一关系使用案例
# 做者 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() phone = models.IntegerField() books = models.ManyToManyField(to="Book", related_name="authors") detail = models.OneToOneField(to="AuthorDetail") def __str__(self): return self.name # 做者详情 class AuthorDetail(models.Model): # 爱好 hobby = models.CharField(max_length=32) # 地址 addr = models.CharField(max_length=128)
注意:一对一关系时,默认值会很差使,觉得这列不能有相同的,全为none也不行
若是你没有指定OneToOneField
的related_name
参数,Django 将使用当前模型的小写的名称做为默认值。
例以下面的例子:
from django.conf import settings from django.db import models class MySpecialUser(models.Model): user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, ) supervisor = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='supervisor_of', )
你将使得User
模型具备如下属性:
>>> user = User.objects.get(pk=1) >>> hasattr(user, 'myspecialuser') True >>> hasattr(user, 'supervisor_of') True
class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' PS: 返回值为字段在数据库中的属性,Django字段默认的值为: '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)',
自定义char类型字段:
class FixedCharField(models.Field): """ 自定义的char类型的字段类 """ def __init__(self, max_length, *args, **kwargs): self.max_length = max_length super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection): """ 限定生成数据库表的字段类型为char,长度为max_length指定的值 """ return 'char(%s)' % self.max_length class Class(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=25) # 使用自定义的char类型的字段 cname = FixedCharField(max_length=25)
建立的表结构:
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': '格式错误'}
正常状况在models.py中写下ORM语句,而后使用makemigrations和migrate便可将models中表结构映射到数据库中,当有了数据库的表结构却没有ORM又该如何呢?下面是从数据库中逆向生成ORM的方法:
首先呢:咱们就须要根据数据库去自动生成新的models文件
python manage.py inspectdb #简单能够看一下自动映射成的models中的内容
这个语句只会将ORM语句输出到控制台中,并无将其保存到文件里,能够手动将这些代码保存到文件里,也可使用下面的语句。
导出而且去代替models.py
python manage.py inspectdb > models.py
这样你就会发如今manage.py的同级目录下生成了一个models.py文件,使用这个models.py文件覆盖app中的models文件,或者将文件里的语句复制到你本身的models.py文件中。
文件的头部提示信息以下:
# This is an auto-generated Django model module. # You'll have to do the following manually to clean this up: # * Rearrange models' order # * Make sure each model has one field with primary_key=True # * Make sure each ForeignKey has `on_delete` set to the desired behavior. # * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table # Feel free to rename the models, but don't rename db_table values or field names.
若是完成了以上的操做,生成的是一个不可修改/删除的models(managed=False),修改meta class中的managed = True则能够去告诉django能够对数据库进行操做,下面解释managed属性的意义
managed:
Options.
managed
True
,表示Django会经过migrate
建立合适的数据表,而且可经过flush
管理命令移除这些数据库表。 换句话说,Django会管理这些数据表的生命周期。
若是是False
,Django 就不会为当前模型建立和删除数据表。 若是当前模型表示一个已经存在的且是经过其它方法建立的者数据表或数据库视图,这会至关有用。 这是设置为managed=False
时惟一的不一样之处。 模型处理的其它任何方面都和日常同样。 这包括:
managed=False
且含有ManyToManyField
,且这个多对多字段指向其余一样也是未被管理模型的,那么这两个未被管理的模型的多对多中介表也不会被建立。 可是,一个被管理模型和一个未被管理模型之间的中介表就会被建立。若是你须要修改这一默认行为,建立中介表做为显式的模型(也要设置managed
),而且使用ManyToManyField.through
为你的自定义模型建立关联。managed=False
),那么在测试以前,你应该要确保在 测试启动时 已经建立了正确的数据表。
若是你对在Python层面修改模型类的行为感兴趣,你能够设置 managed=False
,而且为一个已经存在的模型建立一个副本。 不过在面对这种状况时还有个更好的办法就是使 用Proxy models.
在咱们建立一个模型时,Django的ORM会根据应用名(app name), 模型名(model name)和字段名(field name)自动在数据库中建立数据表。好比咱们有一个Blog的应用,里面有Article模型, 其中Article模型有title这个字段,那么Django默认会建立一个名为blog_article的数据表,其中有title这个字段。假如咱们但愿把表名改成article,标题改成article_title,以便与已经存在的数据表或字段创建映射关系,咱们能够按以下代码操做。
class Article(models.Model): """文章模型""" # 经过db_column自定义数据表中字段名 title = models.CharField('标题', max_length=200, db_column='article_title') slug = models.SlugField('slug', max_length=60, blank=True) def __str__(self): return self.title class Meta: db_table = 'article' # 经过db_table自定义数据表名
经过db_table指定数据表名,还能够经过db_column指定但愿访问的字段名。参考:https://blog.csdn.net/weixin_42134789/article/details/84567297
假如models里面有这样一个表数据:
class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) roles = models.ManyToManyField(to="Role") def __str__(self): return self.name
查询的时候使用下面的语句查询
models.User.objects.filter(name=username, pwd=password).first()
写过orm查询的都知道这句话的用法,那么User.objects到底是什么呢?
objects是Django帮咱们自动生成的管理器对象,经过这个管理器能够为数据的查询添加点共性的东西。好比添加额外的方法和修改查询结果
objects是models.Manager类的一个对象。
class Manager(BaseManager.from_queryset(QuerySet)): pass
可是若是在里本身生成管理器对象,那么原来的objects将再也不好使,改为你定义的那种,好比:
class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) roles = models.ManyToManyField(to="Role") user = models.Manager() # 自定义了一个Manager类对象 def __str__(self): return self.name
这时,User.objects将很差使,而User.user将彻底代替User.objects,下面的图说明这些关系
例以下面,这样修改管理器类的all方法,object.all()方法的内容就会更着改变,这样就能够添加方法和修改原方法