2013-01-23 42 views
1

在我的項目中(使用Python,Html & Jinja2)我有一個包含電影圖片的home_page,每張圖片都會與電影數據一起導向特定頁面。當我嘗試,我發現了以下錯誤電影的數據來呈現網頁(我試圖刪除每一個元素,如去除moving.summary和錯誤,則上述放慢參數標記):Google App Engine中的UnicodeDecodeError

Traceback (most recent call last): 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1536, in __call__ 
     rv = self.handle_exception(request, response, e) 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1530, in __call__ 
     rv = self.router.dispatch(request, response) 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1278, in default_dispatcher 
     return route.handler_adapter(request, response) 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 1102, in __call__ 
     return handler.dispatch() 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 572, in dispatch 
     return self.handle_exception(e, self.app.debug) 
     File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2\webapp2.py", line 570, in dispatch 
     return method(*args, **kwargs) 
     File "C:\Users\User\Desktop\imovie-good\main.py", line 77, in get 
     self.response.out.write(template.render(template_values)) 
     File "C:\Program Files (x86)\Google\google_appengine\lib\jinja2\jinja2\environment.py", line 894, in render 
     return self.environment.handle_exception(exc_info, True) 
     File "C:\Users\User\Desktop\imovie-good\movie_data.html", line 7, in top-level template code 
     <td> Movie Name: {{movie_data.name}}</td> 
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128) 

這是我的Python代碼:

import webapp2 
    import jinja2 
    import os 
    import datetime 
    import time 
    import cgi 
    from google.appengine.ext import db 
    from google.appengine.api import users 
    from google.appengine.api import images 


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

    class Movie(db.Model): 
     name = db.StringProperty() 
     release_date = db.StringProperty() 
     duration = db.StringProperty() 
     director = db.StringProperty() 
     actors = db.StringProperty(multiline=True) 
     summary = db.StringProperty(multiline=True) 
     picture = db.BlobProperty() 
     trailer = db.StringProperty(multiline=True) 
     date = db.DateTimeProperty(auto_now_add=True) 

    class Movie_Data(webapp2.RequestHandler): 
     def get(self): 
      movie_key = self.request.get('movie_key') 
      movie_data = Movie.get(movie_key) 

    template_values = {'movie_data': movie_data} 
      template = jinja_environment.get_template('movie_data.html') 
      self.response.out.write(template.render(template_values)) 

    class Image(webapp2.RequestHandler): 
     def get(self): 
      movie = db.get(self.request.get('img_id')) 
      if movie.picture: 
       self.response.headers['Content-Type'] = 'image/jpeg' 
       self.response.out.write(movie.picture) 
      else: 
       self.response.out.write("No Image") 

    class Main(webapp2.RequestHandler): 
     def get(self): 
      movies = db.GqlQuery("SELECT * " 
           "FROM Movie " 
           "ORDER BY release_date DESC LIMIT 5") 
      template_values = { 'movies': movies}         
      template = jinja_environment.get_template('home_page.html') 
      self.response.out.write(template.render(template_values)) 

    class Admin(webapp2.RequestHandler): 
     def get(self): 
      template_values = {} 
      template = jinja_environment.get_template('admin.html') 
      self.response.out.write(template.render(template_values)) 


     def post(self): 
      name = self.request.get('name') 
      release_date = self.request.get('release_date') 
      c = time.strptime(release_date,"%m/%d/%Y") 
      release_date = time.strftime("%m%d%Y",c) 
      duration = self.request.get('duration') 
      director = self.request.get('director') 
      actors = self.request.get('actors') 
      summary = self.request.get('summary') 
      picture = self.request.get('img') 
      trailer = self.request.get('trailer') 

      movie = Movie(key_name = name) 
      movie.release_date = release_date 
      movie.duration = duration 
      movie.director = director 
      movie.actors = actors 
      movie.summary = summary 
      movie.picture = db.Blob(picture) 
      movie.trailer = trailer 
      movie.put() 
      self.redirect('/') 



    app = webapp2.WSGIApplication([('/admin', Admin), ('/', Main), ('/img', Image), ('/movie_data', Movie_Data)], debug=True) 

