Django Grappelli Tabular Inline добавить новую строку Текстовое поле TinyMCE не редактируется
Я использую кожу django Grappelli для своего проекта.
У меня есть ModelAdmin с табличной встроенной функцией.
Я использую extra = 0, чтобы предотвратить автоматическую вставку пустой строки, когда страница загружена. Он отлично работает.
Теперь, когда я нажимаю на знак +, чтобы вставить новую строку, строка загружается, но текстовое поле tinymce не редактируется.
Кто-нибудь знает, в чем причины и как решить эту проблему?
После прочтения документа:
http://django-grappelli.readthedocs.org/en/latest/customization.html#using-tinymce
Я замечаю:
Использование TinyMCE с Inlines немного сложнее из-за скрытой пустой формы. Вам нужно написать собственный шаблон и использовать встроенные обратные вызовы для
onInit: удалить экземпляры TinyMCE из пустой формы.
onAfterAdded: инициализировать экземпляр TinyMCE из формы.
onBeforeRemoved: удалите экземпляры TinyMCE из формы.
TinyMCE с Inlines не поддерживается по умолчанию.
Любой образец для этого? Я замечаю, что это функции TinyMCE, которые мне нужно изменить.
Ответы
Ответ 1
Похоже, что некоторые из классов CSS и структуры HTML, используемые Grappelli, имеют изменения, поскольку было написано решение Almflm. Тем не менее, я смог изменить hir-решение для работы с Grappelli v2.4.7 и упростил реализацию в этом процессе.
Настройка
- Отмените соответствующий шаблон, скопировав
/PATH/TO/grappelli/templates/admin/edit_inline/stacked.html
в /PATH/TO/YOURMOD/templates/admin/edit_inline/
- На вашем сайте
settings.py
убедитесь, что YOURMOD находится выше grappelli в INSTALLED_APPS
. В противном случае Django продолжит использовать версию шаблона Grappelli.
код
Теперь вам просто нужно сделать две копии вашей копии stacked.html
. Найдите блок javascript, который начинается:
$("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({
... и внесите следующие изменения внутри этого блока:
-
Добавьте функцию onBeforeAdded
, подобную этой (или измените существующую функцию, если она существует, но у меня ее нет):
onBeforeAdded:function(form) {
// New inlines start as a hidden template with class grp-empty-form.
// This contains a textarea, which TinyMCE converts correctly, but
// something about the transformation from template to visible
// form breaks TinyMCE, so we need to remove it from the template and
// then re-add it after the transformation.
// c.f. http://stackoverflow.com/questions/5738173/
if (tinyMCE != undefined) {
django.jQuery('.grp-empty-form').find('textarea').each(function() {
var tid = django.jQuery(this).attr("id");
tinyMCE.execCommand("mceRemoveControl",false,tid);
});
}
},
-
Добавьте в функцию onAfterAdded
следующее: у вас уже есть один, поэтому обязательно измените существующий, а не определяйте новый!):
if (tinyMCE != undefined) {
// re-initialise tinyMCE instances
deselector = tinyMCE.settings.editor_deselector;
django.jQuery(form).find('textarea:not(.'+deselector+')').each(function(k,v) {
var tid = django.jQuery(this).attr('id');
tinyMCE.execCommand('mceAddControl', false, tid);
});
}
// This line is optional. It just ensures that the new inline appears
// un-collapsed, even if inlines are collapsed by default
django.jQuery(form).removeClass("grp-closed").addClass("grp-open");
Что это!
ИЗМЕНИТЬ
Добавлен деселектор в onAfterLoad
- гарантирует, что вы все еще можете определить класс deselector в файле конфигурации tinymce, а встраиваемые строки будут соответствовать этому.
Ответ 2
У меня не было времени, чтобы изучить это более подробно, поэтому я уверен, что там лучшее решение, но это, похоже, работает для меня (проверено с помощью django-grappelli 2.3.5 и django-tinymce 1.5.1a2.
Я предполагаю, что вы используете многострочные строки.
Вы должны переопределить шаблон из grappelli, templates/admin/edit_inline/stacked.html
.
Внутри цикла for-loop, проходящего через inline_admin_formset|formsetsort:sortable_field_name
, сразу после итерации вложенного цикла for inline_admin_form
добавьте этот фрагмент:
{% if forloop.last %}
<script type="text/javascript">
if (tinyMCE != undefined) {
django.jQuery('textarea', '.empty-form').each(function() {
tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
});
}
</script>
{% endif %}
он должен отключить элементы управления tinyMCE для элементов textarea в скрытой "пустой форме", инициализированной встроенным javascript, отображаемым для виджета (ов) tinyMCE.
где-то вокруг строки 133 в исходном шаблоне grappelli вы увидите обращение grp_inline()
. Добавить/изменить аргументы:
$("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({
prefix: "{{ inline_admin_formset.formset.prefix }}",
onBeforeRemoved: function(f) {
if (tinyMCE != undefined) {
// make sure tinyMCE instances in empty-form are inactive
django.jQuery('textarea', '.empty-form').each(function() {
tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
});
}
},
[...]
onAfterAdded: function(form) {
if (tinyMCE != undefined) {
// re-initialise tinyMCE instances
$('textarea', form).each(function(k,v) {
var tid = $(this).attr('id');
tinyMCE.execCommand('mceRemoveControl', false, tid);
tinyMCE.execCommand('mceAddControl', false, tid);
});
// make sure tinyMCE instances in empty-form are inactive
django.jQuery('textarea', '.empty-form').each(function() {
tinyMCE.execCommand('mceRemoveControl', false, django.jQuery(this).attr('id'));
});
}
[...]
}
[...]
Если вы используете сортировки, вы также хотите отключить элементы управления tinyMCE в текстовых областях встроенного перетаскивания. Найдите инициализацию sortable()
и измените обратный вызов "start":
start: function(evt, ui) {
ui.placeholder.height(ui.item.height() + 12);
if (tinyMCE != undefined) {
// make sure tinyMCE instances in empty-form are inactive
$('textarea', ui.item).each(function(k,v) {
var tid = $(this).attr('id');
tinyMCE.execCommand('mceRemoveControl', false, tid);
});
}
},
[...]
Это должно дать общее представление о том, как обойти эту надоедливую проблему...