GAE отображает «нет», но я вижу объекты БД в средстве просмотра хранилища данных

У меня проблема с доступом к объектам хранилища данных. Я новичок в GAE и Python, так что будьте добры. Я брал код из онлайн-учебников и других примеров кода, и до сих пор все шло нормально.

В конечном счете, я хочу иметь возможность удалить вложение электронной почты, внести некоторые простые изменения в файл (файлы) и объединить его с другим файлом (файлами) .kml (или даже лучше .kmz, но по одному :).

шаг 1. должен был отправлять электронные письма на адрес appspotmail приложения = готово :)

шаг 2. ... который пишет в db.model = я вижу в средстве просмотра панели инструментов/хранилища данных, что сущности есть, так что нет проблем = готово :)

шаг 3. - визуализировать шаблон, чтобы показать самые последние, скажем, 20 полученных писем. этот список будет динамически обновляться..... :( Хммммм

Вместо этого происходит то, что я вижу none для всех переменных в index.html. Не могли бы вы указать мне правильное направление? Благодарность!

Дав-о

вот yaml.app

application: racetracer
version: 1
runtime: python27
api_version: 1
threadsafe: false

libraries:                                                                      
- name: jinja2                                                                  
  version: latest   

handlers:
- url: /_ah/mail/.+ 
  script: handle_incoming_email.py
  login: admin

- url: /favicon.ico
  static_files: images/favicon.ico
  upload: images/favicon.ico

- url: /static/css
  static_dir: static/css

- url: /static/html
  static_dir: static/index.html

- url: .*
  script: main.app

inbound_services:
- mail

вот handle_incoming_email.py

import logging, email
import cgi
import datetime
import os.path
import os

from os import path
from google.appengine.ext import webapp 
from google.appengine.ext import db
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler 
from google.appengine.ext.webapp.util import run_wsgi_app 
from google.appengine.ext.webapp.template import render
import jinja2
import wsgiref.handlers

from main import *
from baseController import *
from authController import *

class Vault(db.Model):
    #fromAddress= db.UserProperty()
    fromAddress= db.StringProperty()
    subject = db.StringProperty(multiline=True)
    #date = db.DateTimeProperty(auto_now_add=True)
    date = db.StringProperty(multiline=True)
    name = db.StringProperty(multiline=True)

class ProcessEmail(InboundMailHandler): 
    def receive(self, mailMessage): 
        logging.info("Email from: " + mailMessage.sender + " received ok")
        logging.info("Email subject: " + mailMessage.subject )
        logging.info("Email date: " + mailMessage.date )

        fromAddress = mailMessage.sender
        subject = mailMessage.subject
        date = mailMessage.date

        if not hasattr(mailMessage, 'attachments'):
            logging.info("Oi, the email has no attachments")
            # raise ProcessingFailedError('Email had no attached documents')
        else:
            logging.info("Email has %i attachment(s) " % len (mailMessage.attachments))

            for attach in mailMessage.attachments:
                name = attach[0] #this is the file name
                contents = str(attach[1]) #and this is the attached files contents
                logging.info("Attachment name: " + name )
                logging.info("Attachment contents: " + contents)
                vault = Vault()
                vault.fromAddress = fromAddress
                vault.subject = subject
                vault.date = date
                vault.name = name
                vault.contents = contents #.decode() EncodedPayload.decode()
                    vault.put()      

                #f = open("aardvark.txt", "r")
                #blah = f.read(30);
                #logging.info("the examined string is : " + blah)
                #f.close() # Close opened file

app = webapp.WSGIApplication([
  ProcessEmail.mapping()
], debug=True)

def main():
    run_wsgi_app(app)

if __name__ == "__main__":
    main()

а вот basecontroller.py

from authController import *
from handle_incoming_email import *
import logging
import os
import webapp2
import jinja2
import wsgiref.handlers

from google.appengine.ext.webapp import template 
from google.appengine.ext import db
from google.appengine.api import users 

TEMPLATE_DIR = os.path.join(os.path.dirname(__file__))
jinja_environment = \
    jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_DIR))

class Vault(db.Model):
    #fromAddress= db.UserProperty()
    fromAddress= db.StringProperty()
    subject = db.StringProperty(multiline=True)
    #date = db.DateTimeProperty(auto_now_add=True)
    date = db.StringProperty(multiline=True)
    name = db.StringProperty(multiline=True)

class MainPage(webapp2.RequestHandler):    
    def get(self):
        logging.info("this is MainPage in baseController")
        list = db.GqlQuery("SELECT * FROM Vault ORDER BY date DESC").fetch(10)
        logging.info("this is in list: " + str(list))

        vault = Vault()

        fromAddress = vault.fromAddress
        subject = vault.subject
        date = vault.date
        name = vault.name

        values = {
                'fromAddress': fromAddress,
            'subject': subject,
            'date': date,
            'name': name,
            }
        templ = jinja_environment.get_template('index.html')
        self.response.out.write(templ.render(values))                        

