Как создать ListField в Django (Python), как свойство ListProperty в Google App Engine (Python)? Мои данные - это список: 3,4,5,6,7,8
.
Какое свойство я должен определить и как бы получить из него значения?
Как создать ListField в Django (Python), как свойство ListProperty в Google App Engine (Python)? Мои данные - это список: 3,4,5,6,7,8
.
Какое свойство я должен определить и как бы получить из него значения?
Повторное использование этого типа 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)
Попробуйте использовать CommaSeparatedIntegerField
, который описан здесь: http://docs.djangoproject.com/en/1.2/ref/models/fields/#commaseparatedintegerfield
Рассмотрим django-jsonfield, преимущества следующие:
и
В то время как ответ jathanism велик, я получал следующую ошибку при попытке использовать команду dumpdata
:
Error: Unable to serialize database: get_db_prep_value() takes at least 3 arguments (2 given)
Проблема заключается в том, что вызов self.get_db_prep_value
в методе value_to_string
требует предоставления значения connection
(по крайней мере, в Django 1.4.10, что я использую). В конце концов, я действительно не понял, что получилось, вызвав метод value_to_string
и удалив его, а также ненужный метод __init__
. Это то, с чем я столкнулся:
class ListField(models.TextField):
__metaclass__ = models.SubfieldBase
description = "Stores a python list"
def to_python(self, value):
if not value:
value = []
if isinstance(value, list):
return value
converted = ast.literal_eval(value)
if not isinstance(converted, list):
raise ValueError('Value "%s" not a list' % converted)
return converted
Если вы используете postgresql, django поддерживает postgres с arrayfield.
Я делаю это:
def get_comma_field(self, field):
data = getattr(self, field)
if data:
return data.split(',')
return []
def set_comma_field(self, val, field):
if isinstance(val, types.StringTypes):
setattr(self, field, val)
else:
setattr(self, field, ','.join(val))
def make_comma_field(field):
def getter(self):
return get_comma_field(self, field)
def setter(self, val):
return set_comma_field(self, val, field)
return property(getter, setter)
class MyModel(models.Model):
_myfield = models.CharField(max_length=31)
myfield = make_comma_field('_myfield')
Но я полагаю, теперь это может быть излишним. Мне было нужно немало из них, поэтому я написал функцию make_comma_field.
Просто вы можете сохранить список как строку и всякий раз использовать его, используйте ast.literal_eval() для преобразования в список сначала из строки. например:
import ast
class MyModel(models.Model):
field_1 = models.any kind of field()
list_field = models.CharField(max_length=255)
def get_list(self):
list = ast.literal_eval(self.list_field)
return list
таким же образом в представлениях и т.д. При сохранении сделайте oprations в списке и, наконец, преобразуйте его в строку:
model.list_field = str(list)
model.save()