[web2py] Re: Validation on all fields when updating only certain specific fields?
If I don't want to see certain fields I suggest something like this: rec = db.thing(request.args(0)) db.thing.firstUserId.readable = db.thing.firstUserId.writable= False form = SQLFORM(db.thing, rec) But if that's not what you mean, take a look at the hidden parameter for SQLFORM too. e.g. hiddenfields = { 'firstUserId' : 1, 'secondUserId' : 2, 'thirdUserId' : 3 } form = SQLFORM(db.thing, rec, hidden=hiddenfields) Hope the above at least gives you something new to try. Regards, David --
[web2py] Re: Validation on all fields when updating only certain specific fields?
Are you saying you want to create a single form object on the server side that includes all the fields, but on the client side you want to break that up into several distinct forms, each of which would only submit one of the fields? If so, I'm not sure that's a common enough use case to warrant re-vamping how SQLFORM works. In this case, maybe you could do something like this: fields = [f for f in request.post_vars if f in db.thing.fields] if request.post_vars else None form = SQLFORM(db.thing, fields=fields, ...) When the form is created, fields will be None, so all fields will be included, but when a form is submitted, fields will include only the submitted field. Anthony On Thursday, June 21, 2012 5:11:32 PM UTC-4, Osman Masood wrote: Hey all, Was just wondering about thiscurrently web2py re-runs the form validations for every single field, even if you only update one field. For example, in the models file: db.define_table('user', format = '%(id)s') db.define_table('thing', Field('name', length=100), Field('type', length=100), Field('size', length=100), Field('firstUserId', db.user), Field('secondUserId', db.user), Field('thirdUserId', db.user), format = '%(type)s' ) So now, if I want make a form to only update thing.type, it will return a form error unless I also supply the firstUserId, secondUserId, and thirdUserId fields. This is because foreign field references have a validation for IS_IN_DB by default. I can work around this by making their input fields hidden, but isn't that a bit of a hassle? If I have a page that has separate forms for thing.name, thing.type, thing.size, thing.firstUserId, etc., (because they are on different parts of the page, and there are forms for other tables in between), then I have to redundantly enter all the hidden userId fields for each form. For example, if I want to have a form that just updates 'type', currently I have to do: form name=thing input name=type type=text value={{=thing.type}} / input name=firstUserId type=hidden value={{=thing.firstUserId}} / input name=secondUserId type=hidden value= {{=thing.secondUserId}} / input name=thirdUserId type=hidden value={{=thing.thirdUserId}} / input name=_formname type=hidden value=thing / input name=id type=hidden value={{=thing.id}} / /form I know there is a way around this by setting the 'fields' attribute in SQLFORM, but what if I want to update firstUserId, secondUserId, or thirdUserId using the same SQLFORM? Then I'd have to make a SQLFORM for each of firstUserId, secondUserId, and thirdUserId. So, in total, I'd have at least 4 almost-identical SQLFORMs in the same controller action. This is just an example, but you can see how in a real-world application this could get lead to a lot of duplicate code and get pretty messy. If web2py only performed validations on the fields that are being updated (instead of on every field), then this problem would be solved, and much duplicate code would be avoided. Also, the code would run faster, especially in cases where there are many fields and validations need to be done on every one of them. What do you guys think? Thanks --
[web2py] Re: Validation on all fields when updating only certain specific fields?
Thanks for all the help. I tried using a 'hidden' field but it still gives me the same error. This is my SQLFORM: candidate_form = SQLFORM(db.candidate, candidate_record, hidden={'ownerUserId': candidate_record.ownerUserId}) If I print candidate_record.ownerUserId, it returns 1 (successfully). If I print candidate_form.vars.ownerUserId (after creating the SQLFORM), it returns None (which I think is correct). The validation for ownerUserId is as follows: db.candidate.ownerUserId.requires = IS_IN_DB(db, 'user.id', db.user._format) db.candidate.ownerUserId.required = True Yet, still, when I submit the form and only change the name, it gives me a ownerUserId value not in database error. Here's my form: form name=candidate input type=text class=editable name=firstName readonly=readonly value={{= candidate.firstName }} / input type=text class=editable name=middleName readonly=readonly value={{= candidate.middleName }} / input type=text class=editable name=lastName readonly=readonly value={{= candidate.lastName }} / input type=hidden name=id value={{= candidate.id }} / input type=hidden name=_formname value=candidate / /form Any help is greatly appreciated, guys. If I can't get this thing to work, I'll use Anthony's one-liner (which was a beautiful piece of code by the way). I'll probably have to use it anyway, but I really want to know why this form validation doesn't work. Thanks! On Thursday, June 21, 2012 3:59:25 PM UTC-7, Anthony wrote: Are you saying you want to create a single form object on the server side that includes all the fields, but on the client side you want to break that up into several distinct forms, each of which would only submit one of the fields? If so, I'm not sure that's a common enough use case to warrant re-vamping how SQLFORM works. In this case, maybe you could do something like this: fields = [f for f in request.post_vars if f in db.thing.fields] if request .post_vars else None form = SQLFORM(db.thing, fields=fields, ...) When the form is created, fields will be None, so all fields will be included, but when a form is submitted, fields will include only the submitted field. Anthony On Thursday, June 21, 2012 5:11:32 PM UTC-4, Osman Masood wrote: Hey all, Was just wondering about thiscurrently web2py re-runs the form validations for every single field, even if you only update one field. For example, in the models file: db.define_table('user', format = '%(id)s') db.define_table('thing', Field('name', length=100), Field('type', length=100), Field('size', length=100), Field('firstUserId', db.user), Field('secondUserId', db.user), Field('thirdUserId', db.user), format = '%(type)s' ) So now, if I want make a form to only update thing.type, it will return a form error unless I also supply the firstUserId, secondUserId, and thirdUserId fields. This is because foreign field references have a validation for IS_IN_DB by default. I can work around this by making their input fields hidden, but isn't that a bit of a hassle? If I have a page that has separate forms for thing.name, thing.type, thing.size, thing.firstUserId, etc., (because they are on different parts of the page, and there are forms for other tables in between), then I have to redundantly enter all the hidden userId fields for each form. For example, if I want to have a form that just updates 'type', currently I have to do: form name=thing input name=type type=text value={{=thing.type}} / input name=firstUserId type=hidden value= {{=thing.firstUserId}} / input name=secondUserId type=hidden value= {{=thing.secondUserId}} / input name=thirdUserId type=hidden value= {{=thing.thirdUserId}} / input name=_formname type=hidden value=thing / input name=id type=hidden value={{=thing.id}} / /form I know there is a way around this by setting the 'fields' attribute in SQLFORM, but what if I want to update firstUserId, secondUserId, or thirdUserId using the same SQLFORM? Then I'd have to make a SQLFORM for each of firstUserId, secondUserId, and thirdUserId. So, in total, I'd have at least 4 almost-identical SQLFORMs in the same controller action. This is just an example, but you can see how in a real-world application this could get lead to a lot of duplicate code and get pretty messy. If web2py only performed validations on the fields that are being updated (instead of on every field), then this problem would be solved, and much duplicate code would be avoided. Also, the code would run faster, especially in cases where there are many fields and validations need to be done on every one of them. What do you guys think? Thanks --
[web2py] Re: Validation on all fields when updating only certain specific fields?
candidate_form = SQLFORM(db.candidate, candidate_record, hidden={'ownerUserId': candidate_record.ownerUserId}) input type=hidden name=id value={{= candidate.id }} / First, shouldn't that be name=ownerUserId and candidate.ownerUserId? Note, hidden fields are not really part of the form object and do not get processed with the other form fields. They are merely added to the HTML when the form is serialized in the view so the hidden field values come back with the form submission. It is then up to you to do whatever you want with those values manually. If you want them to be processed as regular fields of the database table, I think you could do something like: candidate_form = SQLFORM(db.candidate, candidate_record, hidden=dict(ownerUserId=candidate_record.ownerUserId)) candidate_form.vars.ownerUserId = request.vars.ownerUserId candidate_form.process() Anyway, I think the other method might be better because you don't have to bother including and manually manipulating hidden fields, and it won't unnecessarily run validators on the non-updated fields. Anthony --
[web2py] Re: Validation on all fields when updating only certain specific fields?
Awesome, thanks for the clarification, Anthony. I thought hidden fields were normal fields processed by SQLFORM. I used the code you gave me and it works great...hope others can benefit from it too. Thanks On Thursday, June 21, 2012 6:33:29 PM UTC-7, Anthony wrote: candidate_form = SQLFORM(db.candidate, candidate_record, hidden={'ownerUserId': candidate_record.ownerUserId}) input type=hidden name=id value={{= candidate.id }} / First, shouldn't that be name=ownerUserId and candidate.ownerUserId? Note, hidden fields are not really part of the form object and do not get processed with the other form fields. They are merely added to the HTML when the form is serialized in the view so the hidden field values come back with the form submission. It is then up to you to do whatever you want with those values manually. If you want them to be processed as regular fields of the database table, I think you could do something like: candidate_form = SQLFORM(db.candidate, candidate_record, hidden=dict(ownerUserId=candidate_record.ownerUserId)) candidate_form.vars.ownerUserId = request.vars.ownerUserId candidate_form.process() Anyway, I think the other method might be better because you don't have to bother including and manually manipulating hidden fields, and it won't unnecessarily run validators on the non-updated fields. Anthony --