def main():
    wsgiref.handlers.CGIHandler().run(app)

if __name__ == "__main__":
  main()

я читал в учебнике, что рендеринг шаблонов лучше, чем просто использование html в .py, но, может быть, я разбил его на слишком много файлов? Их логика заключалась в том, что фронтэнд и бэкенд делают разные люди, так что привыкайте к этому сейчас. В любом случае вышеизложенное предназначено для отображения в index.html, который:

index.html

{% extends "base.html" %}
{% block title %} racetracer {% endblock %}
{% block content %}
<h1>Racetracer </h1>
<h3>Files recently received :</h3>
<br>
        <table>
        <tr>
            <th>Email address:                  </th>
            <th>-----------                     </th>
            <th>Subject:                        </th>
            <th>Date Received:                  </th>
            <th>Attachment:                     </th>
        </tr>           
        <tr>                
            <td> {{ fromAddress }}              </td>
            <td> ---------------                </td>   
            <td> {{ subject }}                  </td>
            <td> {{ date }}                     </td>
            <td> {{ name }}                     </td>
        <blockquote>{{ content|escape }}</blockquote>                     
        </p>
        </tr>                               
    </tr>    
    </table>      
<br>

<hr>
<form action="/sign" method="post">
    <textarea name="content" rows="1" cols="20"></textarea>
    <input type="submit" value="Submit (in index:)">
</form>
{% endblock %}

и base.html....

<html><head>
<link type="text/css" rel="stylesheet" href="/static/css/main.css" /></head>

<body> From the file base out in the racetracer folder<br>
right now you are logged in as : 
    {% if user %}
        {{ user.nickname }}!
        [<a href="{{ logout }}"><b>sign out</b></a>]
    {% else %}
        anonymous, who are you?
        [<a href="{{ login }}"><b>sign in</b></a>]
    {% endif %}
    {% block content %}
    {% endblock %}
</body></html>

а вот main.py

import os
import webapp2
from handle_incoming_email import *
from baseController import *
from authController import *
from google.appengine.ext.webapp import template 

app = webapp2.WSGIApplication([
    ('/', MainPage),
    #('/ProcessEmail', ProcessEmail),
], debug=True)

def main():
    wsgiref.handlers.CGIHandler().run(app)

if __name__ == "__main__":
  main()

Спасибо за вашу помощь! это будет НАМНОГО оценено.


person sixD    schedule 26.03.2013    source источник
comment
Вы должны переместить свою модель в один файл и импортировать ее в свои разные обработчики, очень легко внести всевозможные ошибки, потому что у вас есть 2 отдельные реализации Vault.   -  person Tim Hoffman    schedule 26.03.2013
comment
Хорошо, спасибо, Тим. поэтому я бы сделал файл model.py, который состоял только из class vault, как показано выше, и добавлял from model.py import * всякий раз, когда это необходимо, да? Не уверен, что это что-то изменит в проблеме рендеринга???   -  person sixD    schedule 26.03.2013
comment
Да, я не решал вашу настоящую проблему с большим количеством кода, который нужно было пробираться :-), но дублированный класс выделялся как общая проблема, ожидающая укуса :-)   -  person Tim Hoffman    schedule 26.03.2013


Ответы (1)


Вы получаете None, потому что это IS None. Вы объявляете объект Vault, но не присваиваете ему никаких значений. Значения будут в объекте списка в результате запроса GQL.

vault = Vault() # This creates an empty object (assuming you aren't doing any dynamic init

fromAddress = vault.fromAddress  # Still empty....
subject = vault.subject
date = vault.date
name = vault.name

Кроме того, вы не должны назначать list как переменную, поскольку она зарезервирована для Py.

То, что вы хотите сделать, это установить что-то вроде:

my_list = YOUR GQL QUERY.fetch()

# Create a formatted list
values = []
for ml in my_list:
    value = {
            'fromAddress': ml.fromAddress,
        'subject': ml.subject,
        'date': ml.date,
        'name': ml.name,
        }

    values.append(value) # You could just append the dictionary directly here, of course

Затем используйте список значений в параметрах шаблона.

** Обновлять **

Ваш запрос GQL выглядит хорошо по сравнению с вашей моделью Vault хранилища данных.

Во-первых, убедитесь, что вы изменили переменную list на my_list. Затем, если вы хотите, чтобы содержимое полученного объекта было напечатано в виде читаемой строки, добавьте это в свою модель:

    def __unicode__(self):
       return ('%s %s %s' % (self.key,self.fromAddress,self.subject)) # etc... for the vars you want printed with you print the object

Проверьте свой logging.info(my_list) и посмотрите, печатает ли он что-нибудь более читаемое.

Если нет, запустите цикл for в списке и зарегистрируйте ключ и/или fromAddress, поэтому:

for vault in my_list:
   logging.info('the key = %s'%vault.key)

