Why are my search results not displayed? - google-app-engine

When I make I search in my web form, it appears that matches are found but they are not displayed:
What can I do to make the SERP display? My code is:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="/static/css/main.css"/>
<title>Search Demonstration App</title>
</head>
<body>
<form action="/sign" method="post">
<div>Search Demo</div>
<div><textarea name="search" rows="1" cols="60"></textarea></div>
<div><input type="submit" value="Search"/></div>
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Comment"/></div>
</form>
{{number_returned}} of {{results.number_found}} comments found <p>
{% for scored_document in results %}
{% for field in scored_document.fields %}
{{field.value}}
{% endfor %}
<p>
{% endfor %}
{{ url_linktext }}
</body>
</html>
And .py
class SearchAPI(webapp.RequestHandler):
"""Handles search requests for comments."""
def get(self):
"""Handles a get request with a query."""
uri = urlparse(self.request.uri)
query = ''
if uri.query:
query = parse_qs(uri.query)
query = query['query'][0]
# sort results by author descending
expr_list = [search.SortExpression(
expression='author', default_value='',
direction=search.SortExpression.DESCENDING)]
# construct the sort options
sort_opts = search.SortOptions(
expressions=expr_list)
query_options = search.QueryOptions(
limit=3,
sort_options=sort_opts)
query_obj = search.Query(query_string=query, options=query_options)
results = search.Index(name='ad').search(query=query_obj)
#logging.info("number of results:" +len(results))
if users.get_current_user():
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
template_values = {
'results': results,
'number_returned': len(results.results),
'url': url,
'url_linktext': url_linktext,
}
path = os.path.join(os.path.dirname(__file__), 'searchapi.html')
self.response.out.write(template.render(path, template_values))
The index is built like this:
class CreateAdHandler(BaseHandler):
def post(self):
ad = Ad.get_by_id(self.session.get('ad_id'))
city_entity = montaomodel.City.all().filter('name =', ad.city).get()
region_entity = montaomodel.Region.all().filter('name =', ad.region).get()
form = PreviewAdForm(self.request.params)
if form.validate():
ad.set_password(self.request.get('password'))
ad.published = True
ad.put()
doc = search.Document(doc_id=str(ad.key()),
fields=[search.TextField(name='title',
value=ad.title),search.TextField(name='text',
value=ad.text),search.TextField(name='city',
value=ad.city),search.TextField(name='region',
value=ad.region),search.NumberField(name='cityID',
value=city_entity.key().id()),search.NumberField(name='regionID',
value=region_entity.key().id()),search.NumberField(name='category',
value=int(ad.category)), search.NumberField(name='constant',
value=1), search.NumberField(name='adID',
value=ad.key().id()),
search.TextField(name='name',
value=ad.name
)],
language='en')
search.Index(name='ad').add(doc) # should this be "put" instead? see https://developers.google.com/appengine/docs/python/search/overview#Deleting_Documents
self.redirect('/vi/%d.html' % (ad.key().id(), ))
else:
logging.info('form did not validate')
self.render_jinja('preview', form=form, ad=ad)
Update
By careful debugging it's shown that this line won't work: {% for f in scored_document.fields %}. I found by debugging but I don't know why. So at least I'm closer to the solution now but it's not done.
Update 2
I can't understand why the fields are not accessed. I can add and output the data to the console:
INFO 2013-05-14 01:00:53,944 main.py:4437] result: search.ScoredDocument(doc_id=u'eb24f746-c60a-462c-9f64-a06ad6a823cb', fields=[search.TextField(name=u'author', value=u'test'), search.TextField(name=u'comment', value=u'test'), search.DateField(name=u'date', value=datetime.datetime(2013, 5, 13, 0, 0))], language=u'en', rank=74648319L)
INFO 2013-05-14 01:00:53,944 main.py:4437] result: search.ScoredDocument(doc_id=u'af0de892-0e59-4c12-bd9e-6e8caa2067d4', fields=[search.TextField(name=u'author', value=u'test'), search.TextField(name=u'comment', value=u'test'), search.DateField(name=u'date', value=datetime.datetime(2013, 5, 14, 0, 0))], language=u'en', rank=74653247L)
This logging takes place like this now:
for r in results:
logging.info("result: " + str(r))
So if I can log data like that to the console, why can't I just output it to my page?

