Django - WYSIWYG Editor not displaying in template - django

I am now using django ckeditor as a WYSIWYG editor for adding product information,
previously I was using Summernote, but after moving to production the widget would not display in my template (at all, just a big white space) so I decided to try ckeditor.
However with django CKEditor all I see is a normal textarea, rather than the WYSIWYG editor.
The source code from the template is as follows:
<div class="col-sm-2"> Description:</div><div class="col-sm-10"><div class="django-ckeditor-widget" data-field-id="id_description" style="display: inline-block;">
<textarea cols="40" id="id_description" name="description" rows="10" data-processed="0" data-config='{"toolbar_Basic": [["Source", "-", "Bold", "Italic"]], "language": "en-us", "height": 291, "width": 835, "toolbar": "Full", "skin": "moono", "toolbar_Full": [["Styles", "Format", "Bold", "Italic", "Underline", "Strike", "SpellChecker", "Undo", "Redo"], ["Link", "Unlink", "Anchor"], ["Image", "Flash", "Table", "HorizontalRule"], ["TextColor", "BGColor"], ["Smiley", "SpecialChar"], ["Source"]], "filebrowserWindowWidth": 940, "filebrowserWindowHeight": 725}' data-external-plugin-resources='[]' data-id="id_description" data-type="ckeditortype"></textarea>
My installation process was very simple: install django-ckeditor, (jquery already), add to installed apps, collectstatic, change the widget in my modelform, refresh server.
I am sure there is a simple thing I am missing here but I have no idea what it could be!
Any ideas?

You didn't mention if this is in admin or custom view.
If this is in a custom view check that both the widget .js file and jQuery are linked correctly in your page.
If it's in admin you probably don't have jQuery linked there and should add this to your settings.py:
CKEDITOR_JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
If both do not help share what errors your JS console gives you

Related

Stylized HTML fields in Django admin

