0
votes

I'm trying to understand how to edit or update a model. I have tried several scenarios which sometimes give an error message: 405 Method Not Allowed - The method POST is not allowed for this resource. Below is my code:

The Python Models:

import os 
import webapp2
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext.webapp import template

class MessageModel(db.Model):
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)

class Message(webapp2.RequestHandler):

    def get(self):
        doRender(self,'message.htm')

    def post(self):
        m = MessageModel()
        m.content = self.request.get('content')
        m.put()

        self.redirect('/view') 

class View(webapp2.RequestHandler):

    def get(self):

        que = db.Query(MessageModel)
        messageview_list = que.fetch(999)

        doRender(self,
                 'view.htm', 
                 {'messageview_list': messageview_list })


class Edit(webapp2.RequestHandler):

    def get(self):

        doRender(self,'edit.htm')    

    def post(self):

        updated_content = self.request.get('content')

        content_query = db.GqlQuery("SELECT * "
                                   "FROM MessageModel "
                                   "ORDER BY date DESC LIMIT 1")

        messageview_list = content_query.fetch(1)
        m = MessageModel()
        m.content = self.request.get(updated_content)
        m.put()

        doRender(self,
                 'edit.htm', 
                 {'messageview_list': messageview_list })


class Main(webapp2.RequestHandler):

    def get(self):
        doRender(self,'index.htm')


def doRender(handler, tname = 'index.htm', values = { }):
    temp = os.path.join(
    os.path.dirname(__file__),
    'templates/' + tname)
    if not os.path.isfile(temp):
    return False

    newval = dict(values)
    newval['path'] = handler.request.path

    outstr = template.render(temp, newval)
    handler.response.out.write(outstr)
    return True




app = webapp2.WSGIApplication([('/', Main),
                   ('/message', Message),
                   ('/view', View),                                                                          
                   ('/edit', Edit)], 
                   debug=True)

The HTML Form:

{% for messageview in messageview_list %}

<form method="post" action="/edit">
    <p>
        <textarea name="message" rows="3" cols="60" MAXLENGTH=60>
        {{ messageview.content }}</textarea>
        <br>
        <input type="submit" value="Update"/> 
      </p>
</form>
      {% ifnotequal error None %}
       <p>
       {{ error }}
       </p>
      {% endifnotequal %}
{% endfor %}
1
I do not understand your code. How do you start your application? How does the url look like, which results in a GET? Have you looked in your resulting HTML after the GET? - voscausa
what's the question? If you have a handler defined for POST requests then your app can deal with them. If you don't then you'll get the error you note. But what is the actual problem? Perhaps post your handler mapping code? - Paul Collingwood
I edit my post - and replace it with whole edit.py hope that someone can explain me how the function to edit ore update a POST works - Hendrikus Godvliet

1 Answers

0
votes

I am assuming the indentation is due to copy/paste, but make sure that the post() and get() functions are actually indented inside of your class.

In your form, you have <textarea name="message" rows="3" cols="60" MAXLENGTH=60>, but in your def post() you use updated_content = self.request.get('content'), which is looking for the content keyword in the request. Also, your edit doesn't look like it is doing what you want it to do. In order to edit an entity, the basic outline of the process is 1.) Retrieve the entity (so do as you do, query using some parameter); 2.) Modify the properties of the entity however you want; and 3.) put() the entity back in the datastore.

From your code, it looks like you are retrieving the last entity entered into the datastore, but then creating a new model instead of editing that one (assuming that is what you want to do - not quite sure if that is accurate :) ). If you are looking to modify the entity that is returned, this should work:

def post(self):

    updated_content = self.request.get('message')
    content_query = db.GqlQuery("SELECT * "
                               "FROM MessageModel "
                               "ORDER BY date DESC LIMIT 1")

    # Your query will always return just one entity (due to the LIMIT),
    # but you can use get() here instead of fetch(1)
    latest_model = content_query.get()

    # Update the model's content property
    latest_model.content = updated_content
    latest_model.put()

    # Assuming you want to output that model, you'd output it now
    doRender(self,
             'edit.htm', 
             {'messageview_list': latest_model })