第六节:模型层表操作之Fields字段

模型层表操作之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)
上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 帮助IT小伙伴学到真正的技术