当前位置: 代码网 > it编程>前端脚本>Python > Django模型字段类型怎么选?一文搞懂常用字段选项

Django模型字段类型怎么选?一文搞懂常用字段选项

2026年07月17日 Python 我要评论
模型准确且唯一的描述了数据。它包含您储存的数据的重要字段和行为。一般来说,每一个模型都映射一张数据库表。每个模型都是一个 python 的类,这些类继承 django.db.models.model模

模型准确且唯一的描述了数据。它包含您储存的数据的重要字段和行为。

一般来说,每一个模型都映射一张数据库表。

  • 每个模型都是一个 python 的类,这些类继承 django.db.models.model
  • 模型类的每个属性都相当于一个数据库的字段。
  • 利用这些,django 提供了一个自动生成访问数据库的 api;

字段类型

模型中每一个字段都应该是某个 field 类的实例, django 利用这些字段类来实现以下功能:

  • 字段类型用以指定数据库数据类型(如:integer, varchar, text)。
  • 在渲染表单字段时默认使用的 html 视图 (如: , )。
  • 基本的有效性验证功能,用于 django 后台和自动生成的表单。
字段描述
autofield一个 integerfield,根据可用的 id 自动递增
bigautofield一个 64 位整数,与 autofield 很相似,但保证适合 1 到 9223372036854775807 的数字
booleanfield一个 true/false 字段。该字段的默认表单部件是 checkboxinput,或者如果 null=true 则是 nullbooleanselect。当 field.default 没有定义时,booleanfield 的默认值是 none。
charfield一个字符串字段,适用于小到大的字符串。对于大量的文本,使用 textfield charfield 有两个额外的参数:charfield.max_length(必须的。该字段的最大长度)、charfield.db_collation(可选的。该字段的数据库字符序名称)
datefield一个日期,在 python 中用一个 datetime.date 实例表示 可选参数auto_now(每次保存对象时,自动将该字段设置为现在)、auto_now_add(当第一次创建对象时,自动将该字段设置为现在)

详见:django官方文档–字段类型

字段选项

以下只介绍field类中的选项,拓展类每个都有独特的选项,详细参考django文档中每个类别的详细介绍(例如, charfield (以及它的子类)需要接收一个 max_length 参数,用以指定数据库存储 varchar 数据时用的字节数。)

选型描述
null如果设置为 true,当该字段为空时,django 会将数据库中该字段设置为 null。默认为 false 。
blank如果设置为 true,该字段允许为空。默认为 false。
choices一系列二元组,用作此字段的选项 choices = [(‘fr’, ‘freshman’),(‘so’, ‘sophomore’),]
default该字段的默认值
help_text额外的“帮助”文本,随表单控件一同显示。
primary_key如果设置为 true ,将该字段设置为该模型的主键
unique如果设置为 true,这个字段的值必须在整个表中保持唯一

除了 foreignkey, manytomanyfield 和 onetoonefield,任何字段类型都接收一个可选的位置参数 verbose_name,如果未指定该参数值, django 会自动使用字段的属性名作为该参数值,并且把下划线转换为空格。

关联关系

显然,关系型数据库的强大之处在于各表之间的关联关系。

django 提供了定义三种最常见的数据库关联关系的方法:多对一,多对多,一对一。

多对一关联

class foreignkey(to, on_delete, **options)

一个多对一的关系。需要两个位置参数:模型相关的类和 on_delete 选项。

如果需要创建一个递归关系—— 一个与自己有多对一关系的对象

使用 models.foreignkey(‘self’,on_delete=models.cascade)。

如果你需要在一个尚未定义的模型上创建关系,你可以使用模型的名称,而不是模型对象本身:

例如,如果一个 car 模型有一个制造者 manufacturer --就是说一个 manufacturer

制造许多辆车,但是每辆车都仅有一个制造者-- 那么使用下面的方法定义这个关系:

from django.db import models

class manufacturer(models.model):
    # ...
    pass

class car(models.model):
    manufacturer = models.foreignkey(manufacturer, on_delete=models.cascade)
    # ...

on_delete参数设置

当一个由 foreignkey 引用的对象被删除时,django 将模拟 on_delete 参数所指定的 sql 约束的行为。

  • cascade
manufacturer = models.foreignkey(manufacturer, on_delete=models.restrict)

级联删除。django 模拟了 sql 约束 on delete cascade 的行为,也删除了包含 foreignkey 的对象。

model.delete() 在相关的模型上没有被调用,但是 pre_delete 和 post_delete 信号是为所有被删除的对象发送的。

  • protect
manufacturer = models.foreignkey(manufacturer, on_delete=models.protect)

