Thread: [SQLObject] SQLObject introspection: help!
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Carlos R. <car...@gm...> - 2005-03-10 12:00:24
|
Hi all, I am working out something that can become really great for using SQLObject with web forms & complex schemas. The basic idea is as follows (long post ahead!): The app receives values from the form in a dict (duh!). The form description includes a list that maps the form field names to the equivalent SQLObject field names. Up to this point, it's pretty obvious. Now for the trick. The form can refer to fields that are stored in related tables. As long as the relationship is 'safe' - and I'm yet to come up with a good definition of safe, but for this moment we can assume that simple foreign keys are safe - we should be able to edit, and then create or save the complete object. An example (using the infamous Person-Address schema!), using pseudo code: class MyForm(Form) _table = Person name = inputText(source="name") street = inputText(source="address.street") When posted, the form above should update (or create) a person, and update (or create) an address object accordingly. These operations need to be made in the correct order, and there's an awful lot of things to do that I am just beginning to scratch my head over. But notheless... Now, I need to find some way to get to the correct class for the objects mentioned, so I can create new records (update is easier, new object creation is the hard task... because it depends on the class, not the instance, and because it *has* do be done in a very specific order). For the 'root' object, the easiest way is just to supply it in the form description, as in the example above (_table = Person). But how can I get to the Address class in this scenario? - Person.address is a property object. No useful info here (AFAIK). - _columns has the info on the ForeignKey, but can't be acessed directly by name. I have to loop over it to find the column that I need. - Neither _columns (or _join, for what is worth) seem to contain the required info on all cases. For example, in one case I am working with inherited tables. In this case, I had to traverse the inheritance chain to get to the parent, and then I could find the correct foreignKey column (it's not replicated on the child, understably). My question is, how I am supposed to make it work? I think I can do it right now, if I pay attention to each & every special case, but it seems to me that there should be an easier way. I believe that SQLObject can supply better introspection methods, making easy to get the desired info with a clean API. My proposal (feel free to bash it at will) is as follows: - a iterColumns() method, which returns all column descriptors, regardless of inheritance, etc. - a findColumn() method, which returns a column descriptor, lookup upon by name, also taking care of inheritance. - a simple & well documented 'public' interface for the column descriptor, making easy to get information from it. It would be useful for all kinds of form & report generators, etc. Of course, I am willing to contribute code :-) But I would like to get more opinions on this design first. -- Carlos Ribeiro Consultoria em Projetos blog: http://rascunhosrotos.blogspot.com blog: http://pythonnotes.blogspot.com mail: car...@gm... mail: car...@ya... |
From: Oleg B. <ph...@ma...> - 2005-03-10 12:07:25
|
On Thu, Mar 10, 2005 at 09:00:21AM -0300, Carlos Ribeiro wrote: > - _columns has the info on the ForeignKey, but can't be acessed > directly by name. I have to loop over it to find the column that I > need. There is _SO_columnDict (now it is sqlmeta.columnDict). Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Carlos R. <car...@gm...> - 2005-03-10 14:32:40
|
On Thu, 10 Mar 2005 15:07:17 +0300, Oleg Broytmann <ph...@ma...> wrote: > On Thu, Mar 10, 2005 at 09:00:21AM -0300, Carlos Ribeiro wrote: > > - _columns has the info on the ForeignKey, but can't be acessed > > directly by name. I have to loop over it to find the column that I > > need. > > There is _SO_columnDict (now it is sqlmeta.columnDict). Thanks for the info. Anyway, what's your take on the proposed API (iterColumns & findColumn)? -- Carlos Ribeiro Consultoria em Projetos blog: http://rascunhosrotos.blogspot.com blog: http://pythonnotes.blogspot.com mail: car...@gm... mail: car...@ya... |
From: Oleg B. <ph...@ph...> - 2005-03-10 14:27:57
|
On Thu, Mar 10, 2005 at 09:18:09AM -0300, Carlos Ribeiro wrote: > Anyway, what's your take on the proposed API (iterColumns & findColumn)? I don't have any opinion - neither pro nor contra. I do not understand use cases for the API. Why these are functions? You can extend sqlmeta with new lists and dictionaries, no need to find/iterate columns at run-time. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Carlos R. <car...@gm...> - 2005-03-10 14:30:46
|
On Thu, 10 Mar 2005 15:27:22 +0300, Oleg Broytmann <ph...@ph...> wrote: > On Thu, Mar 10, 2005 at 09:18:09AM -0300, Carlos Ribeiro wrote: > > Anyway, what's your take on the proposed API (iterColumns & findColumn)? > > I don't have any opinion - neither pro nor contra. I do not > understand use cases for the API. > Why these are functions? You can extend sqlmeta with new lists and > dictionaries, no need to find/iterate columns at run-time. We can split this question in two parts: 1) Why functions, and not simple new lists and dicts? It depends on the approach, and may be a matter of personal taste. Currently the sqlmeta._columnDict contains only the data from the current class, and does not automatically includes data from the ancestors in an inherited schema. -- In a method-oriented implementation, the iterator (iterColumns) would automatically do the chaining of the parent class transparently. findColumn would do the lookup on the ancestors also. -- In a data-oriented implementation, we either (a) create a new dict for the full column set of the class (including ancestor fields), or (b) augment the existing columnDict with the inherited data (which involves changes to existing code to account for it). ----> Option (a) is interesting -- it solves the iteration & find column problem, at the cost of little space, and is fast. On the other hand, it's yet another member in sqlmeta to take care of. ----> Option (b) seems better in the sense that it does not duplicate info, but causes a whole lot of side effects. (btw, I don't understand the need for a underscore prefix on sqlmeta contents. They're already inside a special structure. sqlmeta.columnDict is better IMHO) 2) Where to put stuff? I agree with you, and the place for it -- be it a data member or a new method -- is inside sqlmeta. -- Carlos Ribeiro Consultoria em Projetos blog: http://rascunhosrotos.blogspot.com blog: http://pythonnotes.blogspot.com mail: car...@gm... mail: car...@ya... |
From: Oleg B. <ph...@ph...> - 2005-03-10 14:06:34
|
On Thu, Mar 10, 2005 at 09:43:39AM -0300, Carlos Ribeiro wrote: > -- In a data-oriented implementation, we either (a) create a new dict > for the full column set of the class (including ancestor fields) > > ----> Option (a) is interesting -- it solves the iteration & find > column problem, at the cost of little space, and is fast. That were my thoughts from the very beginning. I personally in favour of this solution. In SQLObject class a new member is just a pointer to _columnDict. In InheritableSQLObject it should be a separate member. > (btw, I don't understand the need for a underscore prefix on sqlmeta > contents. They're already inside a special structure. > sqlmeta.columnDict is better IMHO) Yes, I think so, too. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Carlos R. <car...@gm...> - 2005-03-10 15:38:29
|
On Thu, 10 Mar 2005 16:01:53 +0300, Oleg Broytmann <ph...@ph...> wrote: > On Thu, Mar 10, 2005 at 09:43:39AM -0300, Carlos Ribeiro wrote: > > -- In a data-oriented implementation, we either (a) create a new dict > > for the full column set of the class (including ancestor fields) > > > > ----> Option (a) is interesting -- it solves the iteration & find > > column problem, at the cost of little space, and is fast. > > That were my thoughts from the very beginning. I personally in favour > of this solution. In SQLObject class a new member is just a pointer to > _columnDict. In InheritableSQLObject it should be a separate member. Ok. I'll see what I can do & I'll provide a patch. > > (btw, I don't understand the need for a underscore prefix on sqlmeta > > contents. They're already inside a special structure. > > sqlmeta.columnDict is better IMHO) > > Yes, I think so, too. Time to ask Ian, or is it fine to rename it? (I guess the former :-) -- Carlos Ribeiro Consultoria em Projetos blog: http://rascunhosrotos.blogspot.com blog: http://pythonnotes.blogspot.com mail: car...@gm... mail: car...@ya... |
From: Ian B. <ia...@co...> - 2005-03-11 07:27:46
|
Carlos Ribeiro wrote: > On Thu, 10 Mar 2005 16:01:53 +0300, Oleg Broytmann <ph...@ph...> wrote: > >>On Thu, Mar 10, 2005 at 09:43:39AM -0300, Carlos Ribeiro wrote: >> >>>-- In a data-oriented implementation, we either (a) create a new dict >>>for the full column set of the class (including ancestor fields) >>> >>>----> Option (a) is interesting -- it solves the iteration & find >>>column problem, at the cost of little space, and is fast. >> >> That were my thoughts from the very beginning. I personally in favour >>of this solution. In SQLObject class a new member is just a pointer to >>_columnDict. In InheritableSQLObject it should be a separate member. > > > Ok. I'll see what I can do & I'll provide a patch. > > >>>(btw, I don't understand the need for a underscore prefix on sqlmeta >>>contents. They're already inside a special structure. >>>sqlmeta.columnDict is better IMHO) >> >> Yes, I think so, too. > > > Time to ask Ian, or is it fine to rename it? (I guess the former :-) It is kind-of-hidden now (_) because it was extra-especially-hidden (_SO_) before. Circular? Kind of. It was extra-especially-hidden before because SQLObject generated it (unlike, say, _columns or _table, which you provided -- of course, now _columns is also generated by SQLObject.) I think it's better to call it "columns", have it still be a dictionary, and maybe implement it as a property for now -- based off _columnDict, plus whatever is necessary to fold in the inherited columns. Of course there is a sqlmeta._columns now as well, which is a little confusing -- but that attribute is lame, because it is full of unbound column objects which aren't very useful, and it'll probably go away eventually. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |