模型层表操作之Fields字段
一、字段名命名限制
Fields字段被指定为模型类的类属性,是模型最重要的部分,也是模型唯一必须要有的部分,是用来定义数据库字段的。
Django 对字段的命名设置了一些限制:
1、注意字段名不要选择与模型API冲突的名字,如clean、save或delete等
2、字段名不能是Python保留字,因为这将导致Python语法错误。例如:
class Example(models.Model):
pass = models.IntegerField() # 'pass'是保留字
3、由于Django 查询语法的工作方式,所以字段名称中连续的下划线不能超过两个。 例如:
class Example(models.Model):
foo__bar = models.IntegerField() # 错误,因字段'foo__bar'带有两个下划线
4、出于类似的原因,字段名不能以下划线结尾。
上述只是针对模型字段的限制,并不是针对数据库列的限制,我们的模型字段名与数据库列名并不是匹配的,可以用db_column字段指定数据库名
class Example(models.Model):
# 数据库中字段名改为aaa__aaa,但查询时仍用aaa
aaa=models.CharField(max_length=10,db_column='aaa__aaa')
bbb=models.CharField(max_length=10,db_column='bbb_')
5、SQL 的保留字例如select、where 和join,可以用作模型的字段名,因为Django 会对底层的SQL 查询语句中的数据库表名和列名进行转义。 它根据你的数据库引擎使用不同的引用语法。即使可以,当我们还是不推荐应用保留字。
二、字段类型
字段类型:
#1、AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
#2、IntegerField
一个整数类型,范围在 -2147483648 to 2147483647。
#3、CharField
字符类型,必须提供max_length参数, max_length表示字符长度。
#4、DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
#5、DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例
示例
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
• 更多详见:
附录1:常用字段和非常用字段合集
• django提供了几十个内置的字段类型,详见
https://docs.djangoproject.com/en/3.0/ref/models/fields/#model-field-types
• 如果django的内置类型无法满足需求,也可以自定义
https://docs.djangoproject.com/en/3.0/howto/custom-model-fields/
三、字段选项/参数
每个字段都有一组特定于该字段的参数。例如字段CharField(及其子类)必须定义一个max_length参数,该参数指定用于存储数据的VARCHAR数据库字段的大小,这部分参数参考官网或提示指定即可。
我们主要讨论一下可用于所有字段类型的公共参数,当然,所有的都是可选的
1、null:
如果为True,Django将在数据库中将空值存储为NULL。默认值为False。
2、blank:
如果为True,则该字段允许为空。默认值为False。
注意,这与null不同。null纯粹与数据库相关,而blank则与验证相关。如果字段的blank=True,则表单验证将允许输入空值。如果字段为空=假,则该字段是必需的。
3、unique:
如果为True,该字段必须是唯一的
4、db_index
如果db_index=True 则代表着为此字段设置索引。
5、db_column
指定数据对应的字段名
name = models.CharField(max_length=64, db_column=’book_name’)
默认字段名为name,指定db_column后,数据库表字段名为book_name
6、choices
用于指定一个二元组,如果给定了此选项,则admin界面默认表单小部件将是一个选择框,而不是标准文本字段,并且将选择限制为给定的选项,如下
from django.db import models
class Person(models.Model):
# 每个元组的第二个元素用来在amdin管理界面显示,而第一个元素才是被存入数据库中的值
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display() # 可以使用get_FOO_display()方法访问具有选项的字段的显示值
'Large'
7、default
字段的默认值。这可以是值或可调用对象。如果可调用,则每次创建新对象时都将调用它。
from django.db import models
def func():
print('from func')
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60,null=True,default=func)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
# 首先我们设置null=True,default=函数
# 然后执行,当插入值为空时,会使用默认值,如果此时默认值为函数,则会触发函数的执行
>>> p = Person()
from func
>>> p.save()
8、auto_now_add
针对 DateField和DateTimeField可以设置auto_now_add=True,新增对象时会自动添加当前时间
create_time=models.DateTimeField(auto_now_add=True) # 只针对创建,不针对修改
9、auto_now
针对 DateField和DateTimeField可以设置auto_now=True,新增或修改对象都会自动填充当前时间
modify_time=models.DateTimeField(auto_now=True) # 针对创建以及修改都有效
*强调:*
\1******)****、选项auto_now、auto_now_add和default是互斥的。只能有一个。****
\2******)****、auto_now=True的自动更新有一个条件,就是要通过django的model层,那有哪些操作是通过model层呢???****
如create或是save方法,则是通过model层
如果是filter之后update方法,则直接调用的是sql,不会通过model层,所以不会自动更新此时间。官方解释如下
What you consider a bug, others may consider a feature, e.g. usingupdate_fieldsto bypass updating fields withauto_now. In fact, I wouldn't expectauto_nowfields to be updated if not present inupdate_fields.
*所以,想让auto_now=True生效的办法是:*强制改成save()或者是update时手动传入时间。
总结
auto_now_add=True
auto_now=True
二者的相同之处,在首次插入记录时,无论是使用create还save,都会自动填充时间
二者的不同之处在于,对于已经存在的记录,再进行update或者save操作时
auto_now_add=True(多用于记录数据的创建时间)
无论是update还是.save()都不能更改他的值,所以其一般用于记录数据的创建时间
auto_now=True(多用于记录数据的更新时间)
update方法不能改变其时间,除非updatet时自己手动传入时间才可以
.save() 时auto_now能够自动填充时间
例如:
obj=Book.objects.filter(id=8).first()
obj.title = "xxx"
obj.save() # auto_now的字段会自动更新时间
3注意时区设置,修改配置文件
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False # 必须改为False
help_text,
用于在admin管理界面显示的额外“帮助”文本。它对于文档很有用
name = models.CharField(max_length=60,null=True,default=func,help_text=’哈哈哈哈哈’)
primary_key
如果为True,那么这个字段就是模型的主键。
主键字段是只读的。 如果你在一个已存在的对象上面更改主键的值并且保存,并不会修改,而是会创建一个新的对象。 例如:
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
<QuerySet ['Apple', 'Pear']>
如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField 字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。 详见下一小节 四 自动主键字段
默认情况下,django自动会为每个模型创建一个主键字段,这种自动的行为称之为隐式创建
id = models.AutoField(primary_key=True)
如果我们想自定义主键,需要为你的某一个字段指定参数primary_key=True,这种自定义行为称之为显式创建
如果django看到你已经自定义了主键,它将不会自动创建id字段啦!
四、设置字段的自述名字
除ForeignKey、ManyToManyField和OneToOneField外,每种字段类型都采用可选的第一个位置参数作为详细名称。如果没有指定要显示的详细名称,Django将使用字段的属性名称自动创建它,并将下划线转换为空格。
如下 admin管理界面字段显示的详细名称为:"person’s first name"
first_name = models.CharField("person's first name", max_length=30)
# first_name = models.CharField(name="person's first name", max_length=30)
如下,字段显示的详细名字为: "first name":
first_name = models.CharField(max_length=30)
针对ForeignKey、ManyToManyField和OneToOneField字段,第一个参数必须为模型类,如果要设置字段显示的详细名字,需要指定参数verbose_name,如下
from django.db import models
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField('用户名',max_length=60,null=True,help_text='哈哈哈')
role=models.ForeignKey(to='Role',verbose_name='权限选择',on_delete=models.CASCADE,null=True)
class Role(models.Model):
PRIVS = (
(0, 'superuser'),
(1, 'user'),
(2, 'visitor'),
)
role=models.CharField('角色',max_length=20)
priv=models.IntegerField('权限',choices=PRIVS)
约定俗称不会将详细名称的第一个字母大写,django会在需要的地方自动将第一个字母大写
五、建立表关系
涉及到字段ForeignKey、ManyToManyField、OneToOneField的使用,详见下一小节
六、自定义字段(了解)
自定义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)