如何在Django Model中存储列表?解决实例创建报错问题
Django Model中存储列表的正确方式
你遇到的报错原因很明确:contains = []只是Model类的普通属性,并非Django的数据库字段,所以创建Search实例时传入contains参数会触发"unexpected keyword argument"错误。下面是几种在Django Model中存储列表的标准方案,按需选择:
方案1:使用JSONField(推荐,Django 3.1+)
适合存储简单类型的列表(如字符串、数字、布尔值列表),Django会自动处理序列化和反序列化:
from django.db import models class Search(models.Model): result = models.CharField(max_length=100, null=True, blank=True) name = models.BooleanField(default=True) eotp = models.BooleanField(default=True) reference = models.BooleanField(default=True) date = models.BooleanField(default=True) contains = models.JSONField(null=True, blank=True) # 定义为JSON字段
使用方式:
# 创建实例时直接传入列表 new_search = Search( result=result, name=name, eotp=eotp, reference=reference, date=date, contains=contains_list ) new_search.save() # 读取时直接获取列表 print(new_search.contains) # 直接返回Python列表
方案2:TextField配合手动序列化(兼容老版本Django)
如果你的Django版本低于3.1,可以用TextField存储序列化后的字符串,通过属性封装实现列表的存取:
import json from django.db import models class Search(models.Model): result = models.CharField(max_length=100, null=True, blank=True) name = models.BooleanField(default=True) eotp = models.BooleanField(default=True) reference = models.BooleanField(default=True) date = models.BooleanField(default=True) _contains = models.TextField(null=True, blank=True, db_column='contains') # 实际存储字段 @property def contains(self): # 读取时反序列化为列表 if self._contains: return json.loads(self._contains) return [] @contains.setter def contains(self, value): # 赋值时序列化为字符串 self._contains = json.dumps(value)
使用方式和方案1完全一致,创建实例时直接传入列表即可。
方案3:创建关联模型(适合复杂列表元素)
如果你的列表元素是需要单独查询、修改的复杂对象,推荐用关联模型实现一对多关系:
from django.db import models class Search(models.Model): result = models.CharField(max_length=100, null=True, blank=True) name = models.BooleanField(default=True) eotp = models.BooleanField(default=True) reference = models.BooleanField(default=True) date = models.BooleanField(default=True) class ContainsItem(models.Model): search = models.ForeignKey(Search, on_delete=models.CASCADE, related_name='contains') value = models.CharField(max_length=100) # 根据实际需求定义字段类型,比如IntegerField等
使用方式:
# 先创建Search实例 new_search = Search.objects.create( result=result, name=name, eotp=eotp, reference=reference, date=date ) # 逐个添加列表元素 for item in contains_list: ContainsItem.objects.create(search=new_search, value=item) # 读取时获取所有关联元素 items = new_search.contains.all() # 返回QuerySet,可进一步筛选、排序
内容的提问来源于stack exchange,提问作者Alexandre Boucard
相关产品推荐
相关产品推荐

