Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 12 and Version 13 of DataGridWidget


Ignore:
Timestamp:
06/24/07 18:13:02 (12 years ago)
Author:
Chris Arndt
Comment:

migration notice

Legend:

Unmodified
Added
Removed
Modified
  • DataGridWidget

    v12 v13  
    1 == Overview == 
    2  
    3 DataGrid helps you to present your data on a page in a tabular form. DataGrid's purpose is to render   a list of same-kind objects (such as a list of your model instances) in a nice, tabular layout with minimal efforts. The DataGrid subclass, FastDataGrid, integrates nicely with fastdata controllers by providing inline links to edit or delete an object or create new object of the same type.  
    4  
    5 == Differences between !DataGrid and !FastDataGrid == 
    6  
    7 DataGrid requires you to describe what you're going to display via ''fields'' parameter at construction time. FastDataGrid is sophisticated enough to figure out how to display an arbitrary SelectResults instance (this is what you get when you do .select() on you SQLObject's model object). 
    8  
    9 They also have different Kid templates. DataGrid's template is very simple and on purpose -- the goal is to be easy to grasp and easy to extend/replace with a custom one. On the other hand, the FastData template is much more sophisticated, designed to work within FastData environment. It is intended to be used "as is", giving the user certain hooks to customize its appearance. 
    10  
    11 == Basic !DataGrid usage == 
    12  
    13 Suppose you want to display a list of Users in your system. Here is a sample User declaration (note that it's not an SQLObject -- just a plain Python class): 
    14  
    151{{{ 
    16 #!python 
    17 class User: 
    18     def __init__(self, ID, name, emailAddress): 
    19         self.userId = ID 
    20         self.name = name 
    21         self.emailAddress = emailAddress 
    22     displayName = property(fget=lambda self: self.name.capitalize()) 
     2#!rst 
     3.. note:: This page has been migrated to http://docs.turbogears.org/1.0/DataGridWidget. 
    234}}} 
    24  
    25 Given the above definition, you may want to display Users in the following form: 
    26  
    27 {{{ 
    28 #!python 
    29 from turbogears.widgets import DataGrid 
    30  
    31 users_admin_form = DataGrid(fields=[ 
    32     ('ID', 'userId'), 
    33     ('Name', 'displayName'), 
    34     ('E-mail', 'emailAddress'), 
    35 ]) 
    36 }}} 
    37  
    38 As you have probably guessed, ''fields'' parameter defines what and how would be displayed by this DataGrid instance. Each tuple defines single column in the resulting table; first tuple's element defines column's title while second element defines ''accessor''. Accessor usually refers to attribute's name, such as User.userId or property's name, such as User.displayName of our model class.  
    39  
    40 To display a users' table you pass a list of Users to the users_admin_form.display() method: 
    41  
    42 {{{ 
    43 #!python 
    44 users = [User(1, 'john', 'john@foo.net'), User(2, 'fred', 'fred@foo.net')] 
    45 users_admin_form.display(users) 
    46 }}} 
    47  
    48 Result will look something like this (just a bit prettier): 
    49  
    50 {{{ 
    51 #!html 
    52  <table border="0" cellpadding="0" cellspacing="3"> 
    53    <thead><td>ID</td><td>Name</td><td>E-mail</td></thead> 
    54    <tr><td>1</td><td>John</td><td>john@foo.net</td></tr> 
    55    <tr><td>2</td><td>Fred</td><td>fred@foo.net</td></tr> 
    56  </table> 
    57 }}} 
    58  
    59 == Fastdata integration == 
    60  
    61 For a fastdata environment you're mostly likely to use FastDataGrid: 
    62  
    63 {{{ 
    64 #!python 
    65 from tgfastdata import DataController 
    66 from tgfastdata.datawidgets import FastDataGrid 
    67 from model import TG_User 
    68  
    69 class Root(controllers.RootController): 
    70     users = DataController(sql_class=TG_User, list_widget=users_admin_form) 
    71 }}} 
    72  
    73 Now if you access /users/ page you should see a table with a list of users, along with edit/delete icons and "Add a record" link at the bottom. 
    74  
    75 Note that unlike plain DataGrid class you don't need to pass ''fields'' parameter to FastDataGrid. Instead, FastDataGrid able to inspect SelectResults instance it gets to extract SQLObject's metadata. In other words, FastDataGrid instance can easily render arbitrary SQLObjects while with DataGrid you need to list result fields explicitly. You may still want to pass ''fields'' parameter to FastDataGrid if you want to customize fields' representation: fields, their order and how they are displayed. 
    76  
    77 {{{ 
    78 #!python 
    79 class Root(controllers.RootController): 
    80     users = DataController(sql_class=TG_User, 
    81         list_widget=users_admin_form, 
    82         list_template='.templates.admin_users') 
    83 }}} 
    84  
    85 Add something like this to your `admin_users` template: 
    86  
    87 {{{ 
    88 ${list_widget.display(data, show_actions=False, add_link_title='Add User')} 
    89 }}} 
    90  
    91 == Customizing !FastDataGrid representation == 
    92  
    93 You can tweak FastDataGrid's representation to a certain extent by passing configuration options at "display time" (when you call grid.display() from your template). The following options are supported: `show_actions`, `show_add_link`, `add_link_title`, `delete_link_msg`. I hope their meaning is self-explaining. Most up-to-date list of these options can be found at the top of datagrid.kid file at turbogears.fastdata.templates sub-package. 
    94  
    95 == Using Identity with !FastDataGrid == 
    96  
    97 To use IdentityManagement with a FastDataGrid, you must create a subclass of DataController and identity.SecureResource: 
    98  
    99 {{{ 
    100 class SecureDataController(DataController, identity.SecureResource): 
    101     pass 
    102 }}} 
    103  
    104 And to use it in a controller: 
    105  
    106 {{{ 
    107 class Root(controllers.RootController): 
    108     some_fastdatagrid = SecureDataController(sql_class=Whatever) 
    109     some_fastdatagrid.require = identity.in_group("some_group") 
    110 }}} 
    111  
    112 == Customizing !DataGrid representation == 
    113  
    114 Unlike, FastDataGrid, DataGrid's template provides no customization hook. On the other hand it is really simple and easy to understand so if you need to customize DataGrid's representation simply copy it and tweak as you see fit. To use your template with a DataGrid use ''template'' constructor parameter, just like with any Widget. 
    115  
    116 == Advanced !DataGrid usage == 
    117  
    118 In addition to simple DataGrid definition shown above, you can use ''fields'' parameter in a more "advanced" ways. 
    119  
    120 === Using callable instead of attribute name === 
    121  
    122 Sometimes simply displaying an attribute like 'displayName' is not enough. In case of TG_User object, you may want to format nicely permissions a user posseses. To do this, you provide a callable object instead of the attribute name. The callable is then called with a row object and returned value is inserted in a table cell. 
    123  
    124 Example: 
    125  
    126 {{{ 
    127 #!python 
    128 def format_user_permissions(u): 
    129     # ok, nothing fancy here but you get the idea 
    130     # Hint: use Kid's XML function to return HTML markup. 
    131     return ', '.join(u.permissions)  
    132  
    133 users_admin_form = DataGrid(fields=[ 
    134     ('ID', 'userId'), 
    135     ('Name', 'displayName'), 
    136     ('Permissions', format_user_permissions), 
    137 ]) 
    138 }}} 
    139  
    140 Note that a parameterless method of your model class is a suitable callable object: 
    141  
    142 {{{ 
    143 #!python 
    144 class User: 
    145     # ... 
    146     def get_last_login(self): 
    147         "Returns last login's timestamp." 
    148  
    149 users_admin_form = DataGrid(fields=[ 
    150     ('ID', 'userId'), 
    151     ('Name', 'displayName'), 
    152     ('Last logged in', User.get_last_login), 
    153 ]) 
    154 }}} 
    155  
    156 === Using !DataGrid.Column === 
    157  
    158 Instead of two-element tuple you can use an instance of !DataGrid.Column (or subclass thereof) when defining DataGrid's fields. This is only useful if you're using custom DataGrid template as well. 
    159  
    160 The idea of the !DataGrid.Column is to be able to specify arbitrary additional ''options'' along with a column which are then used in template to alter template's logic. 
    161  
    162 Example: 
    163  
    164 {{{ 
    165 #!python 
    166 users_admin_form = DataGrid(fields=[ 
    167     DataGrid.Column('id', 'userId', 'ID', 
    168         options=dict(sortable=True)), 
    169     DataGrid.Column('name', 'displayName', 'Name',  
    170         options=dict(sortable=True)), 
    171     DataGrid.Column('loggedin', 'get_last_login', 'Last logged in'), 
    172 ]) 
    173 }}} 
    174  
    175 Kid template: 
    176  
    177 {{{ 
    178   <div py:for="col in columns" py:strip="True"> 
    179     <?python sortable = col.get_option('sortable', False) ?> 
    180     ... 
    181     <a py:if="sortable" href="${geturl(sortby=col.name)}">${col.title}</a> 
    182     ... 
    183   </div> 
    184 }}} 
    185  
    186 === Using !DataGrid without a 'model' === 
    187  
    188 All the examples above assumed some model class, like User, being used to display in DataGrid. In fact, you can use DataGrid with any kind of data, not necessarily proper instances. The only "hindrance" is that you have to always specify a callable object as a field's accessor. Example: 
    189  
    190 {{{ 
    191 #!python 
    192  
    193 grid = DataGrid(fields=[ 
    194     ('Name', lambda row: row[1]), 
    195     ('Country', lambda row: row[2]), 
    196     ('Age', lambda row: row[0]), 
    197 ]) 
    198  
    199 data = [(33, "Anton Bykov", "Bulgaria"),  
    200     (23, "Joe Doe", "Great Britain"), (44, "Pablo Martelli", "Brazil")] 
    201 grid.display(data) 
    202  
    203 }}} 
    204  
    205 == Error handling == 
    206  
    207 DataGrid does not intercept any exception that may raise during iteration or accessing particular object's attribute.