I'm having trouble getting my ancestor queries to display the links associated with Tom's photos that are stored in the datastore. Nothing is displayed from the datastore even though there are several links in the datastore. Any assistance will be appreciated. Thanks in advance.
main.py
import webapp2
import jinja2
import os
from google.appengine.ext import db
jinja_environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
class MainPage(webapp2.RequestHandler):
def get(self):
tom = Person(key_name='Tom')
wedding_photo = Photo(parent=tom)
wedding_photo.image_url='http://pinterest.com/pin/200691727117011230/'
wedding_photo.put()
baby_photo = Photo(parent=tom)
baby_photo.image_url='http://pinterest.com/pin/518828819542052681/'
baby_photo.put()
dance_photo = Photo(parent=tom)
dance_photo.image_url='http://pinterest.com/pin/257197828689352707/'
dance_photo.put()
dog_photo = Photo()
dog_photo.image_url='http://pinterest.com/pin/279575089339614779/'
dog_photo.put()
photo_query = Photo.all()
photo_query.ancestor(tom)
message = "Photos"
template_values = {
'message': message,
'photo_query': photo_query,
}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))
class PhotoStore(webapp2.RequestHandler):
def post(self):
photo = Photo()
photo.image_url = self.request.get('image_url')
photo.put()
self.redirect('/')
class Person(db.Model):
name = db.StringProperty()
class Photo(db.Model):
image_url = db.StringProperty()
app = webapp2.WSGIApplication([('/', MainPage),
('/new_photo',PhotoStore)], debug=True)
index.html
<html>
<body>
<form action="/new_photo" method="post">
<label for="photo">Photo</label>
<div><textarea name="image_url" rows="1" cols="60" id="image_url"></textarea></div>
<input type="submit" value="Submit">
</form>
<hr></hr>
<div><b>{{ message }}</b></div>
<b>{% for p in photo_query.run(limit=5): %}</b>
<div>{{ p }}</div>
<b>{% endfor %}</b>
</body>
</html>
What do you see if you open the generated html source? I assume that the code {{ p }} just shows string representation of the Photo objects, which results in showing strings like <__main__.Photo object at 0xfcbd9ef0> that is interpreted as HTML tag and doesn't show in the rendered HTML.
Related
i m new to all this, still learning.
Now task for me is to create search bar using mongodb
What i have done so far
created the mongodb_connection.py to establish connection using pymongo
from pymongo import MongoClient
def mongosearch(title=""):
connection = MongoClient('localhost',27017)
db = connection.djangodb
collection = db.spiderCollection
title = collection.find()
for title in titles:
pprint.pprint()
created view and importing method from mongodb_connection as follows:
from django.shortcuts import render
from django.http import HttpResponse
from .mongodb_connection import mongosearch
from .models import AppModel
# Create your views here.
def search_view(request):
results = []
title_term = ""
search_term = ""
titles = AppModel.objects.all()
if 'search' in request.GET:
search_term = request.GET['search']
titles = titles.filter(title__icontains=search_term)
results = mongosearch(title=title_term)
print(results)
context={
'results':results,
'count':len(results),
'search_term':search_term,
'titles':titles
}
return render(request, 'search.html', context)
added the models.py
from django.db import models
class AppModel(models.Model):
title = models.CharField(max_length=100, primary_key=True)
desc = models.CharField(max_length=100)
url = models.CharField(max_length=100)
class Meta:
db_table = "spiderCollection"
then modified the urls
from django.urls import path, include
from . import views
from django.conf.urls import url
app_name = 'searchapp'
urlpatterns=[
path('',views.search_view, name='search_view'),
]
created html page under apps/templates
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<!doctype html>
<html>
<nav class="navbar navbar-light bg-light">
<form class = "form-inline my-2 my-lg-1">
<input
class="form-control mr-sm-2"
type="search"
placeholder="Search"
aria-label="Search"
name = 'search'
value = "{{request.GET.search}}">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
<ul>
{%for i in titles %}
<li>
{{i.titles}}
</li>
{% endfor %}
</ul>
</form>
</nav>
</html>
The problem is i m getting the data fetching from mongodb. I think i m pretty close. As soon as i enter values in the search and hit submit , it errors out in the following.
Exception Type: NameError
Exception Value:
name 'titles' is not defined
Exception Location: /Users/qasimbutt/PycharmProjects/IntegratedProject/searchui/searchapp/mongodb_connection.py in mongosearch, line 9
Can someone assist me, what change can i make in the mongodb_connection.py file to get it rolling? Also please advise if anything is missing here.
As i need to fetch the data from mongodb and display it under search.
Thanks again.
Just looking at your first function, the line:
for title in titles:
references titles before it is defined anywhere. You might have meant:
titles = collection.find()
for title in titles:
I am trying to write my first GAE/Python application that does the following three things:
Displays a form where the user can enter details about themself (index.html)
Stores the submitted form data in the datastore
Retrieves all data from datastore and displays all results above the form (index.html)
However, I'm getting the following error
line 15, in MainPage 'people' : people NameError: name 'people' is not
defined
Any advice on how to resolve this and get my app working will be appreciated!
main.py
import webapp2
import jinja2
import os
jinja_environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
class MainPage(webapp2.RequestHandler):
def get(self):
people_query = Person.all()
people = people_query.fetch(10)
template_values = {
'people': people
}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))
# retrieve the submitted form data and store in datastore
class PeopleStore(webapp2.RequestHandler):
def post(self):
person = Person()
person.first_name = self.request.get('first_name')
person.last_name = self.request.get('last_name')
person.city = self.request.get('city')
person.birth_year = self.request.get('birth_year')
person.birth_year = self.request.get('height')
person.put()
# models a person class
class Person(db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
city = db.StringProperty()
birth_year = db.IntegerProperty()
height = db.IntegerProperty()
app = webapp2.WSGIApplication([('/', MainPage),
('/new_person')], debug=True)
index.html
<html>
<body>
{% for person in people %}
{% if person %}
<b>{{ person.first_name }}</b>
<b>{{ person.last_name }}</b>
<b>{{ person.city }}</b>
<b>{{ person.birth_year }}</b>
<b>{{ person.height }}</b>
<hr></hr>
{% else %}
No people found
{% endfor %}
<form action="/new_person" method="post">
<div><textarea name="first_name" rows="3" cols="60"></textarea></div>
<div><textarea name="last_name" rows="3" cols="60"></textarea></div>
<div><textarea name="city" rows="3" cols="60"></textarea></div>
<div><textarea name="birth_year" rows="3" cols="60"></textarea></div>
<div><textarea name="height" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Submit"></div>
</form>
</body>
</html>
app.yaml
application: some_name
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
EDIT 1
*main.py*
import webapp2
import jinja2
import os
from google.appengine.ext import db
jinja_environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
class MainPage(webapp2.RequestHandler):
def get(self):
people_query = Person.all()
people = people_query.fetch(10)
template_values = {
'people': people
}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))
class PeopleStore(webapp2.RequestHandler):
def post(self):
person = Person()
person.first_name = self.request.get('first_name')
person.last_name = self.request.get('last_name')
person.city = self.request.get('city')
person.birth_year = self.request.get('birth_year')
person.height = self.request.get('height')
person.put()
class Person(db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
city = db.StringProperty()
birth_year = db.IntegerProperty()
height = db.IntegerProperty()
app = webapp2.WSGIApplication([('/', MainPage),
('/new_person')], debug=True)
EDIT 2
*main.py*
The following edit fixed this error
AttributeError: 'str' object has no attribute 'get_match_routes'
app = webapp2.WSGIApplication([('/', MainPage),('/new_person',PeopleStore)], debug=True)
Ok great, the form displays in the browser, but when I submit the data, I get this error:
BadValueError: Property birth_year must be an int or long, not a
unicode
EDIT 3
main.py
person.birth_year = int(self.request.get('birth_year'))
person.height = int(self.request.get('height'))
resolved this error:
badvalueerror property must be an int or long, not a unicode
Ok, good so far. The data stores in the data store. However, my page comes up blank...
You have an indentation problem. Lines 3 and onwards of your get method should be indented at the same level as the first two lines. Otherwise, they are not part of the method, but the class definition itself, and will be executed when the class is defined - at which point there is no variable people in scope.
In your app.yaml it doesnt like the underscore
#application: some_name
application: somename
There are some more issues with blocks not being closed etc which you need to work through yourself
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>
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
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('/')
I keep receiving an internal server error - 'BadValueError: Property content is required. It seems to happen when I pass blog_table into the template to render. Here's the code:
main.py:
import os
import webapp2
import jinja2
from google.appengine.ext import db
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__),'templates')), autoescape = True)
class Handler(webapp2.RequestHandler):
def write(self,*a,**kw):
self.response.out.write(*a,**kw)
def render_str(self,template,**params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self,template,**kw):
self.write(self.render_str(template,**kw))
class Blog(db.Model):
subject = db.StringProperty(required = True)
content = db.TextProperty(required = True)
created = db.DateTimeProperty(auto_now_add = True)
class MainPage(Handler):
def render_front(self, subject="", content="", error=""):
blog_table = db.GqlQuery("SELECT * FROM Blog ORDER BY created DESC")
self.render("blog.html",subject = subject,content = content,error = error,blog_table = blog_table)
def get(self):
self.render_front()
def post(self):
subject = self.request.get("subject")
content = self.request.get("content")
if subject and content:
b = Blog(subject = subject, content = content)
b.put()
self.redirect("/")
else:
error = "we need both a subject and some content"
self.render_front(subject,content,error)
app = webapp2.WSGIApplication([('/', MainPage)],debug=True)
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
</head>
<body>
<h1>Blog</h1>
<form method="post">
<label>
<div>Subject</div>
<input type="text" name="subject" value="{{subject}}">
</label>
<label>
<div>Content</div>
<textarea name="content" value="{{content}}"></textarea>
</label>
<div class="error">{{error}}</div>
<input type="submit">
</form>
<hr>
{% for post in blog_table %}
<div class="post">
<div class="subject">{{post.subject}}</div>
<pre class="content">{{post.content}}</pre>
</div>
{% endfor %}
</body>
</html>
To see the error go to http://udacity-cs253-a31.appspot.com/
Thanks.
This is just a guess - changed your Blog model and added the Content attribute recently.
There's some old instances of the Blog model in your datastore that have no Content. If you try to load those, your code fails. If you load a Blog instance with Content, everything is fine.
You have to go through your datastore and ensure all instances of your Blog have Content.
I was going through Appengine's Getting Started guide for python, while reading up templates,I modified the code(which is a simple guestbook) to include simple numbering next to the guestbook entries.
In index.html i added the (what I thought would be) relevant code.
index.html (I have added {%i=0%} on line 3,{%i+=1%} on line 5, and {{i}} on line 7, the rest is from the guide):
<html>
<body>
{%i=0%}
{% for greeting in greetings %}
{%i+=1%}
{% if greeting.author %}
<b>{{i}}:{{ greeting.author.nickname }}</b> wrote:
{% else %}
An anonymous person wrote:
{% endif %}
<blockquote>{{ greeting.content|escape }}</blockquote>
{% endfor %}
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
{{ url_linktext }}
</body>
</html>
I got the following error
TemplateSyntaxError: Invalid block
tag: 'i=0'
I read up Django's help on templates, which says that
The Django template system provides
tags which function similarly to some
programming constructs – an if tag for
boolean tests, a for tag for looping,
etc. – but these are not simply
executed as the corresponding Python
code, and the template system will not
execute arbitrary Python expressions.
So I guess, that performing calculations is not what the templating system is for.
tl;dr
Can anyone tell me how to number my entries or use the "counter - increment" construct using Django templates?
I don't thing this code is necessary, but to complete the picture,
Unchanged helloworld.py code:
import os
from google.appengine.ext.webapp import template
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
def get(self):
greetings_query = Greeting.all().order('-date')
greetings = greetings_query.fetch(10)
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 = {
'greetings': greetings,
'url': url,
'url_linktext': url_linktext,
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/sign', Guestbook)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
From http://www.djangobook.com/en/beta/chapter04/
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
It depends on what you need it for. If you need the actual count, you can use a for loop in the template: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
Then you can use forloop.counter or forloop.counter0 to check the index.
If you just want to display a list of numbers you can use a html ordered list.
Django's template engine is for design only, and you want to keep calculations out of it. If you need to do something with your data at the template layer you can write a custom tag/filter.