I Have TextField to store HTML text. I want to colorize HTML tags. I use TinyMCE but didn't need an HTML editor like WordPress just simple to colorize like IDE, Search a lot but didn't find anything useful, So if you can help I appreciate it.
My field:
I want output like this but changeable:
Using a code editor in Django admin Textarea
The following is implemented with CodeMirror but you can use any other library (Monaco, etc).
Final result:
For all the libraries, we need to add some library specific javascript and stylesheet plus some custom code for integration.
Django has pretty flexible templating to enable this. We can override the entire template or specific blocks. Detailed documentation can be fond here.
To integration CodeMirror, we can override the admin/base.html 's extrahead block. We will include the required js/css, one extra css for theming and some js to find and apply CodeMirror.
Here, I have create a admin/base.html inside my project's configured template directory. This will apply to all the apps and models. There are ways to target an app or model individually - check the office docs.
This works for JSONField data. You will have to tweak a bit to format
html or any other language.
Inspect the page and find id of the textarea you want to target
<!-- tested with Django 3.2.9 -->
{% extends "admin/base.html" %}
{% block extrahead %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.js" crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.css"
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/theme/oceanic-next.min.css"
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/mode/javascript/javascript.min.js"
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
window.addEventListener('load', (event) => {
const target = document.getElementById("id_data");
target.value = JSON.stringify(JSON.parse(target.value), null, ' ');
const config = {
mode: 'javascript',
theme: 'oceanic-next',
lineNumbers: true,
lineWrapping: true
}
const jsonCodeMirror = CodeMirror.fromTextArea(target, config);
jsonCodeMirror.setSize("100%", 600);
});
</script>
{% endblock %}
Multiple textarea inputs can be targeted as well with get element with classname and then looping over the result set and applying the same logic.
For html formatting,
you can use this https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/mode/htmlmixed/htmlmixed.min.js instead of javascript. Delete the json stringify statement. Change mode to htmlmixed.
Don't need to override any template
solved by integrating django-ace field and in this we have support for CSS, python, HTML etc also.
Simply use this in django forms and provide the form in django model admin class
admin file
from appname import forms
#admin.register(models.Table)
class TableModelAdmin(admin.ModelAdmin):
form = forms.TableModelForm
form file
from django import forms
from django_ace import AceWidget
class TableModelForm(forms.ModelForm):
class Meta:
model = models.Table
fields = '__all__'
widgets = {
'columns': AceWidget(
mode='json',
theme='None',
width='1200px',
height='500px',
fontsize='18px',
showprintmargin=False,
),
}

Django markdown show_preview feature throws an error

I am new using markdown. I tried to use the show_preview = False to implement preview using jQuery instead.
class PostForm(forms.ModelForm):
content = forms.CharField(widget=PagedownWidget(show_preview=False))
publish = forms.DateField(widget = forms.SelectDateWidget)
class Meta:
model = Post
fields = [
"title",
"content",
"image",
"draft",
"publish",
]
unfortunately, it throws an error:
line 9, in PostForm
content = forms.CharField(widget=PagedownWidget(show_preview=False))
TypeError: __init__() got an unexpected keyword argument 'show_preview'
I did look into the markdown files and could not find show_preview using except here:
4 <textarea {{ attrs|safe }}>{{ body }}</textarea>
5 </div>
6 {% if show_preview %}
7 <p class="wmd-preview-title">
8 <small>HTML Preview:</small>
I am running:
Django==2.2.6
django-markdown-deux==1.0.5
django-pagedown==2.0.3
Are you following a guide?
Django-pagedown widget used to take a number of arguments (including show_preview). Use version 1.0.6 if you want to do that. v1.0.6 is still compatible with django2.2.x.
Since v2.0.0 it is better to subclass the widget and point it to the template / css to define the preview box, see the docs for that:
Github (see the readme)
Example app with form
You can stop the preview showing by overwriting the CSS. eg, add the following to your .css file in the static folder (and ensure it is being imported into your template). Or just stick it in a style tag at the top of your template.
.wmd-preview{
display: none;
}

Using Bootstrap wysiwyg text editor in Django Form

I am using Django and Bootrap 2.32. I want to include this wysiwyg-bootrap-themed text editor: http://mindmup.github.io/bootstrap-wysiwyg/. The usage of this editor is fairly simple, including
$('#editor').wysiwyg();
in the JS-declaration will render each
<div class=editor></div>
into a beatiful wysiwyg text-editor.
Now the problem: I want to include this editor into one of my django form field. I have the single form:
class Article_Form(ModelForm):
Article_text = CharField(widget=Textarea(attrs = {'id' : 'editor'}))
class Meta:
model= Article
, whereas the Article model includes one simple CharField . Is there any chance, to get the editor work inside the Article_text form-field? With the above-mentioned widget, the created textarea cannot be controlled by the wysiwyg-editor-control buttons. Wrapping the form-template-tag like this
<div id="editor">
{{ Article_Form.Article_text }}
</div>
doesn't work either. The problem thus is that Django creates a textarea, wheras the editor would need a <div> to render correctly. Do you guys have any idea how to get this to work (without refering to django-wysiwyg).
Thanks!
I don't know enough about Django but I wrote the editor you're referring to, so here's a suggestion. Assuming the other answer on this page is correct and you can't generate a div directly, you can generate a text area using whatever Django templates you would normally do, then assign two events:
1) page onload event that would copy the textarea contents into the div, something like
$('#editor').html($('#textarea').val())
2) form onsubmit event that would reverse copy the current div contents into the textarea before it gets submitted
$('#textarea').val($('#editor').html())
Take a look at this.
Summernote is a simple WYSIWYG editor based on Twitter's Bootstrap.
django-summernote plugin allows you to embed Summernote into your Django admin page very handy.
https://github.com/lqez/django-summernote
Are you sure that this "plugin" doesn't work with textarea?
{{ Article_Form.Article_text }}
will be rendered to something like:
<textarea cols="40" id="id_Article_text" name="Article_text" rows="10"></textarea>
So there is a chance that you can initialize the wysiwyg editor like:
$('#id_Article_text').wysiwyg();
However after checking the plugin, I doubt that would be possible since it is using contenteditable="true" attribute of HTML5 and probably the plugin works with div only.
So there is no way you can make it work natively with Django form. The solution should be display other fields of your form manually, hide the one with textarea and display the editor instead:
<form action="" method="POST">
{{ Article_Form.field1 }}
{{ Article_Form.field2 }}
<div class=editor></div>
{% csrf_token %}
<input type="submit" value="Submit" id="submit-btn" />
</form>
Then you can use JS to submit your form:
$('#submit-btn').click(function (e) {
e.preventDefault();
$.ajax({
// do your magic here.
// note that you can get the content of the editor with: $('#editor').cleanHtml();
})
});
This way is hackish I agree so I don't recommend you go for it, just find other plugin then. Also please read PEP 8 carefully.
Hope it helps.
Take a look at this repo: https://github.com/rochapps/django-secure-input
I think it solves most of your problems.

