On Mon, Mar 21, 2011 at 2:33 AM, Christophe Pettus <x...@thebuild.com> wrote: > I'd like to make one more pitch for a slightly different implementation here. > My concern with CompositeField isn't based on the fact that it doesn't map > one-to-one with a field in the table; it's that it doesn't have any of the > semantics that are associated with a field. In particular, it can't be: > > - Assigned to. > - Iterated over. > - Or even have a value.
Obviously there's no code here yet, so we don't know exactly. I'd also be -1 on an implementation of a CompositeField that didn't have those values. However, it's reasonably easy to come up with a CompositeField that is assignable, iterable, and has values. Here's the basics:: class CompositeField(object): def __init__(self, *fields): self.fields = fields def contribute_to_class(self, cls, name): nt_name = "%s_%s" % (cls.__name__, name) nt_fields = " ".join(f.name for f in self.fields) self.nt = collections.namedtuple(nt_name, nt_fields) setattr(cls, name, self) def __get__(self, instance, owner): if instance: return self.nt._make(getattr(instance, f, None) for f in self.nt._fields) raise AttributeError("Composite fields only work on instances.") def __set__(self, instance, value): for (field, val) in zip(self.nt._fields, value): setattr(instance, field, val) It works, too:: class Person(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) name = CompositeField(first_name, last_name) # ... >>> p = Person(first_name="Jacob", last_name="KM") >>> p.name : Person_name(first_name='Jacob', last_name='KM') >>> p.name.last_name : 'KM' >>> p.name = ("John", "Doe") >>> p.last_name : 'Doe' >>> for f in p.name: ..: print f ..: ..: John Doe Fields even sorta get saved correctly to the DB with just these few lines of code. Of course there's a lot missing here to correctly handle actual composite keys -- this tiny example won't work in querysets, for example -- but the basics of the Python-side behavior's right there. > My suggestion is to create an Index type that can be included in a class just > like a field can. I think we're talking slightly different concerns here: I'm mostly interested in the Python-side API, and to my eyes a composite field matches more closely what's happening on the Python side of things. Python's not generating an index, after all, so using something called "index" for compositing multiple attributes together seems weird to me. But at the DB level, "index" makes perfect sense. Thing is, we've always tried to make Django's APIs behave well in Python *first*, and then think about the DB concerns. And again, to me "composite field" matches more closely the behavior we want out of the Python side of things. All that said, there's a lot to like about your Index proposal. Perhaps there's a way we can merge these two things together somehow? Jacob -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.