Seems like you should iterate through results.results in your template:
{% for scored_document in results.results %}

I think you need to include the returned_fields property in your QueryOptions. (A list of field-names.)

Related

Having a following followers problem in Django "too many values.."

I'm about to finish a Django based project, and the last step of this project is to build a followers/following feature. I can unfollow someone I've followed manually from the admin, but I can't follow someone from my html view. It misses me just one tiny thing to add into my html code but I'm really stuck. My code
My Model:
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
CREATOR = "CREATOR"
SUBSCRIBER = "SUBSCRIBER"
ROLE_CHOICES = (
(CREATOR, "Créateur"),
(SUBSCRIBER, "Abonné"),
)
profile_photo = models.ImageField(upload_to='profile_photos/', default='profile_photos/default.png', blank=True, null=True)
role = models.CharField(max_length=10, choices=ROLE_CHOICES, default=SUBSCRIBER)
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False)
My Views:
#login_required
def abonnements(request):
user = request.user
followers = user.followers.all()
follows = user.follows.all()
if request.method == 'POST':
if request.POST.get('follow'):
if request.POST.get('follow') == user.username:
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "error": "You can't follow yourself!"})
try:
followed_user = User.objects.get(request.POST.get('follow'))
except User.DoesNotExist:
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "error": "User does not exist"})
else:
print(followed_user)
elif request.POST.get('unfollow'):
user.follows.remove(User.objects.get(pk=request.POST.get('unfollow')))
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "success": "You are no longer following " + request.POST.get('unfollow')})
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows})
My HTML
{% extends 'base.html' %}
<title>{% block title %}Abonnements{% endblock %}</title>
{% block content %} {% include 'partials/_navbar.html' %}
<main class="corps_abonnements">
<section class="suivre">
<p class="suivre_utilisateurs_titre">Suivre d'autres utilisateurs</p>
<form method="post">
{% csrf_token %}
<input type="text" name="follow" value="">
<input type="submit" value="Envoyer">
</form>
</section>
<section class="abonnements">
<p color="red">{{ error }}</p>
{% if success %}<p color="green">{{ success }}</p>{% endif %}
<p class="abonnements_titre">Abonnements</p>
{% for user in follows %}
<div class="utilisateur_desabonner_container">
<p class="nom_utilisateur_desabonner">{{ user.username }}</p>
<form method="post">
{% csrf_token %}
{% if user in follows %}
<input type="hidden" name="unfollow" value="{{ user.id }}">
<button style="background-color:red;" type="submit" class="creer_critique_demande">
Se désabonner
</button>
{% endif %}
</form>
</div>
{% endfor %}
</section>
<section class="abonnes">
<p class="abonnes_titre">Abonnés</p>
{% for user in followers %}
<div class="utilisateur_abonne_container">
<p class="nom_utilisateur_abonne">{{ user.username }}</p>
</div>
{% endfor %}
</section>
</main>
{% endblock %}
So when I put the connected user name in the input, it returns me the error "you can't follow yourself", it means that my code is good
the message
but If I try to put the username of another user I want to follow, it raises me an error. Can someone help me please ?
ValueError at /abonnements/
too many values to unpack (expected 2)
Request Method: POST
Request URL: http://127.0.0.1:8000/abonnements/
views.py, line 155, in abonnements
followed_user = User.objects.get(request.POST.get('follow'))

How to add Checkboxes in Django Form.

