From alan.junk at sunwave.com Fri Apr 2 21:58:20 2004 From: alan.junk at sunwave.com (alan.junk at sunwave.com) Date: Fri, 2 Apr 2004 03:58:20 -0800 (PST) Subject: [albatross-users] Albatross Form Question Message-ID: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> Hello Everyone, I've spent the last few days drooling over albatross, reading documentation and code samples. It looks like a dream come true the things I have to program. Unfortunately, now that I have finally sat down to write my first albatross application, I'm feeling very lost. In addition to being new to albatross, I'm also a python newbie, so I am not sure if I am even approaching my problem from the right direction. Let me explain. Outside of albatross, I currently create customer objects in python and manipulate them. For instance: # create customer object c = customer(username) # read firstname of customer firstname = c.firstName() # set firstname of customer c.firstname('bob') Most of the what the object does is simply manipulate a MySQL backend, but it also runs some checks. Inside albatross, I want to create forms (some of them multipaged and stateful) that will read and manipulate my customer object. After browsing the albatross docs, I came up with an albatross tag like this on a form: First Name: When I load the form, it shows me an input field with the customer object's firstName() value inside it. Good so far. The part that I'm hung up on is saving form input. I am able to do it with something like this: def page_process(self, ctx): ... c = customer(username) c.firstName(ctx.get_value('firstName')) c.lastName(ctx.get_value('lastName')) ...and so on... This works but it feels kludgy. It also seems totally in opposition to the spirit of albatross. The bigger my form is the more it bloats my python code, and if I want to add a field to my form (that will be saved, anyhow), I have to edit the python script and that feels weird. Am I approaching this from the wrong direction? Any advice? Thank you! Alan From neel at mediapulse.com Sat Apr 3 00:16:25 2004 From: neel at mediapulse.com (Michael C. Neel) Date: Fri, 02 Apr 2004 09:16:25 -0500 Subject: [albatross-users] Albatross Form Question In-Reply-To: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> References: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> Message-ID: <406D75B9.5000203@mediapulse.com> Search the list and the docs for the alias attribute for input tags, it will do exactly what you need. A quick summary; you add an albatross_alias method to your customer class that takes no arguments and returns a unique string for the object's instance - in your case using the pri key from the mysql table would be enough. Then in the template, use alias="c.firstname" instead of name and expr. Note the albatross is going to look for a variable not a method. I think there are two ways you can do this, one is add a method .update() in which you call on processing to actually commit the changes to the database, the other would be looking into adding a custom __setattr__ method that provides the actions you need. If your new to python, but an experienced programmer, a good book is Dive Into Python, which is free at http://diveintopython.org/. Mike alan.junk at sunwave.com wrote: > Hello Everyone, > > I've spent the last few days drooling over albatross, reading > documentation and code samples. It looks like a dream come true the > things I have to program. > > Unfortunately, now that I have finally sat down to write my first > albatross application, I'm feeling very lost. In addition to being new to > albatross, I'm also a python newbie, so I am not sure if I am even > approaching my problem from the right direction. > > Let me explain. > > Outside of albatross, I currently create customer objects in python and > manipulate them. For instance: > > # create customer object > c = customer(username) > > # read firstname of customer > firstname = c.firstName() > > # set firstname of customer > c.firstname('bob') > > Most of the what the object does is simply manipulate a MySQL backend, but > it also runs some checks. > > Inside albatross, I want to create forms (some of them multipaged and > stateful) that will read and manipulate my customer object. > > After browsing the albatross docs, I came up with an albatross tag like > this on a form: > > First Name: > > When I load the form, it shows me an input field with the customer > object's firstName() value inside it. Good so far. > > The part that I'm hung up on is saving form input. I am able to do it > with something like this: > > def page_process(self, ctx): > ... > c = customer(username) > c.firstName(ctx.get_value('firstName')) > c.lastName(ctx.get_value('lastName')) > ...and so on... > > This works but it feels kludgy. It also seems totally in opposition to > the spirit of albatross. The bigger my form is the more it bloats my > python code, and if I want to add a field to my form (that will be saved, > anyhow), I have to edit the python script and that feels weird. > > Am I approaching this from the wrong direction? Any advice? > > Thank you! > > Alan > > > > > _______________________________________________ > Albatross-users mailing list > Albatross-users at object-craft.com.au > https://www.object-craft.com.au/cgi-bin/mailman/listinfo/albatross-users From andrewm at object-craft.com.au Sat Apr 3 00:33:52 2004 From: andrewm at object-craft.com.au (Andrew McNamara) Date: Sat, 03 Apr 2004 00:33:52 +1000 Subject: [albatross-users] Albatross Form Question In-Reply-To: Message from alan.junk@sunwave.com of "Fri, 02 Apr 2004 03:58:20 PST." <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> References: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> Message-ID: <20040402143352.8D5CE3C027@coffee.object-craft.com.au> >Unfortunately, now that I have finally sat down to write my first >albatross application, I'm feeling very lost. In addition to being new to >albatross, I'm also a python newbie, so I am not sure if I am even >approaching my problem from the right direction. We've all been there. Fortunately Python is very logical and quick to pick up. >Outside of albatross, I currently create customer objects in python and >manipulate them. For instance: [...] >Most of the what the object does is simply manipulate a MySQL backend, but >it also runs some checks. Good. >Inside albatross, I want to create forms (some of them multipaged and >stateful) that will read and manipulate my customer object. > >After browsing the albatross docs, I came up with an albatross tag like >this on a form: > >First Name: > >When I load the form, it shows me an input field with the customer >object's firstName() value inside it. Good so far. > >The part that I'm hung up on is saving form input. I am able to do it >with something like this: > >def page_process(self, ctx): >... >c = customer(username) >c.firstName(ctx.get_value('firstName')) >c.lastName(ctx.get_value('lastName')) >...and so on... > >This works but it feels kludgy. It also seems totally in opposition to >the spirit of albatross. The bigger my form is the more it bloats my >python code, and if I want to add a field to my form (that will be saved, >anyhow), I have to edit the python script and that feels weird. Albatross wants you to use a Model-View-Controller architecture. There's discussion in the doco on this, but it doesn't go into much depth. The idea is that you have a bunch of logic that implements the business side of your application - this is the Model (your customer class). You have a user interface - this is the View. In between, there's the Controller, which glues the two together (doing conversions and stuff). That's fair enough, but deciding what logic belong where is difficult, and it's often not obvious why you're going to these lengths. One advantage to splitting things up this way is that you can change the business logic without effecting the presentation, or vica versa. And because the business logic is separate, you could write unit-tests for it without the added complexity of interacting with the user interface. You can also use the same Model (business logic) with alternate interfaces (web, gui, command line, etc). What I'm trying to say is that you might find Albatross easier to get along with if you introduce another layer of abstraction between your business logic and the presentation. You might have something like: class CustomerController: def __init__(self, c): ... copy relevent bits of c to attrs of self, possibly formatting the data in friendly ways for the user (eg dates). def update_cust(self, c): ... do the reverse, copying attributes of self to c, converting types, parsing dates, etc. And in the page module or class: def page_enter(ctx): ctx.locals.custcontrol = CustomerController(c) ctx.add_session_vars('custcontrol') def page_display(ctx): ctx.run_template(...) def page_process(ctx): if ctx.req_equals('submit'): ctx.locals.custcontrol.update_cust(c) def page_leave(ctx): ctx.del_session_vars('custcontrol') And in the template: ... etc ... You also ask if you have to update everything when you add another attribute - there isn't really a simple answer to this. Many people have "object relational" abstractions that they use for database driven web applications - they tend to get complex quickly, but the simplest example is a class (or metaclass) that presents the columns of a database row as attributes on an instance, tracks when those attributes change, and generates appropriate SQL to save them back. -- Andrew McNamara, Senior Developer, Object Craft http://www.object-craft.com.au/ From alan.junk at sunwave.com Sat Apr 3 07:16:34 2004 From: alan.junk at sunwave.com (alan.junk at sunwave.com) Date: Fri, 2 Apr 2004 13:16:34 -0800 (PST) Subject: [albatross-users] Albatross Form Question In-Reply-To: <20040402143352.8D5CE3C027@coffee.object-craft.com.au> References: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> <20040402143352.8D5CE3C027@coffee.object-craft.com.au> Message-ID: <62543.63.193.253.38.1080940594.squirrel@webmail.sunwave.com> Mike & Andrew, Thank you both for your excellent replies. They have given me a lot to think about. Andrew, a (hopefully) quick question about your reply: > One advantage to splitting things up this way is that you can change the > business logic without effecting the presentation, or vica versa. And > because the business logic is separate, you could write unit-tests for > it without the added complexity of interacting with the user interface. > You can also use the same Model (business logic) with alternate interfaces > (web, gui, command line, etc). OK, this sounds good and on target for what I want to do. > What I'm trying to say is that you might find Albatross easier to get > along with if you introduce another layer of abstraction between your > business logic and the presentation. I'm willing to go here. Not a problem. Probably better this way for sanity checking routines. > You might have something like: > > class CustomerController: > ... OK, here is where I got lost. Here is the simple CustomerController I came up with: class CustomerController: def __init__(self,c): self.firstname = c.firstName() self.lastname = c.lastName() def update_cust(self,c) c.firstName(self.firstname) c.lastName(self.lastname) Now, I know this is beginning to be more of a python question than an albatross one, but the class above is starting to have that bulky feel again. There are probably 100 customer methods in the customer object dealing with setting, getting, and sanity checking. If I entered them all in the CustomerController just like the methods above, it would start to get pretty ugly. There is also some mention of creating __setitem__ and __getitem__ methods for my customer object, to allow a more "loop" like approach to setting and getting. Although I can see how these would work nicely if my customer data was stored in a dictionary, I don't see how to use them when my customer data is accessed via methods. I'm afraid what I may have done is built a customer object that isn't as python friendly as it could be. I really liked the idea of having a 'firstName' method that could retrieve, store, and run sanity checks but perhaps I need to work with the customer class in some other way? Or perhaps I just need to come to terms with having a bulky CustomerController? I could use the pSQL module to turn my SQL tables into python objects that could play well with albatross just like the CustomerController. My python code would shrink considerably but then I lose any business logic I might have been able to put into a customer method. Alan From neel at mediapulse.com Sat Apr 3 10:20:50 2004 From: neel at mediapulse.com (Michael C. Neel) Date: Fri, 02 Apr 2004 19:20:50 -0500 Subject: [albatross-users] Albatross Form Question In-Reply-To: <62543.63.193.253.38.1080940594.squirrel@webmail.sunwave.com> References: <62314.63.193.253.38.1080907100.squirrel@webmail.sunwave.com> <20040402143352.8D5CE3C027@coffee.object-craft.com.au> <62543.63.193.253.38.1080940594.squirrel@webmail.sunwave.com> Message-ID: <406E0362.3030004@mediapulse.com> > There is also some mention of creating __setitem__ and __getitem__ methods > for my customer object, to allow a more "loop" like approach to setting > and getting. Although I can see how these would work nicely if my > customer data was stored in a dictionary, I don't see how to use them when > my customer data is accessed via methods. > > I'm afraid what I may have done is built a customer object that isn't as > python friendly as it could be. I really liked the idea of having a > 'firstName' method that could retrieve, store, and run sanity checks but > perhaps I need to work with the customer class in some other way? > > Or perhaps I just need to come to terms with having a bulky > CustomerController? No, you have what you need, just not up on python enough yet (hint: read Dive into Python =). Using hasattr, getattr, and setattr your controller wouldn't need to know anthing at all about the underling cusror object. Using some calls to mysql for table info, and/or using c.description information you could preform basic checks on the data. You would still need to hook in complex checks such as is this a valid email, but it wouldn't be much. You also have a dictionary of class members in vars(self) if that approach helps. I'm assuming your using MySQLdb? In which case you can also use a DictCursor class/mixin if getting the result set back as a dict would help. Your going down the right path I think. If you get a solid Controller class, albatross has the tools to expose that Controller in the template, leaving your app logic to the app and not mundane get-validate-update. Then agin, so much of what we do on the web is get-validate-update you may find yourself with nothing to do =p. Mike From alan.junk at sunwave.com Wed Apr 7 13:37:45 2004 From: alan.junk at sunwave.com (Junk) Date: Tue, 06 Apr 2004 20:37:45 -0700 Subject: [albatross-users] Re: al-macro and expr In-Reply-To: <20040402162505.2274.2810.Mailman@numbat.object-craft.com.a u> Message-ID: <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> Hello Again, I find myself trying to do this over and over again in albatross (for example): firstName Of course, this doesn't seem to work. Is there any way to accomplish what I'm trying to do? That is, pass stuff to a macro via and have the macro in turn pass some of those arguments to python expressions for further testing. If I were allowed to do this it would remove a lot of ugly from the routine pages and put them into macros where my brain seems to manage them better. Alan From gabriel.cooper at mediapulse.com Thu Apr 8 00:44:43 2004 From: gabriel.cooper at mediapulse.com (Gabriel Cooper) Date: Wed, 07 Apr 2004 10:44:43 -0400 Subject: [albatross-users] Re: al-macro and expr In-Reply-To: <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> References: <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> Message-ID: <407413DB.8040904@mediapulse.com> Junk wrote: > Hello Again, > > I find myself trying to do this over and over again in albatross (for > example): > > firstName > > > > > > > > [...] The only way that I know of with the current Albatross release is to assign variables instead of using the usearg, like so: [....] [...] (here we have the body where I wanted to print 'myargument':) (which of course prints, as it should, "hello" and not "let's use this in the body!". This is of course obvious, however if you're not careful this can happen to you easily, especially if you have a tendency to name like variables the same way every time. There was some discussion on fixing this in albatross by letting you actually manipulate the arguments, a la: ... but to my knowledge no movement has been made for this. Gabriel. From andrewm at object-craft.com.au Thu Apr 8 11:25:13 2004 From: andrewm at object-craft.com.au (Andrew McNamara) Date: Thu, 08 Apr 2004 11:25:13 +1000 Subject: [albatross-users] Re: al-macro and expr In-Reply-To: Message from Junk of "Tue, 06 Apr 2004 20:37:45 MST." <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> References: <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> Message-ID: <20040408012513.7B9B73C1CA@coffee.object-craft.com.au> >I find myself trying to do this over and over again in albatross (for example): > >firstName > > > > > > > > >Of course, this doesn't seem to work. Is there any way to accomplish what >I'm trying to do? That is, pass stuff to a macro via and have >the macro in turn pass some of those arguments to python expressions for >further testing. Not currently, and I tend to agree that it would be nice. The downside is the templating language starts to look like a programming language, and you loose your separation between presentation and logic, and that way lies PHP... 8-) You might, instead, consider pushing more back into the logic (controller in MVC terms) - something like: page module: ctx.locals.labels = ['firstName', 'whatever'] page template: ... -- Andrew McNamara, Senior Developer, Object Craft http://www.object-craft.com.au/ From neel at mediapulse.com Thu Apr 8 23:51:31 2004 From: neel at mediapulse.com (Michael C. Neel) Date: Thu, 08 Apr 2004 09:51:31 -0400 Subject: [albatross-users] Re: al-macro and expr In-Reply-To: <20040408012513.7B9B73C1CA@coffee.object-craft.com.au> References: <5.2.0.9.2.20040406203240.00b65f50@mail.sunwave.com> <20040408012513.7B9B73C1CA@coffee.object-craft.com.au> Message-ID: <407558E3.5010702@mediapulse.com> An HTML attachment was scrubbed... URL: