Incalement votre

Entries tagged “zope”

The mysterious Grid class of Formalchemy

written by arrakis, on Jan 20, 2010 6:18:00 PM.

Formalchemy is offering us multiple ways to render our data and to display it. With a form we can create new instances of your objects and modify existing ones. But, more importantly, in our case, we can use it to create multiple new instances at a time

Background

For a project at work, it was needed to generate multiple instances of an item. I decided to use formalchemy to render different form. At first, it was not that easy, when I launched the validation process, an exception was thrown because multiple values with the same key were found. The problem was caused by the fact that each new item was using the same fields name.

It was necessary to use a kind of unique id for each new item and to make sure that their fields would use this in their id

How to use it

Yeah that's cool, but how to propagated a unique to id the field and how to make the validation process to use them?

The main form

All form's definition are built using zope.schema and it's type definition tools

from formalchemy.ext.zope import FieldSet, Grid, Pk
class IOrderEditForm(interface.Interface):
      """Interface of order's edition form"""
      number = schema.Int(title=u"Id of the order", required=True)
      supplyer = schema.List(title=u"Supplyer", required=True)

class IOrderAddItemForm(interface.Interface):
      line = schema.Int(title=u"Line", required=True)
      product = schema.List(title=u"Product", required=True)
      quantity = schema.Int(title=u"Quantity", required=True)

OrderAddItemForm = Grid(IOrderAddItemForm)
OrderEditForm = FieldSet(IOrderEditForm)

class OrderEdit(object):
      _pk = Pk("number")
      interface.implements(IOrderEditForm)

class OrderAddItem(object):
      _pk = Pk("line")
      interface.implements(IOrderAddItemForm)

The pylons controller

The controller is responsible of the rendering of the different fields and to launch the validations. In our case, it's important to configure item's form with pk (primary key) flag to True.

     def edit(self):
         c.instance = OrderEdit()
         c.instance_items = []
         for i in range(0,request.params['item_count'] or 1):
             item = OrderAddItem()
             item.line = i+1
             c.istance_items.append(item)
         c.form = OrderEditForm.bind(c.instance, data=request.params or None)
         c.form_items = OrderAddItemForm.bind(c.instance_items, \
                             data=request.params or None)

         supps = [('One',1),('Two',2),('Three',3)]
         params = [c.form.supplyer.dropdown(options=supp)]  

         c.form.configure(options=params)
         c.form_items.configure(pk=True)
         if request.method == "POST" and c.form.validate() \
               and c.form_items.validate():
            #... ...
            # save routine
            #... ...
            return render("/order/detail")
         return render("/order/edit")

Conclusion

By using a primary key for your multi-items form, it will generate the correct name for each fields, including this primary key value. By example, the name of line field of the first item would be:

OrderAddItem-1-line

When you will validate your form, it will bind each post's data to the corresponding item, depending of the primary of each item ! You just need to create a cool ajaxified interface for your form and it would complete your multi-item form. Oh! And by the way, you should think about using jquery.form.js if you need to submit in an Ajaxified way your form !

Using formalchemy and zope.schema with non-sql databases

written by arrakis, on Jan 14, 2010 7:27:00 PM.

Not so long ago, I started to work on a new pylons project at work. I was now in charge of the development of a new website dealing with accountancy datas.

The particularity of this project is that data is stocked in a proprietary software and we communicate with it using a socket and a special kind of textual request language.

Doing it with Zope ?

Request are in a csv-like format. For example, to fetch all products id, name and available quantity in stock, we would send this:

RQ39,R01,,PRO,PNOM,,PNUM,PNOM,PQST

The response will be something like a csv list of the requested attributes and values. I decided to build a simple kind of ORM and to connect it to pylons with formalchemy and normal html tables.

Formalchemy is a form generator especially useful when using SQLAlchemy. But I did not want to create a kind of adaptor for our strange request system. So I decided to use zope.schema and zope.interface to define the structure of the different fields and to connect everything to my custom ORM.

1. First of all, I defined my form's model with the different field types and their attributes, that way:

class IBuyEditForm(interface.Interface):
      buyid = schema.Int(title=u'Id', readonly=True)
      prodid = schema.Int(title=u'Product', required=True)
      quantity = schema.Int(title=Quantity', required=True)

2. Secondly I implemented my form model as a new type of FieldSet:

from formalchemy.ext.zope import FieldSet

     BuyEditForm = FieldSet(IBuyEditForm)

3. Now I use my form's fieldset in a pylons controller:

from formalchemy.ext.zope import FlexibleDict
from your.project.forms import BuyEditForm
from your.project.lib.buy import BuyWriter

def edit(self):
    instance = FlexibleDict()
    c.form = BuyEditForm.bind(instance, data=request.params or None)
    if request.method == "POST" and c.form.validate():
       c.form.sync()
       BuyWriter.update(**instance)
       return redirect_to(controler='buy', action='detail', id=instance.id)
    return render("/buy/edit.mako")

Conclusion

With the simplicity of formalchemy and zope.schema, I successfuly implemented all needed forms dealing with all my custom queries in my custom ORM. The zope.schema part is very useful to define generic validation parameters and structure of forms. The formalchemy part was very easy to integrate with this kind of strange logic of development, connected with a none common way to interact data.

Thank you zope, you can be easy and useful some times!

Thank you formalchemy, you're the best !

 

Resume Blog Contact Projects Buildbot Code Slides fr en