I want to add checkboxes in my Django form for different NGOs(say NGO1, NGO2, and so on...). I want the user to select those checkboxes and that data should be saved in the database.
Please, Suggest me the necessary changes in the code. I'm using Django 1.9.
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfileInfo(models.Model):
user=models.OneToOneField(User)
def __str__(self):
return self.user.first_name
return self.user.last_name
return self.user.email
forms.py
from django import forms
from django.contrib.auth.models import User
from volunteer.models import UserProfileInfo
class UserForm(forms.ModelForm):
class Meta():
model = User
fields = ('email','first_name','last_name','username')
views.py
from django.shortcuts import render
from volunteer.forms import UserForm
def register(request):
registered = False
if request.method =="POST" :
user_form = UserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'volunteer/volunteer.html',
{'user_form':user_form,
'registered':registered})
admin.py
from django.contrib import admin
from volunteer.models import UserProfileInfo
# Register your models here.
admin.site.register(UserProfileInfo)
urls.py
from django.conf.urls import url
from . import views
app_name = 'volunteer'
urlpatterns = [
url(r'^', views.register, name='register'),
]
volunteer.html(which has the form)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
</head>
<body>
<div class="jumbotron">
{% if registered %}
<p>Thank you <p>
{% else %}
<h1>Register yourself for Volunteering</h1>
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<input type="submit" name="" value="Register as a Volunteer">
{% endif %}
</div>
</form>
</body>
</html>
NOTE - I haven't included bootstrap, ajax and JQuery libraries in the above html code due to the formatting issues, I think it has nothing to do with the problem, so.
Thanks in advance!
You can easily achieve that using checkbox widget in django forms.
Define your form class as :
NGO_CHOICES = (
('one', 'ONE'),
('two', 'TWO'),
('three', 'THREE'),)
class UserForm(forms.ModelForm):
ngo = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
choices=NGO_CHOICES)
class Meta():
model = User
fields = ('ngo', 'email','first_name','last_name','username')
Now while saving the data, you can access the data of checkbox in
if request.method =="POST" :
user_form = UserForm(data=request.POST)
if user_form.is_valid():
# getting the list of ngos
ngo = user_form.cleaned_data['ngo']
user = user_form.save()
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
Hope it helps.

Forms do not create new entry in database with Django

I try to create a Form to create new players. Opening the url works well and when i clic on submit button, i get no error but redirected to the home project.
When i check in the admin part, i can not see the data i posted in the form before. Moreover, i can not see the picture i send before in the media directory.
The database is not updated when informations are posted with forms in Django 2.1
I don't know if i set right the POST request.
Maybe a bug or i miss something?
template.py
<h1>Add a new player</h1>
{% if saved %}
<p>Player has been saved</p>
{% endif %}
<p>
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
</p>
view.py
from game.models import Scenario, Player
from .forms import ScenarioForm, NewPlayerForm
def newplayer(request):
saved = False
form = NewPlayerForm(request.POST or None, request.FILES)
if form.is_valid():
player = Player()
player.pseudo = form.cleaned_data['pseudo']
player.gender = form.cleaned_data['gender']
player.picture = form.cleaned_data['picture']
player.save()
saved = True
return render(request, 'game/newplayer.html', {
'form': form,
'saved': saved
})
model.py
class Player(models.Model):
pseudo = models.CharField(max_length=100)
GENDER_CHOICES = (
('M', 'Homme'),
('F', 'Femme'),
('O','Other'),
)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
picture = models.ImageField(upload_to="images/")
class Meta:
verbose_name = "player"
ordering = ['pseudo']
def __str__(self):
"""
Cette méthode que nous définirons dans tous les modèles
nous permettra de reconnaître facilement les différents objets que
nous traiterons plus tard dans l'administration
"""
return self.pseudo
Form.py
from django import forms
from .models import Scenario, Player
class NewPlayerForm(forms.Form):
pseudo = forms.CharField(required=True)
GENDER_CHOICES = (
('M', 'Homme'),
('F', 'Femme'),
('O', 'Other'),
)
gender = forms.ChoiceField(choices=GENDER_CHOICES, required=True)
picture = forms.ImageField()
I would put a comment but I can't do that until I have 50 reputation, but...
In your view, at the <form> element, you have action=".", which means if you submit it, that will run through the function at the current url. Is your urlpattern for newplayer() pointing to that same page? Because you said you're being redirected to your home project, but your function doesn't have a return redirect(). And the return render() you have doesn't say it goes to something like index.html, which is the typical home directory as far as I'm used to.
Mind putting your url patterns in here?
Also, because your view has a saved variable, and because of your control flow, no matter what you do, you will always get the page returning with <p>Player has been saved</p> because your current setup makes it always exist. If you did something like the following, then it would show you the update on that page properly (but I still need to see the url patterns):
views.py
def newplayer(request):
# You might have to change some of the parameters in the form object below.
# Example: I know if you made your own validation instead of django's,
# object.photo = request.FILES.get('uploadphoto', False) would get the picture fine,
# but I'm not sure about django forms.
form = NewPlayerForm(request.POST or None, request.FILES)
if request.method == 'POST' and form.is_valid():
player = Player()
player.pseudo = form.cleaned_data['pseudo']
player.gender = form.cleaned_data['gender']
player.picture = form.cleaned_data['picture']
player.save()
saved = 'Player has been saved!'
return render(request, 'success.html', {'saved': saved})
else:
return render(request, 'create_player.html', {'form': form})
template.html
{% if saved %}
<p>{{ saved }}</p>
{% else %)
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
{% endif %}

