'Update a record
@param r: the S3Request
@param attr: dictionary of parameters for the method handler'

def update(self, r, **attr):

    resource = self.resource
    table = resource.table
    tablename = resource.tablename
    representation = r.representation
    output = dict()
    _config = self._config
    editable = _config('editable', True)
    onvalidation = (_config('update_onvalidation') or _config('onvalidation'))
    onaccept = (_config('update_onaccept') or _config('onaccept'))
    record_id = self.record_id
    if (r.interactive and (not record_id)):
        r.error(404, current.ERROR.BAD_RECORD)
    if (not editable):
        if r.interactive:
            return self.read(r, **attr)
        else:
            r.error(405, current.ERROR.METHOD_DISABLED)
    authorised = self._permitted(method='update')
    if (not authorised):
        r.unauthorised()
    if (r.interactive or (representation == 'plain')):
        response = current.response
        s3 = response.s3
        subheadings = _config('subheadings')
        if (representation == 'html'):
            response.view = self._view(r, 'update.html')
        elif (representation in 'popup'):
            response.view = self._view(r, 'popup.html')
        elif (representation == 'plain'):
            response.view = self._view(r, 'plain.html')
        elif (representation == 'iframe'):
            response.view = self._view(r, 'iframe.html')
        crud_string = self.crud_string
        if r.component:
            title = crud_string(r.tablename, 'title_display')
            subtitle = crud_string(self.tablename, 'title_update')
            output['title'] = title
            output['subtitle'] = subtitle
        else:
            title = crud_string(self.tablename, 'title_update')
            output['title'] = title
        output['title_list'] = crud_string(tablename, 'title_list')
        link = None
        if r.component:
            if (resource.link is None):
                link = self._embed_component(resource, record=r.id)
                pkey = resource.pkey
                fkey = resource.fkey
                field = table[fkey]
                value = r.record[pkey]
                field.comment = None
                field.default = value
                field.update = value
                if (r.http == 'POST'):
                    r.post_vars.update({fkey: value})
                field.readable = False
                field.writable = False
            else:
                link = Storage(resource=resource.link, master=r.record)
        message = crud_string(self.tablename, 'msg_record_modified')
        self._interim_save_button()
        if ((r.representation == 'html') and ((r.method == 'update') or (not r.method))):
            self._default_cancel_button(r)
        try:
            form = self.sqlform(request=self.request, resource=resource, record_id=record_id, onvalidation=onvalidation, onaccept=onaccept, message=message, link=link, subheadings=subheadings, format=representation)
        except HTTP as e:
            message = (current.ERROR.BAD_RECORD if (e.status == 404) else e.message)
            r.error(e.status, message)
        if self.settings.navigate_away_confirm:
            s3.jquery_ready.append('S3EnableNavigateAwayConfirm()')
        output['form'] = form
        if (representation == 'plain'):
            output['item'] = form
            output['title'] = ''
        buttons = self.render_buttons(r, ['delete'], record_id=record_id, **attr)
        if buttons:
            output['buttons'] = buttons
        last_update = self.last_update()
        if last_update:
            try:
                output['modified_on'] = last_update['modified_on']
            except:
                pass
            try:
                output['modified_by'] = last_update['modified_by']
            except:
                pass
        from s3merge import S3Merge
        output['deduplicate'] = S3Merge.bookmark(r, tablename, record_id)
        if ((r.http == 'POST') and ('interim_save' in r.post_vars)):
            next_vars = self._remove_filters(r.get_vars)
            self.next = r.url(target='[id]', method='update', vars=next_vars)
        else:
            update_next = _config('update_next')
            if (representation in ('popup', 'iframe', 'plain', 'dl')):
                self.next = None
            elif (not update_next):
                next_vars = self._remove_filters(r.get_vars)
                if r.component:
                    self.next = r.url(method='', vars=next_vars)
                else:
                    self.next = r.url(id='[id]', method='read', vars=next_vars)
            else:
                try:
                    self.next = update_next(self)
                except TypeError:
                    self.next = update_next
    elif (representation == 'url'):
        return self.import_url(r)
    else:
        r.error(415, current.ERROR.BAD_FORMAT)
    return output
