在Django模型中存储一个数组是否可能?

67

我想知道在Django模型中是否可以存储数组?

我之所以询问这个问题,是因为我需要在一个字段中存储一组int(例如[1,2,3]),然后能够搜索特定的数组并与之匹配或通过其可能的组合进行匹配。

我正在考虑将这些数组存储为CharField中的字符串,然后在需要搜索时,将值(通过过滤其他模型获得)用' [ ',' ] '和' , '连接起来,然后使用一个生成的字符串进行对象过滤。问题是我必须生成每个可能的组合,然后逐个过滤它们,直到找到匹配项,我认为这可能效率低下。

因此,我希望您能给我一些其他尝试的思路。

我不是在要求代码,任何有关如何实现此目标的想法都是好的。


5个回答

81

我有两个建议:

1) 如果您使用PostgreSQL作为数据库,请使用ArrayField。您可以在这里了解更多关于ArrayField的信息。

2) 将您的数组编码为JSON,然后将其存储为纯字符串或使用JSONField,可以在这里找到相关内容。

就我个人而言,我更喜欢选项1,因为它是更干净、更好的方法,但取决于您实际使用的数据存储方式,这可能不可用。


另一个建议是使用NoSQL数据库。 - Kenny Worden
现在有django支持的JSONField:https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#jsonfield - Eduardo
18
@KennyWorden 哈哈,升级真快:D - Malik Bagwala
Django现在支持JSON字段。只需使用models.JSONField()即可。详情请见:https://docs.djangoproject.com/en/3.1/releases/3.1/#jsonfield-for-all-supported-database-backends - hkimani

30

是的,您可以像这样使用它:

from django.contrib.postgres.fields import ArrayField
class Board(models.Model):
    pieces = ArrayField(ArrayField(models.IntegerField()))

然而,只有在使用PostgreSQL作为数据库时才能使用它。


你是不是想连续两次包含ArrayField?为什么? - Andy Swift
3
@AndrewSwift 这是一个数组的数组,也就是一个矩形数组。 - Aristide
多维数组 - Lakshith Nishshanke

12

3

我不知道为什么没有人建议,但你可以随时使用pickle对对象进行序列化并将结果放入二进制字段。

这种方法的优点是它几乎适用于任何数据库,效率高,并且不仅适用于数组。 缺点是无法轻松地让数据库对序列化数据运行查询。


Pickle是不安全的,它不是序列化,它依赖于虚拟机来重新创建对象,而这个虚拟机是图灵完备的。因此基本上它可以执行任意代码,这可能就是原因。 - jlandercy
@jlandercy 这在这里是一个什么问题?如果攻击者可以访问您的数据库以插入经过处理的数据并运行恶意代码,那么他们也可能能够要求数据库本身运行任意代码。 - al45tair
Pickle是不安全的,这是众所周知的,但我们仍然看到一些错误的快速解决方案依赖它,通常在某个时候会出现问题,因为它是一个非常强大的攻击向量。你的意思是故意向代码中添加漏洞因为它很容易吗? - jlandercy
1
@alastair 这不是真的。攻击者可能只能访问数据库,什么都不能做。是的,数据完全被泄露了,但后端可能没有被攻击。存储腌制数据将为攻击者提供更好的自由度来完成他的工作。此外,攻击者只能简单地插入数据,仅此而已。他们可以插入一些恶意的腌制数据,然后砰,他们现在就拥有了完全的访问权限。 - HosseyNJF
1
我从pickle诞生以来一直在使用它。只要你不对用户输入进行pickling,就没有问题。它从未出现过任何故障,也从未必须更换过它,代码运行良好已经几十年了(只需确保在切换主要版本时迁移格式)。我相信那些“不要使用pickle”的人在他们的代码中做了更棘手的事情。这只是一些容易被人们抓住的低垂果实。 - nurettin
显示剩余2条评论

1
你可以存储一个JSON,并使用该JSON的子数组。
if (data != "attachmentto") {
        formData.append(data, this.recipe[data])
        console.log('rec data ', data)}
        else if (data == "attachmentto") {
          console.log('rec data434 ', this.recipe.attachmentto)
          var myObj = { name: this.recipe.attachmentto.name, age: 31, city: "New York" };
          let kokos = JSON.stringify(myObj);
          // this.recipe.attachmentto.name = this.recipe.attachmentto.name
          formData.append('attachmentto', kokos)
        }

Django 后端:
class Video(models.Model):
  objects = models.Manager()
  title = models.CharField(max_length=80)
  description = models.TextField(max_length=300)
  picture = JSONField(encoder=None)
  price = models.IntegerField(default=0)
  url = models.URLField()
  category = models.CharField(max_length=50)
  subcategory = models.TextField(max_length=50)
  attachmentto = JSONField(encoder=None)
  # attachmentto2 = models.JSONField()
  user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)

并在后端API上返回结果:

   {
        "id": 174,
        "title": "ads",
        "description": "ads",
        "picture": {
            "name": "https://v3.vuejs.org/logo.png"
        },
        "price": 0,
        "user": 1,
        "rating_average": 0,
        "attachmentto": {
            "age": 31,
            "city": "New York",
            "name": [
                "https://restdj.herokuapp.com/media/uploads/ftf_3_cJ0V7TF.png",
                "https://restdj.herokuapp.com/media/uploads/ftf_3.jpg"
            ]
        }
    },

我称它为noicely(nicely)。请注意,我们发送了一个JSON,并且在该JSON中有一个数组

Kokos是为Django设计的完整JSON。

  var myObj = { name: this.recipe.attachmentto.name, age: 31, city: "New York" };



let kokos = JSON.stringify(myObj);

formData.append('attachmentto', kokos)

上面的代码中,name为this.recipe.attachmentto.name的一个数组

这是该数组:

"name": [

"https://restdj.herokuapp.com/media/uploads/ftf_3_cJ0V7TF.png",
                "https://restdj.herokuapp.com/media/uploads/ftf_3.jpg"
            ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接