tornado dont accept the POST method - python

i get the 405: Method Not Allowed, so where is the problem, it's a
post method since i want to send data to the server
class VendreHandler(BaseHandler):
#tornado.web.authenticated
def post(self):
self.db = conn["essog"]
user = self.get_secure_cookie("mechtari")
info = tornado.escape.json_decode(user)
email = info["email"]
namep = self.get_argument("namep")
prix = self.get_argument("prix")
description = self.get_argument("description")
date = datetime.datetime.now().date()
try:
photo = self.request.files['photo'][0]["body"]
try:
avctype = self.request.files['avatar'][0]["content_type"]
image = Image.open(StringIO.StringIO(buf=avat))
type = image.format
(x, y) = image.size
if x < y:
orientation = "portrait"
else:
orientation = "paysage"
pref = str(time.time())
nomfi = pref.replace(".", "")
nomfich = nomfi + "-" + self.request.files['avatar'][0]["filename"]
self.fs = GridFS(self.db)
avatar_id = self.fs.put(avat, content_type=avctype,filename=nomfich)
except IOError, TypeError:
self.redirect("/error-im")
except KeyError:
nomfich = "nofile"
orientation = "paysage"
avctype = "image/jpeg"
avatar_id = '503ae8553a5f3a0dd8b9cb4c'
self.db.users.update({"email":email}, {"$set":{"produit_up.namep":namep,"produit_up.prix":prix,"produit_up.photo":photo_id, "produit_up.description":description,"produit_up.date":date, "produit_up.vendu":False}})
self.redirect("/success")
and the template:
<form id="formvente" name="formvente" method="post" action="/vendre" enctype="multipart/form-data">
{% raw xsrf_form_html() %}
<label for="namep">Le nom du Produit</label>
<input type="text" name="namep" required title="vous devez mettre le nom du produit" placeholder="exemple: peugeot 206">
<label for="prix">Son prix (en Dinars Algérien)</label>
<input type="number" name="prix" required title="vous devez mettre le prix en chiffre (en Dinars Algérien)" placeholder="exemple: 800000">
<label for="photo">Une photo de votre produit</label>
<input name="photo" type="file">
<label for="description">Veuillez donner une déscription du produit (maximum 160 caractères)</label>
<textarea name="description" id="description" rows="3" cols="60" required title="vous devez mettre une petite description" placeholder="escence, 2006, roulant 100000km, toutes options, siege en cuir" onKeyDown="textCounter(document.formvente.description,160)" onKeyUp="textCounter(document.formvente.description, 160)"></textarea>
<meter name="shower" min="1" max="160" value="1"id="shower" low="30" high="140">afficher son etat</meter>
<input id="vendre" type="submit" value="Mettre en Vente"/>
</form>
and i have simplified the handler to this
class VendreHandler(tornado.web.RequestHandler):
def post(self):
namep = 1
prix = 3
description = 43
date = 345
self.db = conn["essog"]
self.db.users.update({"email":email}, {"$set":{"produit_up.namep":namep,"produit_up.prix":prix, "produit_up.photo":photo_id, "produit_up.description":description,"produit_up.date":date, "produit_up.vendu":False}})
self.redirect("/profil#vendu")
always the method error it dident check the handler content at all
(else it raised and error when not finding email)!
NB: is it because i've used the accodion effect (CSS3)? the page contains 3 parts: the profile, upload product, and search for product, and of course every part has its own handler; so the profile will call
a GET to get the user information and the avatar, and the upload product will make a POST to write product information to the server, and finally the search will make a GET to the server to search for the product.
so, am i making mistake?

SOLVED!
it seems that the problem is coming from the picture handler; in the URLSpec, IT MUST BE THE LAST ONE IN THE LIST
url = [
...,
...,
...,
(r"/(?P<picture>.*)", handlers.PictureHandler)]
this is why when using GET method return errors concerning picture!
hope this will help, and thank you :)

Related

MultiValueDictKeyError when passing empty file

In my website uploading picture is not compulsory, Therefore when left empty I get
MultiValueDictKeyError
But if i pass an image is dont get an error.
Am I missing some thing?? Thanks in advance....
views.py
if request.method == "POST":
FirstName = request.POST['FirstName']
LastName = request.POST['LastName']
image = request.FILES['image'] #This one
age = request.POST['age']
gender = request.POST['gender']
address = request.POST['address']
PhoneNumber = request.POST['PhoneNumber']
EmailAddress = request.POST['EmailAddress']
Password = request.POST['Password']
RepeatPassword = request.POST['RepeatPassword']
BloodGroup = request.POST['BloodGroup']
try:
if Password == RepeatPassword:
Patient.objects.create(FirstName=FirstName, LastName=LastName, image=image, age=age, gender=gender,
address=address, PhoneNumber=PhoneNumber, EmailAddress=EmailAddress, BloodGroup=BloodGroup)
return redirect('login')
else:
messages.success(
request, ("Passwords do not match. Please try again"))
except Exception as e:
messages.success(
request, ("This email already exists. Try again with another email or recover your account"))
return render(request, 'signup.html')
HTML
<div class="input-div one">
<div class="i">
<ion-icon name="image-sharp"></ion-icon>
</div>
<div class="div">
<h5>Photo</h5>
<input type="file" class="input" name="image">
</div>
</div>
Use .get() instead, i.e:
image = request.FILES.get('image')
It will resolve to None if it can't find it. You can set the default to something else with:
image = request.FILES.get('image', "New default that isn't None")
See: https://www.w3schools.com/python/ref_dictionary_get.asp

