Version 11 (modified by Peter Bowyer, 8 years ago) (diff)

Added links to TinyMCE's site so others won't have to search for it!

RichTextField

An attempt at integrating TinyMCE completely as its own field that has the capability to save a copy as UTF-8 in another field for searchability.

Adding the field type

project_dir/local_models.py

from django.utils.html import escape
from django.forms import LargeTextField 
from django.db.models.fields import Field
from django.dispatch import dispatcher
from django.db.models import signals
from django.conf import settings

class TextFieldWithClass(LargeTextField):
    def __init__(self, css_class='', plaintext_field=None, *args, **kwargs):
        self.css_class, self.plaintext_field = css_class, plaintext_field
        LargeTextField.__init__(self, *args, **kwargs)

    def render(self, data):
        if data is None:
            data = ''
        if isinstance(data, unicode):
            data = data.encode(settings.DEFAULT_CHARSET)

        css_class = ''
        if self.css_class != '':
            css_class = ' ' + self.css_class

        return '<textarea id="%s" class="v%s%s%s" name="%s" rows="%s" cols="%s">%s</textarea>' % \
            (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
            css_class, self.field_name, self.rows, self.cols, escape(data))

class RichTextFieldWithClass(Field):

    def __init__(self, css_class='', plaintext_field=None, *args, **kwargs):
        self.css_class, self.plaintext_field = css_class, plaintext_field
        Field.__init__(self, *args, **kwargs)

    def set_plaintext_field(self, instance=None):
        from genshi.core import Markup
	plain = Markup(getattr(instance, self.attname)).striptags().stripentities().encode('utf-8')
        setattr(instance, self.plaintext_field, plain) 

    def contribute_to_class(self, cls, name):
        super(RichTextFieldWithClass, self).contribute_to_class(cls, name)
	if self.plaintext_field:
            dispatcher.connect(self.set_plaintext_field, signals.pre_save, sender=cls)

    def prepare_field_objs_and_params(self, manipulator, name_prefix):
        field_objs, params = super(RichTextFieldWithClass, self).prepare_field_objs_and_params(manipulator, name_prefix)
        params['css_class'], params['plaintext_field'] = self.css_class, self.plaintext_field
        return (field_objs, params)

    def get_manipulator_field_objs(self):
        return [TextFieldWithClass]

    def get_internal_type(self):
        return 'TextField'

Adding the neccesary javascript

Download and unpack TinyMCE so tiny_mce.js ends up here: /media/js/tinymce/jscripts/tiny_mce/tiny_mce.js

Remember this javascript must be on the same domain as the admin or it won't work.

/media/js/tmce.js

	tinyMCE.init({
		mode : "specific_textareas", // only specific textareas
                editor_selector : "mceEditor", // specified by the mceEditor class
		theme : "advanced",
		plugins : "table,save,advhr,advimage,advlink",
		theme_advanced_buttons1 : "bold,italic,underline,strikethrough,sub,sup,removeformat,charmap,separator,justifyleft,justifycenter,justifyright,bullist,numlist,outdent,indent,separator,formatselect,styleselect,code",
        theme_advanced_buttons2 : "cut,copy,paste,separator,search,replace,image,link,anchor,separator,tablecontrols",
		theme_advanced_buttons3 : "",
		theme_advanced_toolbar_location : "top",
		theme_advanced_toolbar_align : "left",
		theme_advanced_path_location : "bottom",
		theme_advanced_styles : "Left=left;Right=right;", // possible classes
        content_css : "/media/js/tmce.css", // add css styles
	    plugin_insertdate_dateFormat : "%Y-%m-%d",
	    plugin_insertdate_timeFormat : "%H:%M:%S",
		extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
        width : "640", height : "350" // set size of field
	});

Using the field in the model

project_dir/appdir/models.py

from django.db import models
from local_models import RichTextFieldWithClass

class Page(models.Model):
        
    label = models.CharField(maxlength=255)
    text = RichTextFieldWithClass(css_class='mceEditor', plaintext_field='plaintext')
    plaintext = models.TextField() # optional            optional argument, requires genshi from edgewall

    def __repr__(self):
        return self.label
        
    class Admin:
        js=['../js/tinymce/jscripts/tiny_mce/tiny_mce.js', '../js/tmce.js'] 

Back to Top