Using TinyMCE how do I limit html while ensuring that styles in the textarea match the styles output to my app

I'm using tinyMCE 3 (in my django app with django-tinymce). It's a very restricted set of html that I want output and I don't want tinyMCE adding inline styles or span elements.
I've used the valid_elements parameter for tinyMCE.init(), but this seems to only effect the html tinyMCE passes to my database - it doesn't seem to control the html in the textarea (spans and inline style are still being added). I want wysiwyg.
I've included my init parameters below (they're in python - django-tinymce passes these to the javascript when tinyMCE is initiated).
TINYMCE_DEFAULT_CONFIG = {
'plugins': "paste",
'paste_remove_styles': 'true',
'paste_remove_styles_if_webkit': 'true',
'paste_strip_class_attributes': 'all',
'content_css': (STATIC_URL + 'css/normalize.css, ' + STATIC_URL +
'css/BrandonG.css, ' + STATIC_URL +
'css/main.css'),
'theme': "advanced",
'theme_advanced_toolbar_location': "top",
'theme_advanced_buttons1': "bold,italic,underline,separator,"
"bullist,separator,outdent,indent,separator,undo,redo,"
"link,unlink",
'theme_advanced_buttons2': "",
'theme_advanced_buttons3': "",
'height': 400,
'valid_elements': "a[!style,href|target=_blank],strong[!style],ul[!style],li[!style],p[!style]"
}
How to I control the html in editing textarea?
To clean on paste use:
http://www.tinymce.com/wiki.php/Plugin3x:paste
You can have advanced control over the html on submit with the new Event API: http://www.tinymce.com/wiki.php/API3:class.tinymce.Editor

Why does a DOJO tools text area control break my forms

Hi I'm using django comments in one of my apps. I customized the comments framework to fit my needs. Everything works properly until I use dojo to make the textarea for the comments expandable http://dojotoolkit.org/reference-guide/1.7/dijit/form/Textarea.html#dijit-form-textarea. After adding the script the form throws an error after submitting: this field is required. So it seems django doesn't recognize the textarea as part of the form anymore.
in my template I use the standart comment tags:
{% render_comment_form for event %}
{% render_comment_list for event %}
When I'm adding the dojo script, the textarea gets expandable, but the form doesn't pass it's value anymore.
dojo.require("dijit.form.Textarea");
dojo.ready(function(){
var textarea = new dijit.form.Textarea({
name: "id_comment",
style: "width:200px;"
}, "id_comment");
});
dojo adds a bunch of classes to the textarea so that it looks like following. But it still got it's id and it's still a textarea isn't it?
<textarea autocomplete="off" data-dojo-attach-point="focusNode,containerNode,textbox" name="id_comment" class="dijitTextBox dijitTextArea dijitExpandingTextArea" style="overflow-y: hidden; overflow-x: auto; -moz-box-sizing: border-box; width: 200px; height: 36px;" tabindex="0" id="id_comment" widgetid="id_comment" value="" rows="1"></textarea>
After reading the answers for this question: Searching for the Ultimate Resizing Textarea. I thought this might the best way to go but unfortunatly it's not.
I'm wondering if it's just me. Is there a way to get this right or should I use a different method to make the field expandable.
Edit
with dojo the post looks like that:
content_type cylebrations.image
csrfmiddlewaretoken 24827190efbb5b7793aeadaf8276beed
honeypot
id_comment ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
object_pk 4
post Post
security_hash 8a091cfbf1e309627369069d4f71c21b33843a85
timestamp 1335209980
without dojo:
comment eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
content_type cylebrations.image
csrfmiddlewaretoken 24827190efbb5b7793aeadaf8276beed
honeypot
object_pk 4
post Post
security_hash e02d8261f528cfc0f22ee30ced820cfbb80715bc
timestamp 1335210114
Dojo overwrites the name of the textarea. I called it id_comment, instead of just comment. After changing that the post looks just fine and everything works like it should:
dojo.require("dijit.form.Textarea");
dojo.ready(function(){
var textarea = new dijit.form.Textarea({
name: "comment",
style: "width:200px;"
}, "id_comment");
});