模型中的列表字段? ?

在我的模型中,我需要一个包含三胞胎列表的字段。例如 [[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]。是否有一个字段可以将这些数据存储在数据库中?

177131 次浏览

您可以展开列表,然后将值存储到 逗号分隔整数字段中。从数据库中读取数据时,只需将这些值重新分组为3。

免责声明: 根据数据库规范化理论,最好不要将收藏品存储在单个字段中,而是鼓励您将这些值存储在他们自己的字段中,并通过外键将它们链接起来。然而,在现实世界中,有时这样做太麻烦/缓慢了。

我觉得这对你有帮助。

from django.db import models
import ast


class ListField(models.TextField):
__metaclass__ = models.SubfieldBase
description = "Stores a python list"


def __init__(self, *args, **kwargs):
super(ListField, self).__init__(*args, **kwargs)


def to_python(self, value):
if not value:
value = []


if isinstance(value, list):
return value


return ast.literal_eval(value)


def get_prep_value(self, value):
if value is None:
return value


return unicode(value)


def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_db_prep_value(value)


class ListModel(models.Model):
test_list = ListField()

例如:

>>> ListModel.objects.create(test_list= [[1,2,3], [2,3,4,4]])
<ListModel: ListModel object>
>>> ListModel.objects.get(id=1)
<ListModel: ListModel object>
>>> o = ListModel.objects.get(id=1)
>>> o.id
1L
>>> o.test_list
[[1, 2, 3], [2, 3, 4, 4]]
>>>

您可以使用 JSON 将其转换为字符串并将其存储为字符串。

比如说,

In [3]: json.dumps([[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]])


Out[3]: '[[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]'

您可以向类中添加一个方法来自动转换它。

import json




class Foobar(models.Model):
foo = models.CharField(max_length=200)


def set_foo(self, x):
self.foo = json.dumps(x)


def get_foo(self):
return json.loads(self.foo)

如果您使用的是 Django 1.9或更高版本,并且您使用 postgreql,那么有一个名为 JSONField 的新类,您应该改用它。这里有一个链接

关于 Youtube上的 PostgreSQLJSONs 和 Ararray 有一个很好的讨论。

只需使用这些第三方软件包提供的 JSON 字段:

在这种情况下,您不需要关心字段值序列化——它将发生在引擎盖下面。

如果使用 PostgreSQL,则可以将 ArrayField 与嵌套的 ArrayField: https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/一起使用

这样,底层数据库就会知道数据结构。

请注意,您必须自己创建一个 GIN 索引(请参阅上面的链接,下面是: https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#indexing-arrayfield)。

(编辑: 更新到最新的 Django LTS 的链接,这个特性至少在1.8以后就存在了。)

如果您正在使用 Google App Engine 或 MongoDB 作为后端,并且正在使用 djangoappengine库,那么在 ListField中有一个内置程序可以完全满足您的需要。此外,查询 Listfield 很容易找到列表中包含元素的所有对象。

如果您使用 Django 1.10或更新的 AND Postgres 作为数据库,则可以使用 ArrayField。它比 django-taggit或其他替代品更适合使用,因为它是 Django 框架的本地特性。 Https://docs.djangoproject.com/en/3.1/ref/contrib/postgres/fields/#arrayfield

from django.db import models
from django.contrib.postgres.fields import ArrayField


class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)

如果你使用的是 Django 3.1或更新的版本,他们已经为 JSONField添加了对大多数数据库后端的支持(MariaDB 10.2.7 + ,MySQL 5.7.8 + ,Oracle,PostgreSQL 和 SQLite 3.9.0 +)。您可以使用它来存储数组!

Https://docs.djangoproject.com/en/3.1/ref/models/fields/#jsonfield

from django.db import models


class ChessBoard(models.Model):
list_of_pieces = models.JSONField()

以我目前的声誉,我没有能力进行注释,所以我选择 Prashant Gaur回答示例代码的回答参考注释(谢谢,Gaur-这很有帮助!)他的样本是 python2,因为 python3没有

Unicode
方法。

下面函数

Get _ ready _ value (self,value) :
的替换应该使用运行 python3的 Django (我很快就会使用这段代码,但还没有测试过)。 但是请注意,我正在将
Code = ‘ utf-8’,error = ‘ annon’编码 = ‘ utf-8’,错误 = ‘忽略’
参数传递给
解码()
Unicode ()方法
。编码应该匹配您的 Django setings.py 配置,传递
错误 = ‘忽略’
是可选的(并且可能导致静默数据丢失,而不是在极少数情况下错误配置 Django 的异常)。

import sys


...


def get_prep_value(self, value):
if value is None:
return value
if sys.version_info[0] >= 3:
if isinstance(out_data, type(b'')):
return value.decode(encoding='utf-8', errors='ignore')
else:
if isinstance(out_data, type(b'')):
return unicode(value, encoding='utf-8', errors='ignore')
return str(value)
...



这是一个相当老的主题,但是由于在搜索“ Django list field”时返回了它,因此我将共享我修改用于 Python 3和 Django 2的自定义 Django list field 代码。它现在支持管理界面,不使用 eval (这是 Prashant Gaur 代码中的一个巨大安全漏洞)。

from django.db import models
from typing import Iterable


class ListField(models.TextField):
"""
A custom Django field to represent lists as comma separated strings
"""


def __init__(self, *args, **kwargs):
self.token = kwargs.pop('token', ',')
super().__init__(*args, **kwargs)


def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['token'] = self.token
return name, path, args, kwargs


def to_python(self, value):


class SubList(list):
def __init__(self, token, *args):
self.token = token
super().__init__(*args)


def __str__(self):
return self.token.join(self)


if isinstance(value, list):
return value
if value is None:
return SubList(self.token)
return SubList(self.token, value.split(self.token))


def from_db_value(self, value, expression, connection):
return self.to_python(value)


def get_prep_value(self, value):
if not value:
return
assert(isinstance(value, Iterable))
return self.token.join(value)


def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)