Задал этот вопрос, ища параметры по умолчанию в EcmaScript 2015 , таким образом, просто упоминая ...
С ES6 мы можем сделать параметры по умолчанию :
function doSomething(optionalParam = "defaultValue"){
console.log(optionalParam);//not required to check for falsy values
}
doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"
То, что вы описали, мне очень похоже на теги.
Итак, почему бы не использовать теги django ?
Он работает как чудо, вы можете установить его независимо от приложения, а его API довольно прост в использовании.
Здесь есть очень хорошая документация по созданию настраиваемых полей .
Однако, я думаю, вы слишком много думаете об этом. Похоже, вам просто нужен стандартный внешний ключ, но с дополнительной возможностью извлекать все элементы в виде единого списка. Так что проще всего было бы просто использовать ForeignKey и определить метод get_myfield_as_list
в модели:
class Friends(model.Model):
name = models.CharField(max_length=100)
my_items = models.ForeignKey(MyModel)
class MyModel(models.Model):
...
def get_my_friends_as_list(self):
return ', '.join(self.friends_set.values_list('name', flat=True))
Теперь вызов get_my_friends_as_list ()
в экземпляре MyModel вернет вам список строк, если требуется.
Спасибо всем, кто ответил. Даже если я не использовал ваш ответ напрямую, примеры и ссылки заставили меня двигаться в правильном направлении.
Я не уверен, что это готово к производству, но, похоже, до сих пор он работал во всех моих тестах.
class ListValueDescriptor(object):
def __init__(self, lvd_parent, lvd_model_name, lvd_value_type, lvd_unique, **kwargs):
"""
This descriptor object acts like a django field, but it will accept
a list of values, instead a single value.
For example:
# define our model
class Person(models.Model):
name = models.CharField(max_length=120)
friends = ListValueDescriptor("Person", "Friend", "CharField", True, max_length=120)
# Later in the code we can do this
p = Person("John")
p.save() # we have to have an id
p.friends = ["Jerry", "Jimmy", "Jamail"]
...
p = Person.objects.get(name="John")
friends = p.friends
# and now friends is a list.
lvd_parent - The name of our parent class
lvd_model_name - The name of our new model
lvd_value_type - The value type of the value in our new model
This has to be the name of one of the valid django
model field types such as 'CharField', 'FloatField',
or a valid custom field name.
lvd_unique - Set this to true if you want the values in the list to
be unique in the table they are stored in. For
example if you are storing a list of strings and
the strings are always "foo", "bar", and "baz", your
data table would only have those three strings listed in
it in the database.
kwargs - These are passed to the value field.
"""
self.related_set_name = lvd_model_name.lower() + "_set"
self.model_name = lvd_model_name
self.parent = lvd_parent
self.unique = lvd_unique
# only set this to true if they have not already set it.
# this helps speed up the searchs when unique is true.
kwargs['db_index'] = kwargs.get('db_index', True)
filter = ["lvd_parent", "lvd_model_name", "lvd_value_type", "lvd_unique"]
evalStr = """class %s (models.Model):\n""" % (self.model_name)
evalStr += """ value = models.%s(""" % (lvd_value_type)
evalStr += self._params_from_kwargs(filter, **kwargs)
evalStr += ")\n"
if self.unique:
evalStr += """ parent = models.ManyToManyField('%s')\n""" % (self.parent)
else:
evalStr += """ parent = models.ForeignKey('%s')\n""" % (self.parent)
evalStr += "\n"
evalStr += """self.innerClass = %s\n""" % (self.model_name)
print evalStr
exec (evalStr) # build the inner class
def __get__(self, instance, owner):
value_set = instance.__getattribute__(self.related_set_name)
l = []
for x in value_set.all():
l.append(x.value)
return l
def __set__(self, instance, values):
value_set = instance.__getattribute__(self.related_set_name)
for x in values:
value_set.add(self._get_or_create_value(x))
def __delete__(self, instance):
pass # I should probably try and do something here.
def _get_or_create_value(self, x):
if self.unique:
# Try and find an existing value
try:
return self.innerClass.objects.get(value=x)
except django.core.exceptions.ObjectDoesNotExist:
pass
v = self.innerClass(value=x)
v.save() # we have to save to create the id.
return v
def _params_from_kwargs(self, filter, **kwargs):
"""Given a dictionary of arguments, build a string which
represents it as a parameter list, and filter out any
keywords in filter."""
params = ""
for key in kwargs:
if key not in filter:
value = kwargs[key]
params += "%s=%s, " % (key, value.__repr__())
return params[:-2] # chop off the last ', '
class Person(models.Model):
name = models.CharField(max_length=120)
friends = ListValueDescriptor("Person", "Friend", "CharField", True, max_length=120)
В конечном счете, я думаю, что это было бы лучше, если бы оно было втолкнуто глубже в код django и работало больше как ManyToManyField или ForeignKey.
Я тоже думаю, что вы идете неверным путем. Пытаться создать из поля Django таблицу вспомогательной базы данных - почти наверняка неправильный подход. Это было бы очень сложно сделать и, вероятно, сбило бы с толку сторонних разработчиков, если бы вы пытались сделать свое решение в целом полезным.
Если вы пытаетесь сохранить денормализованный большой двоичный объект данных в одном столбце, я бы взял подход, аналогичный тому, с которым вы связались, сериализует структуру данных Python и сохраняет ее в TextField. Если вы хотите, чтобы инструменты, отличные от Django, могли работать с данными, вы можете сериализовать его в JSON (или какой-либо другой формат с широкой языковой поддержкой):
from django.db import models
from django.utils import simplejson
class JSONDataField(models.TextField):
__metaclass__ = models.SubfieldBase
def to_python(self, value):
if value is None:
return None
if not isinstance(value, basestring):
return value
return simplejson.loads(value)
def get_db_prep_save(self, value):
if value is None:
return None
return simplejson.dumps(value)
Если вам просто нужен дескриптор, похожий на django Manager, который позволяет вам работать со списком строк, связанных с моделью, вы можете вручную создать таблицу соединения и использовать дескриптор для управления отношениями. Это не совсем то, что вам нужно, но этот код должен помочь вам .