def update(self, r, **attr):
        """
            Update a record

            @param r: the S3Request
            @param attr: dictionary of parameters for the method handler
        """

        resource = self.resource
        table = resource.table
        tablename = resource.tablename

        representation = r.representation

        output = dict()

        # Get table configuration
        _config = self._config
        editable = _config("editable", True)

        # Get callbacks
        onvalidation = _config("update_onvalidation") or \
                       _config("onvalidation")
        onaccept = _config("update_onaccept") or \
                   _config("onaccept")

        # Get the target record ID
        record_id = self.record_id
        if r.interactive and not record_id:
            r.error(404, current.ERROR.BAD_RECORD)

        # Check if editable
        if not editable:
            if r.interactive:
                return self.read(r, **attr)
            else:
                r.error(405, current.ERROR.METHOD_DISABLED)

        # Check permission for update
        authorised = self._permitted(method="update")
        if not authorised:
            r.unauthorised()

        if r.interactive or representation == "plain":

            response = current.response
            s3 = response.s3

            # Form configuration
            subheadings = _config("subheadings")

            # Set view
            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")

            # Title and subtitle
            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")

            # Component join
            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)

            # Success message
            message = crud_string(self.tablename, "msg_record_modified")

            # Interim save button
            self._interim_save_button()

            # Default Cancel Button
            if r.representation == "html" and \
               (r.method == "update" or not r.method):
                self._default_cancel_button(r)

            # Get the form
            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, e:
                message = current.ERROR.BAD_RECORD \
                          if e.status == 404 else e.message
                r.error(e.status, message)

            # Navigate-away confirmation
            if self.settings.navigate_away_confirm:
                s3.jquery_ready.append("S3EnableNavigateAwayConfirm()")

            # Put form into output
            output["form"] = form
            if representation == "plain":
                output["item"] = form
                output["title"] = ""

            # Add delete and list buttons
            buttons = self.render_buttons(r,
                                          ["delete"],
                                          record_id=record_id,
                                          **attr)
            if buttons:
                output["buttons"] = buttons

            # Last update
            last_update = self.last_update()
            if last_update:
                try:
                    output["modified_on"] = last_update["modified_on"]
                except:
                    # Field not in table
                    pass
                try:
                    output["modified_by"] = last_update["modified_by"]
                except:
                    # Field not in table, such as auth_user
                    pass

            # De-duplication
            from s3merge import S3Merge
            output["deduplicate"] = S3Merge.bookmark(r, tablename, record_id)

            # Redirection
            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

    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/s3crud.py/S3CRUD.update/original