Возвращаясь к этому типу ListField
, который вы можете использовать.Но он делает несколько предположений, например, тот факт, что вы не храните сложные типы в вашем списке.По этой причине я использовал ast.literal_eval()
для обеспечения того, чтобы только простые встроенные типы могли храниться в качестве элементов в ListField
:
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 Dummy(models.Model):
mylist = ListField()
Принимая это за вращение:
>>> from foo.models import Dummy, ListField
>>> d = Dummy()
>>> d.mylist
[]
>>> d.mylist = [3,4,5,6,7,8]
>>> d.mylist
[3, 4, 5, 6, 7, 8]
>>> f = ListField()
>>> f.get_prep_value(d.numbers)
u'[3, 4, 5, 6, 7, 8]'
Там у вас есть то, что список хранится в базе данных в виде строки в юникоде, и когда он извлекается, он запускается через ast.literal_eval()
.
Ранее я предлагал это решениеиз этого поста о пользовательских полях в Django :
Альтернатива CommaSeparatedIntegerField, она позволяет хранить любые отдельные значения.Вы также можете дополнительно указать параметр токена.
from django.db import models
class SeparatedValuesField(models.TextField):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
self.token = kwargs.pop('token', ',')
super(SeparatedValuesField, self).__init__(*args, **kwargs)
def to_python(self, value):
if not value: return
if isinstance(value, list):
return value
return value.split(self.token)
def get_db_prep_value(self, value):
if not value: return
assert(isinstance(value, list) or isinstance(value, tuple))
return self.token.join([unicode(s) for s in value])
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_db_prep_value(value)