Если это ничего не возвращает, перейдите непосредственно в интерактивную консоль в вашей среде разработки и запустите этот запрос:

from google.appengine.ext import db
from *vault_file* import Vault

my_list = db.GqlQuery("SELECT * FROM Vault ORDER BY date DESC").fetch(10) # run query

for vault in my_list:
   print vault.key
   print vault.fromAddress

Дайте мне знать, где вас оставят эти тесты, и я продолжу обновлять.

* Обновление №2 *

Итак, теперь, когда вы можете подтвердить получение значений хранилища данных
, вы хотите установить параметр страницы шаблона, равный списку хранилища, поэтому:

params = dict(values=my_list)
self.response.out.write(templ.render(params)) 

И теперь на вашей странице вам нужно пройтись по списку, чтобы распечатать каждый элемент словаря:

{% for vault in values %}
    <tr>
       <td>{{vault.fromAddress}}}</td>
       etc...
    </tr>

{% endfor %}

Та работа?

person kevin    schedule 26.03.2013
comment
Спасибо, Кевин. я изменил код, как вы сказали, но на html-странице ничего нет (даже none из предыдущего). Одна вещь, я заметил в my_list = db.GqlQuery("SELECT * FROM Vault ORDER BY date DESC").fetch(10) logging.info("this is in my_list: " + str(my_list)), что в журнале эта строка выдает INFO 2013-03-26 22:32:24,828 baseController.py:36] this is in list: []. Означает ли это, что Vault записывается правильно? как вы думаете, где я должен искать дальше? еще раз спасибо. Дав-о - person sixD; 27.03.2013
comment
И.... когда я развертываю приложение, а ЗАТЕМ смотрю журналы, я получаю this is in my_list: [<handle_incoming_email.Vault object at 0xfce6c870>, <handle_incoming_email.Vault object at 0xfce6cad0>, <handle_incoming_email.Vault object at 0xfce6c9d0>, <handle_incoming_email.Vault object at 0xfce6cd90>, ... и т. д. Итак, как мне лучше преобразовать их в строки? - person sixD; 27.03.2013
comment
Ваш журнал выглядит так, как будто ваш запрос не возвращает результата, поэтому давайте начнем с этого. Можете ли вы проверить, что у вас есть в вашем хранилище данных? - person kevin; 27.03.2013
comment
Кроме того, вы должны попробовать ndb и выполнить запросы API ndb по сравнению с GQL, особенно для простых запросов, подобных тем, что у вас есть. developers.google.com/appengine/docs/python/ndb - person kevin; 27.03.2013
comment
Спасибо, Кевин. я читал о NDB, но пока давайте остановимся на GQL. Я думаю, что вы можете быть на деньги, когда вы говорите, что вы не должны назначать list как переменную, поскольку это зарезервировано для Py, но я не знаю, где это взять. Сначала OK хранилище данных: вот скриншот окна просмотра хранилища данных ‹ нажмите сейчас›. мне кажется, что содержимое электронных писем, отправленных на адрес appspotmail.com, хранится в порядке... - person sixD; 27.03.2013
comment
Великий Кевин - мы уже на пути: после годового обновления добавление ___unicode__(self) к модели произвело объект ‹handle_incoming_email.Vault по адресу 0xfce68bb0›, ‹handle_incoming_email.Vault объект по адресу 0xfce6fb90›, ‹ha....., так что я добавил for vault in my_list, который отлично регистрирует десять адресов электронной почты! Значит, проблема должна быть в рендеринге шаблона, верно? Что дальше, доктор? Спасибо, Дав-о. - person sixD; 28.03.2013
comment
Привет, Кевин. очень ценю вашу помощь. params = dict(values=my_list) был ключом к первому биту. Потрясающий. Теперь html отображает по крайней мере что-то, НО он отображает все те же данные 10 раз, и это не последний объект! Тем не менее, проверяя средство просмотра хранилища данных, каждый объект имеет разные даты, имена, идентификаторы и так далее. Любые идеи? - person sixD; 28.03.2013
comment
Кевин также, Тим выше предложил вынести Vault в свой собственный .py. Вы согласны? - person sixD; 28.03.2013
comment
с организационной точки зрения это помогло бы, но решать эту конкретную проблему не обязательно. Если у вас много моделей и обработчиков, вам следует подумать об этом. - person kevin; 28.03.2013
comment
Если вы распечатаете список на странице шаблона {{values}}, будет ли отображаться тот же объект? - person kevin; 28.03.2013
comment
Тогда я изменю Vault на собственный .py отдельно. НЕТ. это действительно странно. {{ values ​​}} производит [, , , , , , , , , ], это только 9 запятых, так что я думаю, десять пустых значений??? - person sixD; 28.03.2013
comment
у вас есть учетная запись github, где вы можете загрузить простой пример этого приложения, демонстрирующий проблему? - person kevin; 29.03.2013