Code


Version 7 (modified by anonymous, 6 years ago) (diff)

added mark_safe for render output

Custom Widgets - TinyMCE

With the introduction of the newforms module in revision [3944] came the functionality to create custom widgets for forms. Outlined below is the process of creating a custom reusable TinyMCE widget. Please Note - django.newforms is a work in progress.

To start the custom widget, create a custom_widgets.py file in your project folder

for the TinyMCE widget utilise the code below

from django.newforms import *
from django.newforms.widgets import flatatt
from django.newforms.util import smart_unicode
from django.utils.html import escape
from django.utils.simplejson import *
from django.utils.safestring import mark_safe
        
class TinyMCE(Textarea):
    """
    TinyMCE widget. requires you include tiny_mce_src.js in your template
    you can customize the mce_settings by overwriting instance mce_settings,
    or add extra options using update_settings
    """ 
    
    mce_settings = dict(
        mode = "exact",
        theme = "simple",
        theme_advanced_toolbar_location = "top",
        theme_advanced_toolbar_align = "center",
    )    
             
    def update_settings(self, custom):
        return_dict = self.mce_settings.copy()
        return_dict.update(custom)
        return return_dict
    
    def render(self, name, value, attrs=None):
        if value is None: value = ''
        value = smart_unicode(value)
        final_attrs = self.build_attrs(attrs, name=name)
                   
        self.mce_settings['elements'] = "id_%s" % name
        mce_json = JSONEncoder().encode(self.mce_settings)
        
        return mark_safe(u'<textarea%s>%s</textarea> <script type="text/javascript">\
                tinyMCE.init(%s)</script>' % (flatatt(final_attrs), escape(value), mce_json))

in the views.py file, import the custom_widget.py file (replace myproject below) and create a form which will use the new TinyMCE widget.

from myproject.custom_widgets import TinyMCE
from django.newforms import Form
from django.newforms.widgets import Textarea
from django.newforms.fields import CharField
from django.shortcuts import render_to_response

cust = dict( auto_resize = True )

class TestForm(Form):
    #test with custom settings
    test_mce = CharField(widget=TinyMCE())
    test_mce.widget.mce_settings = test_mce.widget.update_settings(cust)
    #test with no custom settings
    another_test = CharField(widget=TinyMCE())
    #plain old textarea
    plain_textarea = CharField(widget=Textarea)

def index(request):
    test_form = TestForm(auto_id='id_%s')
    return render_to_response('index.html', {'test_form': test_form })

In your template file simply add the following, replace http://localhost/ with the location of the tinyMCE source served on your media server.

<html>
<script src="http://localhost/tiny_mce/tiny_mce_src.js"></script>
<head>
    
</head>
<body>

<table>
{{ test_form.as_table }}
</table>

</body>

<html>

This implementation has the following flaw

  1. It requires the template author to include the javascript source in every template which displays a TinyMCE widget. (although adding a "TinyMCE" block in the main template in the header and populate from the view also works)