POST request of rot13 app breaking my app

I am following the tutorials on Udacity.com to learn web development and I currently have to build a rot13 app on Google App Engine..
My entire code is shown below even though I believe the error is from POST function.
If I comment it out I'm able to see the app even though can't do anything it.
But if I uncomment it, it shows a blank page in my browser.
Hoping to get some pointers on what I'm doing wrong here. Thanks in advance
import webapp2
import cgi
form="""<html>
<head>
<title>Unit 2 Rot 13</title>
</head>
<body>
<h2>Enter some text to ROT13:</h2>
<form method="post">
<textarea name="text" style="height: 100px; width: 400px;"> </textarea>
<br>
<input type="submit" value="submit">
</form>
</body>
</html>
"""
def rot13(a):
list1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
list2 = 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
result = ''
for e in a:
if e in list1:
result = result + list2[list1.find(e)]
else:
result = result + e
return result
def escape_html(s):
return cgi.escape(s, quote = True)
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.out.write(form)
def post(self):
rot13 = ''
text = self.request.get('text')
if text:
rot13 = text.encode('rot13')
self.response.out.write(form, text = rot13)
application = webapp2.WSGIApplication([('/', MainPage)], debug=True)

UnicodeDecodeError. While rendering the blob image

I am trying to add uploading images feature.
This class saves new entity:
class NewPost(Handler):
def render_newpost(self, title='' , content='', error = ''):
self.render("newpost.html", title = title, content = content, error = error)
def get(self):
user_cookie = self.request.cookies.get('user')
if user_cookie:
user_id = user_cookie.split('|')[0]
if hash_str(user_id) == user_cookie.split('|')[1]:
user = Users.get_by_id(int(user_id))
self.render_newpost()
else:
self.redirect('/')
def post(self):
title = self.request.get("title")
content = self.request.get("content")
image = self.request.get("file")
if title and content:
p = Posts(title = title, content = content)
p.image=db.Blob(image)
p.put()
self.redirect("/")
else:
error = "Enter both title and text"
self.render_newpost(title, content, error)
Here is my front page render class:
class Main(Handler):
def get(self):
posts = db.GqlQuery("SELECT * FROM Posts Order by created DESC LIMIT 10")
user_cookie = self.request.cookies.get('user')
if user_cookie:
user_id = user_cookie.split('|')[0]
if hash_str(user_id) == user_cookie.split('|')[1]:
user = Users.get_by_id(int(user_id))
self.render("front.html", posts = posts, user=user)
else:
self.response.headers['Content-Type'] = "image/jpeg"
self.render("front.html", posts = posts)
form to enter data:
<form method="post" enctype="multipart/form-data">
<div class="newpost">
<label>Image:</label>
<input type="file" name="file"/>
<div class="label">Title:
<input type="text" name="title" value="{{title}}"/>
</div>
<hr>
<div class="label">Content:
<textarea name="content">{{content}}</textarea>
</div>
</div>
<input type="submit"/>
<div class="error">{{error}}</div>
</form>
and here is my home page template: (The problem appears here!)
{% for post in posts %}
{% if post.image %}
<li><img src="/static/images/{{post.image}}"/>
{% endif %}
<h4>{{post.title}}</h4>
<p class="zoom">{{post.content}}</p>
{% endfor %}
App successfully stores image, but when it returns to the front page trying to render image it gives this error:
File "/home/wanhrust/google_appengine/newsite/templates/front.html", line 54, in top-level template code
{{post.image}}
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)
I've been googling for several hours but without results. Any help?
The problem is that you are trying to embed an image in an html document which is not possible. Post.image is storing the bytes representing the image.
If you want to include the image in your html, you need to add something like this
{% if post.image_id %}
<li><img src="/image/{{post.image_id}}" />
{% endif %}
Where /image/ is a handler that returns the content of the image (setting the apprpriate content-type).
I also would recommend you to use the Blobstore API.

Resources