這是我對home_page HTML:

<html> 
    <body> 
     <table> 
      <th>Top Movies</th> 

      {% for movie in movies %} 
      <tr> 
       <td>{{movie.key().name() }} &nbsp</td> 
      </tr> 
      <tr> 
       <td><a href = "/movie_data?movie_key = {{movie.key()}}"> <img src = "/img?img_id={{movie.key()}}"> </td> 


      </tr> 

      {% endfor %} 

      <a href = "/admin">admin</a> 

     </table> 
    </body> 
</html> 

這是我movie_data的html代碼:

<html> 
    <body> 
     <div> 
      <table> 
       <tr> 
        <td rowspan ="6">{{ movie_data.picture }}</td> 
        <td> Movie Name: {{movie_data.name}}</td> 
       </tr> 
       <tr> 
        <td> Release Date: {{movie_data.release_date}}</td> 
       </tr> 
       <tr> 
        <td> Duration (minutes): {{movie_data.duration}}</td> 
       </tr> 
       <tr> 
        <td> Director: {{movie_data.director}}</td> 
       </tr> 
       <tr> 
        <td> Actors: {{movie_data.actors}}</td> 
       </tr> 
       <tr> 
        <td> Summary: {{movie_data.summary}}</td> 
       </tr> 
       <tr> 
        <td colspan ="2"> {{movie_data.trailer}} </td> 
       </table> 
     </div>  
    </body> 
</html> 

回答

0

Jinja2是unicode-only:You have to pass unicode objects or bytestrings that only consist of ASCII characters to the render function

所以我猜你的movie.name是一個包含非ASCII字符的字節串。

我建議您:

一)在數據庫內存儲Unicode,或

B)轉換爲模板中的Unicode(我不知道這是否可能在Jinja2的)。如果可能的話,這個語法是這樣的:

<td> Movie Name: {{unicode(movie_data.name, "utf8")}}</td> 

我強烈推薦方法a)。如果使用b)(如果該語法在jinja模板中甚至是合法的),則需要知道字節字符串的編碼。

一般的Python技巧是始終使用unicode字符串。含義:

  1. 儘快將外部字符串輸入轉換爲unicode(以下是HTML表單處理的示例)。這被稱爲解碼。 unicode(my_byte_string, encoding)(或my_byte_string.decode(encoding))。 encoding可以是'ascii','utf8'等。
  2. 儘可能晚地將unicode轉換爲字節字符串。如果您需要通過網絡傳輸unicode或寫入文件,通常需要轉換爲字節字符串。這被稱爲編碼。 my_unicode_string.encode(encoding)
  3. 在源代碼中使用unicode文字。使用movie.name = u"Iron Man"代替movie.name = "Iron Man"

編輯

看起來像你的電影保存到數據庫中的Admin.post方法內。要存儲在數據存儲Unicode值,使用如下代碼:

name = unicode(self.request.get('name'), "utf8") 
# and so on for all the StringProperty values 

EDIT 2

根據Python 2.7, Appengine Data Store & Unicode你不需要使用web應用程序或webapp2的時候解碼self.request.get("...")

我會把post方法裏面幾個斷言檢查,如果你走出請求的值實際上的Unicode:

assert isinstance(self.request.get("name"), unicode) 

而且還要檢查你出去的對象屬性數據存儲都是unicode的(在Main.get):

+0

感謝您的快速答覆。你知道如何在數據庫中存儲unicode嗎? – user1123417

+0

我相信你只需在保存對象時將屬性設置爲unicode。 ''movie = Movie(); movie.name = u「鋼鐵俠」; movie.put()''。 – codeape

+0

感謝您的闡述。我試圖將unicode部分添加到代碼中,但它仍然不起作用:\ – user1123417

1

我不認爲依賴於字符串movie_data.name。創建錯誤的實體更有可能是movie_data.image。根據serving blob documentation查看您的相關代碼。

事實上,你需要提供圖片單獨的處理函數,見例如images docs或只需更換:

{{ movie_data.picture }} 

<img src='data:image/png;base64,{{movie_data.picture.encode("base64")}}'>