one-to-one design problem

7 views
Skip to first unread message

Alice

unread,
Jan 7, 2006, 9:01:44 AM1/7/06
to Django users
Not really django specific, I was having problems with it in
java+hibernate implementation too...

I have a model, 'Items', which is generic enough to extend to more
specialized items, like a 'book items' model for example. This
relationship has been modelled as a one-to-one, but when listing the
detail of any given Item, I would dearly like to have the extended data
displayed too - whatever that may be. The problem is I can't figure out
how to detect that extra data without adding some indication in the
Items table as to what other table(s) to check in. Or I could check all
specialized tables, which is clunky.

Is this a common problem with a solution?

Any help would be appreciated ..


Alice

Dody Suria Wijaya

unread,
Jan 7, 2006, 1:27:05 PM1/7/06
to django...@googlegroups.com

Personally, I avoid separating one2one rows into multiple tables, and
opt to adding more fields into the same table, and then just logically
"extract" whatever field the application needs. Though in ORM world,
this would be a bit difficult or perhaps unnatural way of doing it.

In django, it's easy to get values on the related one2one fields if the
related class name, its module/app name, and the field is specified at
design time:

a = items.get_object(pk=1)
a.get_myapp_itembook().book_title

It becomes tricky otherwise (I can't find an easy way). If you would
only wish to know the extra one2one model's module, this might an
alternative:

from django.core.meta import fields
rel_class_module = [o.opts.get_model_module() \
for o in Item._meta.get_all_related_objects() \
if isinstance(o.field.rel, fields.OneToOne)]

But then you would still need extra steps to get_object(pk=a.pk),
iterate the class' _meta.field to get instance of Field except
OneToOneField, then getattr() their values, ideally in a dictionary
keyed by its name (or field object). Maybe:

allfields = {}
for m in rel_class_module:
obj = m.get_object(pk=a.pk)
for f in m.Klass._meta.field:
if isinstance(f, fields.Field) and \
not isinstance(f, fields.OneToOneField):
allfields[f.name] = getattr(obj, f.name)
# or this:
#allfields[f] = getattr(obj, f.name)


Finally, iterate the dict, all without first knowing Item's related
models or their fields name:

for key,val in allfields.items():
print key,'=',val
# or if using [f] above
# print key.verbose_name,'=',val


--
dsw

Alice

unread,
Jan 7, 2006, 7:05:58 PM1/7/06
to Django users
Thanks for the reply :)

python+django make everything easier than java, but I don't think there
is any nice clean way of modelling something like this.

It might be easier to have each specialized model inheriting from a
generic item class (through django), then listing each seperately or
performing a search across the multiple models ...

... or a model method like item_get_extras() that searches known
specialization models for foreign keys ...

hrm ~ no nice way of doing this it seems.


Alice

oggie rob

unread,
Jan 8, 2006, 3:55:15 PM1/8/06
to Django users
> The problem is I can't figure out
how to detect that extra data without adding some indication in the
Items table as to what other table(s) to check in. Or I could check all
specialized tables, which is clunky.

There may be some way to find out using introspection. You have the
_meta.fields list available for doing so - you could possibly look at
all non-null OneToOne fields and display the extra data in your model:
def get_all_fkey_reps(self):
from django.core.meta import fields
foreignkeys = [f for f in self._meta.fields if str(f.__class__)
== str(fields.ForeignKey)]
for key in foreignkeys:
if getattr(self, key.attname):
print repr(getattr(self, 'get_%s' % (key.name))())

This was just for debugging though - in your case you probably just
want to return the first non-null object.

-rob

Roberto Aguilar

unread,
Jan 8, 2006, 4:01:26 PM1/8/06
to django...@googlegroups.com
I asked a very similar question to this one yesterday and Alice has replied:

http://groups.google.com/group/django-users/browse_thread/thread/0350bdceec7d52d0/54af4cff81b20b32#54af4cff81b20b32

Please take a look at my reply in that post. I think both topics are
awefully similar, should we simply "close" my post and discuss in here
instead?

-Roberto.

oggie rob

unread,
Jan 8, 2006, 5:53:27 PM1/8/06
to Django users
> Please take a look at my reply in that post. I think both topics are
awefully similar, should we simply "close" my post and discuss in here
instead?

Hi Roberto,
I'm not sure the goals you are asking for are the same. What I
mentioned applied to the model only, not to the admin interface.
You should not need to compromise your model for a simpler interface -
Django is flexible enough for you to get by without having to do that.
However, using manipulators is not terribly easy. You might want to try
using some functions that extend object_detail or use multiple
manipulators in the change_stage method (which is what I did).

-rob

Reply all
Reply to author
Forward
0 new messages