通过引发 protectederror错误,即 django.db.integrityerror 的子类,防止删除被引用对象。

  • restrict
manufacturer = models.foreignkey(manufacturer, on_delete=models.restrict)

这个在django 3.1.以上版本使用

通过引发 restrictederror错误 ( django.db.integrityerror 的一个子类)来防止删除被引用的对象。与 protect 不同的是,如果被引用的对象也引用了一个在同一操作中被删除的不同对象,但通过 cascade 关系,则允许删除被引用的对象。

  • set_null
manufacturer = models.foreignkey(manufacturer, on_delete=models.set_null,null=true)

设置 foreignkey 为空;只有当 null 为 true 时,才有可能。

  • set_default
manufacturer = models.foreignkey(manufacturer, on_delete=models.set_default default=1)

foreignkey 设置为默认值,必须为 foreignkey 设置一个默认值。

  • set()
#定义一个函数进行值得返回
def get_manufacturer()
	return 1

manufacturer = models.foreignkey(manufacturer, on_delete=models.set(get_manufacturer),)

将 foreignkey 设置为传递给 set() 的值,如果传递了一个可调用的值,则为调用它的结果。在大多数情况下,为了避免在导入 models.py 时执行查询,传递一个可调用对象是必要的

  • do_nothing
manufacturer = models.foreignkey(manufacturer, on_delete=models.do_nothing)

不采取任何行动。如果你的数据库后端强制执行引用完整性,这将导致一个 integrityerror 除非你手动添加一个 sql on delete 约束条件到数据库字段。

on_delete 的可能值可以在 django.db.models 中找到。

地区的自关联实例

以下使用地区的自关联查询为实例

#模型创建  model.py
class district(models.model):
    parent = models.foreignkey(
        "self",
        null=true,
        blank=true,
        on_delete=models.cascade,
        related_name="child", #
        verbose_name="父级地区",
    )
    name = models.charfield(max_length=128, help_text="地区名称", verbose_name="地区名称")
    level = models.integerfield(default=0, help_text="地区级别", verbose_name="地区级别")
    full_name = models.charfield(max_length=256, help_text="地区全名", verbose_name="地区全名")
    def __str__(self):
        return self.full_name
    class meta:
        managed=true
        verbose_name = "地区信息"
        verbose_name_plural = verbose_name
#视图调用模型以drf框架的视图的使用apiview主
class citycountyview(apiview):
    """
    父级下二级地区信息获取
    """
    authentication_classes = [basicauthentication]
    permission_classes = (allowany,)
    @swagger_auto_schema(operation_description='父级下二级地区信息获取', responses={200: {}})
    def get(self, request, pk):
        # 判断有没有缓存,有缓存使用缓存,没有缓存去数据库查询存入缓存一天
        sub_data = cache.get('sub_data_%s' % pk)
        if not sub_data:
            try:
                # 获取到前端传过来的父级id  查询出父级对象
                parent_obj = district.objects.get(id=pk)
                # 获取对象的所有外键关联的子级
                sub_objs = parent_obj.child.all()
                subs = []
                # 组织数据
                for sub in sub_objs:
                    subs.append({'id': sub.id, 'name': sub.name, })
                sub_data = {'id': pk, 'name': parent_obj.name, 'subs': subs}
            except exception as e:
                print(e)
                return response({'code': 400, 'errmsg': '查询失败'})
            cache_key_name = 'sub_data_%s' % pk
            cache.set(cache_key_name, sub_data, 3600 * 24) #
        return response({'code': 0, 'errmsg': 'ok', 'sub_data': sub_data})

动态生成模型类

#使用函数+class来定义
def gettaskdetailmodel(table_name):
    class myclass(models.model):
        task = models.foreignkey(task, on_delete=models.cascade, related_name='details', verbose_name='任务')
        user_id = models.integerfield(verbose_name='用户id')
        created_time = models.datetimefield(auto_now_add=true, verbose_name='创建时间')
        is_complet = models.booleanfield(default=false, verbose_name='是否完成')
        class meta:
            db_table = table_name

    return myclass

#使用函数+type进行创建动态类
def create_task_detail_model(password_code):
    classname = f'taskdetail_{password_code}'
    class meta:
        db_table = classname

    return type(classname, (models.model,), {
        'task': models.foreignkey(task, on_delete=models.cascade, related_name='details', verbose_name='任务'),
        'user_id': models.integerfield(verbose_name='用户id'),
        'created_time': models.datetimefield(auto_now_add=true, verbose_name='创建时间'),
        'is_complet': models.booleanfield(default=false, verbose_name='是否完成'),
        '__str__': lambda self: f"{self.task.password_code} - {self.user_id}",
        'meta': meta,
        '__module__': __name__,
    })

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com