I want to create a new type of field for django models that is basically a ListOfStrings. So in your model code you would have the following:
models.py: from django.db import models class ListOfStringsField(???): ??? class myDjangoModelClass(): myName = models.CharField(max_length=64) myFriends = ListOfStringsField() # other.py: myclass = myDjangoModelClass() myclass.myName = "bob" myclass.myFriends = ["me", "myself", "and I"] myclass.save() id = myclass.id loadedmyclass = myDjangoModelClass.objects.filter(id__exact=id) myFriendsList = loadedclass.myFriends # myFriendsList is a list and should equal ["me", "myself", "and I"] My first attempt at this looks like the following, and appears to work as I expect: ========================== 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 ========================== However, I think it could be made a bit cleaner if it could inherit from the proper classes inside of Django.db.models. I have looked at the code, but my Django fu is not quite up to the task (yet). Any pointers on making this cleaner would be much appreciated. Sincerely, Dudley --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---