Your code can be simplified as follows:
This is incorrect:
   form.vars.user.writable = False
I assume you mean:
   db.services.user.writable = False

It is not a good idea to define a form in a if block, i.e. in a
different scope than the the form.accepts. Try this instead:

@auth.requires_login()
def services():
    record = db.services(user=auth.user.id) # returns None if record
not found
    db.services.user.writable = False
    db.services.user.default = auth.user.id
    form = SQLFORM(db.services, record, deletable=False) # update or
create depending on record
    if form.accepts(request.vars, session):
         response.flash = 'form accepted'
    elif form.errors:
         response.flash = 'form has errors'
    return dict(form=form)


On Aug 22, 3:48 pm, Niphlod <[email protected]> wrote:
> usually I'll do something like that:
>
> 1. @auth.requires_login()
> 2. def services():
> 3.    record = db(db.services.user==auth.user.id).select().first()
> 4.    if record:
> 5.        form = SQLFORM(db.services, record, deletable=False)
> 6.        form.vars.user.writable = False
> 7.    else:
> 8.        form = SQLFORM(db.services)
> 9.        form.vars.user.default = auth.user.id
> 10.        form.vars.user.writable = False
> 11.    if form.accepts(request.vars, session):
> 12.        response.flash = 'form accepted'
> 13.    elif form.errors:
> 14.        response.flash = 'form has errors'
> 15.    return dict(form=form)
>
> changes made to your implementation:
> a) request.args are needed to catch something "after" something/
> default/services ... that line is copy/pasted from the book but in
> your context it doesn't mean anything...actually the URL with that is
> needed to be like something/default/services/xxx where xxx is an
> identifier of the record to edit. Since you want only one record per
> user, request.args use is meaningless.
>
> so, "if len(request.args)" is missing totally.
>
> b) if there's only one record per user, you can select directly the
> row with .first() , no need to retain the set (multiple rows object)
> if there aren't going to be multiple records per user.
> .first() return a row or None if non-existent, hence the "if record:"
> on line 4.
>
> c) if record exists, form will be "editable" of the row "record" (with
> records[1] you were doing quite a mess....actually selecting the 2nd
> row of your set, python enumeration starts from [0], not from
> [1]!!) .
> on line 6. and 10. "form.vars.user.writable = False" give yourself
> some protection .... actually if you don't do this you'll end up
> giving away the chance to your users to change the "user" field,
> "assigning" his "services" row to another user.... definitely not the
> way to go. I'll be happy to set also form.vars.user.readable = False
> to hide the field at all, but that's your choice.
>
> Feel free to ask more if you're concerned by something or if you
> didn't understand all.
>
> Niphlod

Reply via email to