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
-~----------~----~----~----~------~----~------~--~---

Reply via email to