Django search "DoesNotExist"

I'm using Django to build a website for a football club, which contains many blog articles. I'm trying to include a search bar, but I can't make it work. When submitting the search term, the following error is shown:
DoesNotExist at /web/search/
Articulo matching query does not exist.
Here is my code:
views.py
def search(request):
query = request.GET.get('q', '')
if query:
try:
qset = (
Articulo(titulo__icontains=query) |
Articulo(cuerpo_icontains=query)
)
results = Articulo.objects.filter(qset).distinct()
except Articulo.DoesNotExist:
results = None
else:
results = []
return render_to_response('web/buscar.html', {"results": results, "query": query})
index.html
<div id="busqueda" class="row">
<div class="col-md-12">
<span id="cruz" class="fas fa-times fa-2x"></span>
<form method="GET" action="/web/search/" class="form my-2 my-lg-0">
<input id="searchBox" value="{{ query|escape }}" class="form-control mr-sm-2" type="text" name="q" placeholder="Buscar" aria-label="Buscar">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Buscar</button>
</form>
</div>
</div>
urls.py
url(r'^search/$', search),
models.py
class Articulo(models.Model):
"""Un artículo de la página"""
id = models.AutoField(primary_key=True)
titulo = models.CharField(max_length=100)
slug = models.SlugField(unique=True, default="")
CATEGORIAS = (
('Primera y Sub 21', 'Primera y Sub 21'),
('Inferiores', 'Inferiores'),
('Básquet', 'Básquet'),
('Hockey', 'Hockey'),
('Gurises', 'Gurises'),
('Generales', 'Generales'),
('Institucionales', 'Institucionales'),
('Senior', 'Senior'),
)
categoria = models.CharField(
max_length=200,
choices=CATEGORIAS
)
cuerpo = RichTextField()
fecha_hora= models.DateTimeField()
foto = models.ImageField()
url_video = models.CharField(help_text='Url del video de facebook (opcional). Para obtener el link, ir al video, apretar donde están los 3 puntitos y poner "insertar". Pegar aquí solo el link del video, borrar el resto. Ejemplo: https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FJuanCruzPiornoOficial%2Fvideos%2F302760100205413', max_length=500,blank=True)
album_flickr = models.CharField(help_text="Subir fotos a Flickr, crear un álbum, compartirlo eligiendo la opción 'Insertar', elegir el tamaño más grande, y pegar el link aquí", max_length=700, blank=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.titulo)
super(Articulo, self).save(*args, **kwargs)
def __str__(self):
return self.titulo
try this
def search(request):
query = request.GET.get('q', '')
if query:
try:
qset = Articulo.objects.filter(Q(titulo__icontains=query) | cuerpo_icontains = query) # change is here <<
results = Articulo.objects.filter(some_field=some_value).distinct() # change is here <<
except Articulo.DoesNotExist:
results = None
else:
results = []
return render_to_response('web/buscar.html', {"results": results, "query": query})
Note: I'm not sure why you are using qset and result there!
Since you are trying to perform a "search" (or filtering) you should use "fitler()" instead of get(), it makes more sense semantically. For your information, filter does not raise an exception if the result is empty.
Your code will look similar to:
from django.db.models import Q
def search(request):
results = []
query = request.GET.get('q', '')
if query:
qset = Q(titulo__icontains=query) | Q(cuerpo__icontains=query)
results = Articulo.objects.filter(qset).distinct()
ctx = {"results": results, "query": query}
return render_to_response('web/buscar.html', ctx)
If you are getting DoesNotExist exceptions with code which uses filter() you should take a look to the traceback to look for the liurls.py file to ensure that your desired views is being called and not other one.
first you need to import Q after that you can lookup function that takes keyword-arguments (e.g. filter(), exclude(), get()
from django.db.models import Q
def search(request):
query = request.GET.get('q', '')
if query:
Articulo.objects.get(
Q(titulo__icontains=query) |
Q(cuerpo_icontains=query)
)
return query
for more info you can check the docs here
from django.db.models import Q
def search(request):
results = []
query = request.GET.get('q', None)
if query:
try:
results = Articulo.objects.filter(Q(titulo__icontains=query) | Q(cuerpo_icontains=query))
except Articulo.DoesNotExist:
pass
return render_to_response('web/buscar.html',{"results": results, "query": query})

MultiValueDictKeyError at /registroEstudianteMayor/ "'Acudiente'"

I have this error
MultiValueDictKeyError at /registroEstudianteMayor/"'Acudiente'" ",
I searched a lot for an answer to this error but I couldn't find any.
I have this controller:
def post(self, request, *args, **kwargs):
generos = parametros['generos']
tiposDocumento = parametros['tiposDocumento']
zonas = parametros['zonas']
#Toma de datos
numeroDocumento = request.POST['numeroDocumento']
tipoDocumento = request.POST['tipoDocumento']
contrasena = request.POST['contrasena']
contrasena2 = request.POST['contrasena2']
correoElectronico = request.POST['correoElectronico']
nombres = request.POST['nombres']
apellidos = request.POST['apellidos']
fechaNacimiento = request.POST['fechaNacimiento']
genero = request.POST['genero']
direccion = request.POST['direccion']
barrio = request.POST['barrio']
telefonoFijo = request.POST['telefonoFijo']
telefonoCelular = request.POST['telefonoCelular']
seguridadSocial = request.POST['seguridadSocial']
#Toma de datos particulares
nombreAcudiente = request.POST['Acudiente']
telefonoAcudiente = request.POST['telefonoAcudiente']
foto = request.FILES['foto']
cedula = request.FILES['cedula']
#Inicializo datos opcionales
zona = ""
comuna = ""
grupoEtnico = ""
condicion = ""
enviarInfoAlCorreo = False
#Inicializo Datos Opcionales particulares
desempeno = ""
lugar = ""
#Tomo los datos opcionales
if request.POST['zona']: zona = request.POST['zona']
if request.POST['comuna']: comuna = request.POST['comuna']
if request.POST['grupoEtnico']: grupoEtnico = request.POST['grupoEtnico']
if request.POST['condicion']: condicion = request.POST['condicion']
if "enviarInfoAlCorreo" in request.POST.keys(): enviarInfoAlCorreo = True
#tomo datos opcionales particulares
if request.POST['Labor']: desempeno = request.POST['Labor']
if request.POST['Lugar']: lugar = request.POST['Lugar']
#Validaciones
errorNumeroDocumento = (User.objects.filter(username=numeroDocumento) or not re.match("^([0-9]{8,20})$",numeroDocumento))
errorTipoDocumento = (tipoDocumento not in (parametros["tiposDocumento"]))
errorContrasena = (request.POST["contrasena"]!=request.POST["contrasena2"])
errorCorreoElectronico = (User.objects.filter(email=correoElectronico) or not re.match(r"^[A-Za-z0-9\._-]+#[A-Za-z0-9]+\.[a-zA-Z]+$", correoElectronico))
errorFechaNacimiento = not fechaCorrecta(fechaNacimiento)
errorGenero = (genero not in (parametros["generos"]))
errorTelefonos = (not re.match("^([0-9]{7,12})$",telefonoFijo) or not re.match("^([0-9]{7,12})$",telefonoCelular) or not re.match("^([0-9]{7,12})$",telefonoAcudiente))
if (errorContrasena or errorNumeroDocumento or errorTipoDocumento or errorCorreoElectronico or errorFechaNacimiento or errorGenero or errorTelefonos):
return render_to_response('Generales/registroEstudianteMayor.html', locals(), context_instance = RequestContext(request))
#Guardar usuario
usuario = User.objects.create_user(id=User.objects.all().count() + 1, username=numeroDocumento, email=correoElectronico, password=contrasena)
usuario.first_name = nombres
usuario.last_name = apellidos
usuario.save()
#Guardo estudiante
estudiante = Estudiante(user = usuario, tipoDocumento = tipoDocumento, fechaNacimiento = fechaNacimiento, genero = genero, direccion = direccion, barrio = barrio, zona = zona, comuna = comuna,
telefonoFijo = telefonoFijo, telefonoCelular = telefonoCelular, grupoEtnico = grupoEtnico, condicion = condicion, seguridadSocial = seguridadSocial, enviarInfoAlCorreo = enviarInfoAlCorreo)
estudiante.save()
#Guardo datos particulares del Mayor
datosMayor = DatosFamiliaMayor(idEstudiante= user, nombreContacto= nombreAcudiente, telefonoContacto= telefonoAcudiente,
desempeno= desempeno, lugar= lugar, cedula= cedula, foto= foto)
datosMayor.save()
return inicioControl(request, registerSuccess=True)
and the part of the view being affected is:
<label class="control-label col-md-4" for="acud">Nombre Acudiente:</label>
<div class= "col-md-8">
<input type="text" name="Nomacud" requiered="true" value="{{Acudiente}}" class="form-control" id="nomacud">
</div>
</div>
<div class="form-group" id="TelAcudiente">
<label class="control-label col-md-4" for="Acudtel">Telefono Acudiente:</label>
<div class="col-md-8">
<input type="text" name="Telacud" requiered="true" value="{{telefonoAcudiente}}" class="form-control" id="telacud">
</div>
</div>
In TelefonoAcudiente the error is the same.
You don't have a field called Acudiente in your view; you have one called Nomacud instead.
Really though you should be using Django forms for all this.

Display blob image in template Google App Engine (Python)

I am trying to display an uploaded blob image. It seems to be storing ok, but won't display on the html template when called. Even seems to be showing up in the logging. When looking at other examples, the only real difference I see is you have to iterate over a list, but really just want to pull only one picture. Any advice you can give is greatly appreciated. -Thanks
Handlers:
class PictureHandler(BaseHandler2):
def get(self, **kwargs):
user_session = self.user
user_session_object = self.auth.store.get_session(self.request)
user_info = models.User.get_by_id(long( self.user_id ))
user_info_object = self.auth.store.user_model.get_by_auth_token(
user_session['user_id'], user_session['token'])
user = self.session.get('user')
uploads = db.GqlQuery("SELECT * FROM UserPictureUpload WHERE user =:1 ORDER BY created DESC", user_info.username).get()
upload_url = blobstore.create_upload_url('/upload')
params = {
'upload_url': upload_url,
'user': user_info.username,
'uploads': uploads
}
return self.render_template('picture.html', **params)
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler, BaseHandler2):
def post(self):
user_session = self.user
user_session_object = self.auth.store.get_session(self.request)
user_info = models.User.get_by_id(long( self.user_id ))
user_info_object = self.auth.store.user_model.get_by_auth_token(
user_session['user_id'], user_session['token'])
user = self.session.get('user')
title = self.request.get('title')
pic = self.request.get("picfile")
if pic:
picture = db.Blob(pic)
upload = UserPictureUpload(title = title, picture=picture, user=user_info.username)
upload.put()
self.redirect('/settings/picture')
class ViewHandler(blobstore_handlers.BlobstoreDownloadHandler, BaseHandler2):
def get(self):
user_session = self.user
user_session_object = self.auth.store.get_session(self.request)
user_info = models.User.get_by_id(long( self.user_id ))
user_info_object = self.auth.store.user_model.get_by_auth_token(
user_session['user_id'], user_session['token'])
user = self.session.get('user')
upload_key_str = self.request.params.get('key')
if upload_key_str:
upload = db.get(upload_key_str)
if upload:
logging.info('** Upload Found** -- %s' % upload.picture)
self.send_blob(upload.picture)
if not upload_key_str:
self.error(404)
return
Routing:
RedirectRoute('/settings/picture', handlers.PictureHandler, name='picture', strict_slash=True),
RedirectRoute('/upload', handlers.UploadHandler, name='upload', strict_slash=True),
RedirectRoute('/view', handlers.ViewHandler, name='view', strict_slash=True)
Html:
<form action="{{ upload_url }}" method="post" enctype="multipart/form-data">
<label for="title">Title:</label>
<input type="text" id="title" name="title" /><br />
<label for="upload">File:</label>
<input type="file" id="upload" name="picfile" /><br />
<input type="submit" value="Upload Picture" />
</form>
<br />
<img src='/view?key={{uploads.key()}}' alt='no image'/></img>
App Engine Log:
INFO 2013-07-30 16:11:20,946 handlers.py:875] ** Upload Found** -- Content-Type: image/jpeg
Content-Length: 775702
Content-MD5: NWE0NGM3YmE1YmJlNGVjODY3MjMzZDY3ZTQ4MDY4NDg=
content-disposition: form-data; name="picfile"; filename="Jellyfish.jpg"
X-AppEngine-Upload-Creation: 2013-07-29 15:41:00.481000
INFO 2013-07-30 11:11:21,005 server.py:584] default: "GET /view?key=ag5kZXZ-c2FuZGVuZ2luZXIeCxIRVXNlclBpY3R1cmVVcGxvYWQYgICAgJjxtgsM HTTP/1.1" 200 -
It looks like you are uploading the blob in blobstore but creating a key from your post upload handler and storing it as another blob on picture property instead of getting the blobkey from the uploaded blobinfo which from here: https://developers.google.com/appengine/docs/python/tools/webapp/blobstorehandlers
you can get with
upload = self.get_uploads()[0]
picture=upload.key()
then that's what you put on your send_blob.

GAE - Error: "The method POST is not allowed for this resource"

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 %}
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 })

Categories

Resources