Web2py has several methods for calculated fields, but the documentation states that lazy fields "are not visualized by default in tables" because they don't come with attributes like _. In fact, they don't seem to be able to be available in SQLFORM.grid even if the field is requested. I get the error
AttributeError: 'FieldLazy' object has no attribute 'readable'
When I include a lazy field in the field list.
db.mytable.myfield = Field.Lazy(lambda row: "calc")
Can I put a lazy field into a grid?
What is the recommended way to display a grid that includes calculated fields.
Unfortunately, I don't think there is an easy way to display virtual fields in SQLFORM.grid. What you can do is use the "links" argument and add each virtual field as a link (if "links" is a dictionary, each item will become a separate column in the grid).
links=[dict(header='myfield', body=lambda row: row.myfield)]
Note, in this case, you cannot specify the "fields" argument (i.e., you cannot specify only a subset of the fields for inclusion in the grid) -- this is because the virtual field function needs all the fields in order to work. If you need to hide some of the fields, you can instead set their "readable" attibute to False.
Another option might be computed fields.
Related
The Q&A here and here appear to indicate that the default sort order in the dropdown made by IS_IN_DB validator is determined by the format attribute of the referenced table. But in the following case, the default sort order is the 'id' of the referenced table:
db.define_table('bank',
Field('bank_code', 'string',
unique=True, required=True, label='Bank/FI Code'),
Field('bank_name', 'string',
required=True, label='Bank/FI Name'),
singular="Bank", plural="Banks",
format='%(bank_name)s'
)
db.bank.bank_code.requires=IS_UPPER()
db.bank.bank_name.requires=IS_UPPER()
db.define_table('bank_branch',
Field('bank', 'reference bank', label='Bank/FI'),
Field('branch_name', 'string', required=True, label='Branch Name'),
format=lambda r:'%s-%s' % (r.bank.bank_code, r.branch_name)
Even though the dropdown labels display the labels returned by the lambda function of the table bank_branch, they are sorted on its id field.
It is advised here to use IS_IN_SET for such situations, but what can be the explanation for the normal behaviour of sorting on the basis of 'format' attribute getting changed when such format is done by lambda function?
By default, when the IS_IN_DB validator generates the set of values and associated labels, it does not directly sort by the generated labels. Rather, in the database select, it specifies an ORDER BY clause that includes the fields used to generate the label. If the format attribute of the referenced table is a Python format string, the label fields are extracted from that format string in the order they appear. This has the effect of ordering the final set by the labels in that case.
However, if the format attribute of the referenced table is a function, IS_IN_DB does not know which fields are needed to generate the labels, so it simply selects all fields in the table and orders by all fields (in the order they appear in the table definition). In this case, because db.bank_branch.id is the first field in the table definition (though not defined explicitly), that is the first field in the ORDER BY clause, resulting in the options being ordered by the IDs of the db.bank_branch table.
If you want to force the options to be sorted by the generated labels, you can use the sort argument:
IS_IN_DB(db, 'bank_branch.id', db.bank_branch._format, sort=True)
As an aside, keep in mind that if there are many bank branches, this method of generating labels is somewhat inefficient, as the format function includes a recursive select (i.e., r.bank.brank_code), which does a separate select for every item in the list. An alternative would be to generate your own set of values and labels based on a join query and then use the IS_IN_SET validator (or use IS_IN_DB just for the validation, and specify the form widget and its options separately). Of course, at some point, there may be more branches than would be reasonable to include in a select input, in which case, you can use IS_IN_DB to do the validation but should use an alternative input widget (e.g., an Ajax autocomplete).
I'm trying to update a multi value drop down list field (custom field) in Rally using python2.7 and pyral (v 1.3.2).
I can add a single value to the field like this:
>>> update_data = {'FormattedID' : 'US58848', 'c_MapProfile' : {'ObjectID' : 129751972040}}
>>> rally.post('UserStory', update_data)
<pyral.entity.HierarchicalRequirement object at 0x6fffea46c50>
This updates the field to the attribute value specified by the ObjectID.
The object ID in the MapProfile dict points to the AllowedAttributeValue object.
However, I don't seem to be able to figure out, how to add multiple values to the field.
Can anybody give a hint? Or does pyral not support multi-value fields?
Thanks
Thomas
I'm not familiar with the pyral toolkit, but I can say the api expects the data in a certain shape.
'c_MapProfile':[
{'_ref':'/allowedattributevalue/123'},
{'_ref':'/allowedattributevalue/124'}]
I believe you can retrieve the allowed values for your custom field using the getAllowedValues function
Keep in mind this will overwrite any existing values. If you only wish to add or remove entries without overwriting the current value - use the collection endpoints as explained in the CA Agile Central Web Services API Documentation
I am trying to use flask-admin, which seems great and easy, but I have a problem.
I have a field in a collection which is defined as a ListField(), with an implicit type of None for the list field type. The reason I am not defining a type for the field, is because I am keeping a list of lists, and there is no other elegant way (that I found) to accomplish this with mongoengine.
But flask-admin won't let me define such a field, with an error of ListField "movements" must have field specified for model.
Is there a way around this?
The reason flask admin needs a field specified is because otherwise the form rendering does not know which type of input to display for it.
For example if it is a choice field, date field, or another list field itself !
You could do something like this:
my_field = db.ListField(field=db.ListField(field=db.StringField()))
The innermost field can be anything, including a EmbeddedDocumentField or IntField, etc.
Also, if you want to continue using ListField without specifying the field type, you can also ask flask-admin to just treat this as a string by overriding the ModelView and it will then just give you a text box containing the string:
[ 'a value', 42, { 'A':'B' } ]
So this retains flexibility but reduces structure and makes the validation bad.
I saw this code segment in subscription.py class. It gives selection and many2one fields together for users. I found in openerp documentation and another modules also but i never found any details or other samples for this
here is the its view
here is the code related to that field
'doc_source': fields.reference('Source Document', required=True, selection=_get_document_types, size=128),
here is the selection part function code
def _get_document_types(self, cr, uid, context=None):
cr.execute('select m.model, s.name from subscription_document s, ir_model m WHERE s.model = m.id order by s.name')
return cr.fetchall()
I Need to know that; can we make our own fields.reference type fields.?
another combination instead of MODEL,NAME..?
In the OpenERP framework a fields.reference field is a pseudo-many2one relationship that can target multiple models. That is, it contains the name of the target model in addition to the foreign key, so that each value can belong to a different table. The user interface first presents a drop-down where the user selects the target document model, and then a many2one widget in which they can pick the specific document from that model.
You can of course use it in your own modules, but it will always behave in this manner.
This is typically used for attaching various documents (similarly to attachments except the target is another record rather than a file). It's also used in some internal OpenERP models that need to be attached to different types of record, such as properties (fields.property values) that may belong to any record.
The fields.reference constructor takes 3 main parameters:
'doc': fields.reference('Field Label', selection, size)
where selection contains the list of document models from which values can be selected (e.g Partners, Products, etc.), in the same form as in a fields.selection declaration. The key of the selection values must be the model names (e.g. 'res.partner').
As of OpenERP 7.0 the size parameter should be None, unless you want to specifically restrict the size of the database field where the values will be stored, which is probably a bad idea. Technically, fields.reference values are stored as text in the form model.name,id. You won't be able to use these fields in a regular SQL JOIN, so they won't behave like many2one fields in many cases.
Main API calls
When you programmatically read() a non-null reference value you have to split it on ',' to identify the target model and target ID
When you programmatically write() a non-null reference value you need to pass the 'model.name,id' string.
When you search() for a non-null reference value you need to search for the 'model.name,id' string (e.g. in a search domain)
Finally, when you browse() through a reference value programmatically the framework will automatically dereference it and follow the relationship as with a regular many2one field - this is the main exception to the rule ;-)
I created a new property for my db model in the Google App Engine Datastore.
Old:
class Logo(db.Model):
name = db.StringProperty()
image = db.BlobProperty()
New:
class Logo(db.Model):
name = db.StringProperty()
image = db.BlobProperty()
is_approved = db.BooleanProperty(default=False)
How to query for the Logo records, which to not have the 'is_approved' value set?
I tried
logos.filter("is_approved = ", None)
but it didn't work.
In the Data Viewer the new field values are displayed as .
According to the App Engine documentation on Queries and Indexes, there is a distinction between entities that have no value for a property, and those that have a null value for it; and "Entities Without a Filtered Property Are Never Returned by a Query." So it is not possible to write a query for these old records.
A useful article is Updating Your Model's Schema, which says that the only currently-supported way to find entities missing some property is to examine all of them. The article has example code showing how to cycle through a large set of entities and update them.
A practice which helps us is to assign a "version" field on every Kind. This version is set on every record initially to 1. If a need like this comes up (to populate a new or existing field in a large dataset), the version field allows iteration through all the records containing "version = 1". By iterating through, setting either a "null" or another initial value to the new field, bump the version to 2, store the record, allows populating the new or existing field with a default value.
The benefit to the "version" field is that the selection process can continue to select against that lower version number (initially set to 1) over as many sessions or as much time is needed until ALL records are updated with the new field default value.
Maybe this has changed, but I am able to filter records based on null fields.
When I try the GQL query SELECT * FROM Contact WHERE demo=NULL, it returns only records for which the demo field is missing.
According to the doc http://code.google.com/appengine/docs/python/datastore/gqlreference.html:
The right-hand side of a comparison can be one of the following (as
appropriate for the property's data type): [...] a Boolean literal, as TRUE or
FALSE; the NULL literal, which represents the null value (None in
Python).
I'm not sure that "null" is the same as "missing" though : in my case, these fields already existed in my model but were not populated on creation. Maybe Federico you could let us know if the NULL query works in your specific case?