How to handle delete in Google App Engine (Python)
Asked Answered
F

2

9

I'm a newbie programmer and new to Google App Engine and webapp2 etc. So this may be a very basic question.

I am creating an application to store images into BlobStore. My model stores description, blob_key, image url and date.

I am able to save everything, so that bit is okay.

But now I want to create a delete button which will not only delete an item from the datastore, but also delete the image saved in the blobstore.

I have created a DeleteHandler, and in the html I have a form, passing the key for the item I want to delete. In the DeleteHandler, I am using the posted key to delete the item from the datastore. I am also trying to use the key to use it delete the image saved in the blobstore.

So far I'm getting a 404 on the delete form post, and even if I get past that, I'm not sure if my DeleteHandler is correct to handle the functionality I am looking for.

Any help would be much appreciated..

Main.py:

import os
import urllib
import webapp2
from google.appengine.ext.webapp import template
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import images
#Models
from google.appengine.ext import db

class ImageItem(db.Model):
    description = db.StringProperty(required=True)
    img_url = db.StringProperty()
    blob_key = blobstore.BlobReferenceProperty()
    when = db.DateTimeProperty(auto_now_add=True)


#Handlers (Views)
class MainHandler(webapp2.RequestHandler):
  def get(self):
    upload_url = blobstore.create_upload_url('/upload')
    imgs = db.GqlQuery(
        'SELECT * FROM ImageItem '
        'ORDER BY when DESC')
    imgs_dict = {'imgs': imgs}
    self.response.out.write( template.render( 'main.html',locals() ) )

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    f = self.get_uploads('file')[0]  # 'file' is file upload field in the form
    img =ImageItem(description=self.request.get('description'))
    img.blob_key = f.key()
    img.img_url = images.get_serving_url( f.key() )
    img.put()
    self.redirect('/')

class DeleteHandler(webapp2.RequestHandler):
    def post(self):
        key = self.request.get('k')
        item = db.get(key)
        images.delete( item.blob_key )
        item.delete()
        self.response.out.write(key)

#URL Routing happens here
app = webapp2.WSGIApplication([('/', MainHandler),
                               ('/upload', UploadHandler),
                               ('/delete', DeleteHandler)],
                              debug=True)

Main.html:

<form action="{{upload_url}}" method="POST" enctype="multipart/form-data">
            <p>
                <label for="file">Upload File</label>
                <input type="file" name="file" id="file">
            </p>
            <p>
                <label for="description">Description</label>
                <input type="text" id="description" name="description">
            </p>
            <input type="submit" name="submit" value="Submit"> 
    </form>

    <ul>
        {% for i in imgs %}
        <li>
            <img src="{{i.img_url}}=s400-c" alt="">
            {{i.description }}
            </li>

        <li>{{i.when }}</li>
        <li>
            <form action="/delete" method="POST"  enctype="multipart/form-data">
                <input type="text" name="k" value="{{i.key}}" />
                <input type="submit" value="delete">
            </form>

        </li>
        {% endfor %}
    </ul>
Foamy answered 17/11, 2012 at 15:39 Comment(0)
B
6

The deletes are close. Once you have a key, you can delete entities by calling db.delete(key).
For your example, this would be something like this:

class DeleteHandler(webapp2.RequestHandler):
    def post(self):
        key = self.request.get('k')
        item = db.get(key)
        blobstore.delete([item.blob_key])
        db.delete(item)
        self.response.out.write(key)


Your url handling in main.py is good, so it's not obvious to me why you're getting a 404. You could double-check your app.yaml file to make sure all urls are passed to main.py.
Here's a sample app.yaml handlers url section:

handlers
- url: /.*
    script: main.app


Bis answered 21/11, 2012 at 13:34 Comment(3)
Thanks for your help with this Eric. It's almost working now, except the item is not being deleted from the blobstore. I've tried blobstore.delete(item.key) and blobstore.delete([item.key]). Neither seem to do the trickFoamy
I see in your next post that you figured it out. Glad you got it working. Thanks for replying and letting us know the details.Bis
Thanks Eric, marking your answer with a tick, seeing as you pointing out to use blobstore.delete(KEY) was a major part of figuring this outFoamy
F
1

Got it to work. Thanks Eric, yours was real close. I needed to use blob_key.key().

Final code is following:

class DelHandler(webapp2.RequestHandler):
  def post(self):
    key = self.request.get('k')
    item = db.get(key)
    n = item.blob_key.key() 
    blobstore.delete(n)
    item.delete()
    self.redirect('/')
Foamy answered 23/11, 2012 at 16:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.