pythondjangodjango-templatestracwiki-markup

Django + trac-wiki to html markdown 'SafeText' object has no attribute 'get'


I am trying to render trac wiki markdown format as html for display on my website. I tried following this other SO question 'how do i use trac wiki formatting', but the code snippet returns an error when I run it. It should be noted that the question and code are nearly 4 years old. Any idea how I can get this to work?

In my urls.py i simply call the tracwiki (from the snippet) view.

# urls.py

url(r'^$',                       'tracwiki',              name='index'),

# views.py

"""
Usage:

{% load tracwiki %}

{{ object.body|tracwiki }}

# Logic from http://groups.google.com/group/trac-dev/msg/479decac43883dc0
"""

from trac.test import EnvironmentStub, Mock, MockPerm 
from trac.mimeview import Context 
from trac.wiki.formatter import HtmlFormatter 
from trac.web.href import Href

from django.utils.safestring import mark_safe
from django import template
register = template.Library()

env = EnvironmentStub() 
req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'), 
           authname='anonymous', perm=MockPerm(), args={})
context = Context.from_request(req, 'wiki')

@register.filter
def tracwiki(s):
    return mark_safe(HtmlFormatter(env, context, s).generate())

Here is the error returned:

[01/Apr/2014 18:40:53] "GET / HTTP/1.1" 500 60948


AttributeError at /

'SafeText' object has no attribute 'get'

Request Method:     GET
Request URL:    http://xxx.xxx.xxx.xxx/
Django Version:     1.5.5
Exception Type:     AttributeError
Exception Value:    

'SafeText' object has no attribute 'get'

Exception Location:     /mysite/local/lib/python2.7/site-packages/django/middleware/clickjacking.py in process_response, line 30
Python Executable:  /Envs/mysite/bin/python
Python Version:     2.7.5

Solution

  • The problem is that you have created a custom template filter, but you have saved it in views.py, so django is treating it like a view. This is wrong - your code doesn't belong in views.py and you don't need to add anything to urls.py. To elaborate...

    With your current configuration, when a request to your site root is picked up by the URLConf (via the '^$' pattern you added), django expects the tracwiki() function to return a HttpResponse object - because it thinks that this is a view.

    However if we look at this tracwiki() function, you can see we do not return a HttpResponse object via render() or render_to_response() etc. Instead we are returning a SafeText object which does not have a .get() attribute, unlike a HttpResponse object, hence the exception when the middleware calls .get() on the object we returned.

    Instead you need to remove the line you added to your urls.py, and use the template filter inside the appropriate HTML template where you want to render this markup. For example

    {{ some_variable|tracwiki }}
    

    If you are unfamiliar with template filters, here are some built-in filters being used.

    You also need to move the tracwiki() logic out of the views.py file and into a new module inside a new templatags directory. Read more about that in the docs (but remember you will need to load this new module inside the template before you call the filter)

    {% load new_filter_module %}