You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需第三方数据库,在Django模型中存储数字列表的最简方法?

在Django模型中存储数字列表的简单方案(无需第三方数据库)

首先纠正你的认知:PositiveSmallIntegerField是用于存储单个正小整数的字段,无法直接存储列表;CharField可以存储字符串形式的列表,但需要手动处理序列化逻辑,并非最优选择。下面提供几种基于Django内置字段的可行方案,均支持数字的添加、删除和提取操作:

方案1:使用内置JSONField(推荐)

Django 3.1及以上版本内置了JSONField,支持SQLite(Django默认数据库)、MySQL、PostgreSQL等,无需依赖第三方数据库。它可以直接存储列表类型,ORM层面原生支持对列表的操作,是最便捷的方案。

模型定义

from django.db import models

class MyModel(models.Model):
    numbers = models.JSONField(default=list)  # 默认初始化空列表
    # 其他业务字段...

操作示例

  • 添加数字:
obj = MyModel.objects.get(pk=1)
obj.numbers.append(5)  # 添加单个数字
obj.numbers.extend([3, 7])  # 批量添加
obj.save()
  • 删除数字:
obj = MyModel.objects.get(pk=1)
if 5 in obj.numbers:
    obj.numbers.remove(5)  # 删除指定值的数字
del obj.numbers[0]  # 按索引删除第一个数字
obj.save()
  • 提取数字:
obj = MyModel.objects.get(pk=1)
all_numbers = obj.numbers  # 获取完整列表
first_num = obj.numbers[0] if obj.numbers else None  # 获取单个元素
  • 查询包含特定数字的记录:
# 查询包含数字5的所有MyModel实例
results = MyModel.objects.filter(numbers__contains=5)

方案2:使用CharField/TextField存储序列化字符串

如果你使用的是Django 3.1之前的版本,或出于某些原因不想用JSONField,可以用字符串字段存储JSON序列化后的列表,通过属性封装实现便捷操作。

模型定义

from django.db import models
import json

class MyModel(models.Model):
    numbers_str = models.CharField(max_length=255, default='[]')  # 长列表用TextField

    @property
    def numbers(self):
        # 反序列化字符串为数字列表
        return json.loads(self.numbers_str)
    
    @numbers.setter
    def numbers(self, value):
        # 序列化列表为字符串
        self.numbers_str = json.dumps(value)

操作示例

用法和JSONField一致,因为numbers属性已经封装了序列化逻辑:

obj = MyModel.objects.get(pk=1)
obj.numbers.append(2)
obj.save()

# 删除数字
if 2 in obj.numbers:
    obj.numbers.remove(2)
obj.save()

# 提取列表
print(obj.numbers)

注意:这种方式需要自行处理序列化异常,且查询时只能通过字符串匹配实现,不如JSONField精确(例如查询包含数字5的记录时,可能误匹配到15、25这类包含"5"的数字)。

方案3:使用ManyToManyField关联独立数字模型(规范化存储)

如果需要更规范化的存储(比如后续要给数字添加额外属性),可以创建一个单独的数字模型,通过多对多关联实现列表存储。

模型定义

from django.db import models

class Number(models.Model):
    value = models.PositiveSmallIntegerField()

    def __str__(self):
        return str(self.value)

class MyModel(models.Model):
    numbers = models.ManyToManyField(Number, related_name='my_models')
    # 其他业务字段...

操作示例

  • 添加数字:
# 先获取或创建Number实例(避免重复存储相同数字)
num5, _ = Number.objects.get_or_create(value=5)
obj = MyModel.objects.get(pk=1)
obj.numbers.add(num5)

# 批量添加
nums = [Number.objects.get_or_create(value=v)[0] for v in [3, 7]]
obj.numbers.add(*nums)
  • 删除数字:
num5 = Number.objects.get(value=5)
obj = MyModel.objects.get(pk=1)
obj.numbers.remove(num5)  # 删除指定数字
obj.numbers.clear()  # 清空所有关联数字
  • 提取数字:
obj = MyModel.objects.get(pk=1)
all_numbers = [num.value for num in obj.numbers.all()]
  • 查询包含特定数字的记录:
results = MyModel.objects.filter(numbers__value=5)

内容的提问来源于stack exchange,提问作者Anshul Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:15:35