Quite often I find myself in the need of fields composed of other
fields. e.g.

    class AddressField(CompositeField):
        addressee = models.CharField(max_length=50)
        street = models.CharField(max_lenght=50)
        zipcode = models.CharField(max_lenght=10)
        # ... more fields here

    class Foo(models.Model):
        billing_address = AddressField()
        shipping_address = AddressField()

I implemented [1] this idea by providing a custom meta class and
contribute_to_class method. The given example would creates the fields
'billing_address_addresee', 'billing_address_street', etc. as well as
'shipping_address_addressee', 'shipping_address_addressee', etc.

The fields 'billing_address' and 'shipping_address' in the Foo class are
properties, which provide a set and get method. The setter is capable of
copying all contained fields while the getter returns a Proxy object
which implements __getattr__, __setattr__ and __cmp__.

This makes it possible to use these fields quite naturally:

    foo = Foo()
    foo.shipping_address.addressee = 'Max Mustermann'
    foo.shipping_address.street = 'Musterstr. 1'
    foo.shipping_address.zipcode = '12345'
    # ...
    if foo.billing_address != foo.shipping_address:
        foo.billing_address = foo.shipping_address

One should be aware that the proxy works by assigning the fields to the
underlying model. This causes the following two snippets to do something
different:

1.
    foo = Foo()
    foo.shipping_address = ...
    # copy all shipping_address sub fields to billing_address
    foo.billing_address = foo.shipping_address

2.
    foo = Foo()
    foo.billing_address = foo.shipping_address
    # billing_address sub fields aren't affected
    foo.shipping_address = ...

This is quite counter intuitive, when thinking of those composite fields
as 'references'. It was the only way to implement this feature without
having to fiddle with the ORM internals. ForeignKey fields work simmilar
- you have to make sure the referenced object has an id set or you're
screwed - so I don't consider this too bad.

Nesting of CompositeFields is not possible right now, but shouldn't be a
big deal to implement. I just didn't ran across a use case, yet, so I
didn't want to spend any time on this.

Feel free to grab the code from [1] and tell me what you think. I tried
to provide some meaningful test cases which also act as example code.


I guess this could also provide a nice foundation for #373 [2].


[1] https://hg.labs.terreon.de/common/chimes/
[2] http://code.djangoproject.com/ticket/373


--mp

--

You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@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.


Reply via email to