I'm trying to get my Twitter timeline on my website which I'm making in Django. To do so, I've found a nice piece of code on http://www.pixeldonor.com/blog/2010/aug/15/create-simple-twitter-app-django/ which I implemented on my local development copy of the website. Locally everything works perfectly! The tweets are shown and I get no errors what so ever.
Now that I've deployed my website online, I seem to have run into an error which I can't solve.
This is the error I get:
TemplateSyntaxError at /
Caught TypeError while rendering: must be string or buffer, not None
Request Method: GET
Request URL: http://marcostrijker.com/
Django Version: 1.3
Exception Type: TemplateSyntaxError
Exception Value: Caught TypeError while rendering: must be string or buffer, not None
Exception Location: /home/mstrijker/lib/python2.7/oauth2-1.5.170py2.7.egg/oauth2/__init__.py in sign_request, line 493
Python Executable: /usr/local/bin/python
Python Version: 2.7.1
Python Path:
['/home/ms开发者_运维技巧trijker/webapps/django/vorm4ufolio',
'/home/mstrijker/webapps/django',
'/home/mstrijker/webapps/django/lib/python2.7',
'/home/mstrijker/lib/python2.7/oauth2-1.5.170-py2.7.egg',
'/home/mstrijker/lib/python2.7/httplib2-0.6.0-py2.7.egg',
'/home/mstrijker/lib/python2.7/pip-1.0.1-py2.7.egg',
'/home/mstrijker/lib/python2.7',
'/usr/local/lib/python27.zip',
'/usr/local/lib/python2.7',
'/usr/local/lib/python2.7/plat-linux2',
'/usr/local/lib/python2.7/lib-tk',
'/usr/local/lib/python2.7/lib-old',
'/usr/local/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/site-packages',
'/usr/local/lib/python2.7/site-packages/PIL']
Server time: Thu, 12 May 2011 21:05:17 +0200
After that it displays the following:
Template error
In template /home/mstrijker/webapps/django/vorm4ufolio/templates/index.html, error at line 85
Caught TypeError while rendering: must be string or buffer, not None
<div id="twitter">
<a href="http://twitter.com/#!/Octopixell"><img src="{{ STATIC_URL }}images/twitter_icon.png" alt="twitter_logo"></a>
<div id="tweetcontainer">
{% get_tweet_list 5 as tweets %}
{% for tweet in tweets %}
<div class="tweettop"></div>
<div class="tweet">
{{ tweet.text|safe|twitterize }} <br /> {{ tweet.created_at|date:"M d, Y" }}
</div>
<div class="tweetbottom"></div>
{% endfor %}
</div>
</div>
{% get_tweet_list 5 as tweets %}
is line 85
Also here is the traceback of the error:
Traceback:
File "/home/mstrijker/webapps/django/lib/python2.7/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/home/mstrijker/webapps/django/vorm4ufolio/portfolio/views.py" in index
17. return render_to_response('index.html', {'new_list': new_list,}, context_instance=RequestContext(request))
File "/home/mstrijker/webapps/django/lib/python2.7/django/shortcuts/__init__.py" in render_to_response
20. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "/home/mstrijker/webapps/django/lib/python2.7/django/template/loader.py" in render_to_string
188. return t.render(context_instance)
File "/home/mstrijker/webapps/django/lib/python2.7/django/template/base.py" in render
123. return self._render(context)
File "/home/mstrijker/webapps/django/lib/python2.7/django/template/base.py" in _render
117. return self.nodelist.render(context)
File "/home/mstrijker/webapps/django/lib/python2.7/django/template/base.py" in render
744. bits.append(self.render_node(node, context))
File "/home/mstrijker/webapps/django/lib/python2.7/django/template/debug.py" in render_node
73. result = node.render(context)
File "/home/mstrijker/lib/python2.7/oauth2-1.5.170-py2.7.egg/oauth2/__init__.py" in request
662. req.sign_request(self.method, self.consumer, self.token)
File "/home/mstrijker/lib/python2.7/oauth2-1.5.170-py2.7.egg/oauth2/__init__.py" in sign_request
493. self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest())
Exception Type: TemplateSyntaxError at /
Exception Value: Caught TypeError while rendering: must be string or buffer, not None
I hope this will provide you guys with the necessary information required to help me solve this problem. If you guys need more info or code just ask me and I'll provide it.
I skimmed through the post the code of oauth2 and I doubt the default value of post_body in the signature of oauth_req should be '', not None.
def oauth_req(url, http_method="GET", post_body=None, http_headers=None):
Try it.
This issue is that there is a bug in the python-oauth2 module where a TypeError is thrown when the body of the request (or a followed request) is None
. Here is the sign_request function in oauth2/\_\_init\_\_.py
:
def sign_request(self, signature_method, consumer, token):
"""Set the signature parameter to the result of sign."""
if not self.is_form_encoded:
# according to
# http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
# section 4.1.1 "OAuth Consumers MUST NOT include an
# oauth_body_hash parameter on requests with form-encoded
# request bodies."
self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest())
if 'oauth_consumer_key' not in self:
self['oauth_consumer_key'] = consumer.key
if token and 'oauth_token' not in self:
self['oauth_token'] = token.key
self['oauth_signature_method'] = signature_method.name
self['oauth_signature'] = signature_method.sign(self, consumer, token)
Line 493 is:
self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest())
So somehow the body is being set to None
. Since httplib2 sets the request body to None
when following redirects, my guess is that when you deployed online, there's a new redirect somewhere that httplib2 is following, which then sets the body to None
and raises this error.
The good news is that this is a bug I've fixed and issued a pull request. Until it is accepted, you can either edit your own oauth2/\_\_init\_\_.py
file to handle the case where the body is None
or download and use my version of python-oauth.
精彩评论