Should I have posted this to the developer's list? I ask because I have received no responses yet. Not even a "...you shouldn't do that." :)
Sincerely, Dudley On Wed, Jul 15, 2009 at 11:38 AM, Dudley Fox<dudley....@gmail.com> wrote: > 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 -~----------~----~----~----~------~----~------~--~---