我有一个TextField,其中的文本来自admin中的txt文件。我的txt有换行符。问题在于TextField处于readonly_fields中时,所有换行符便宜且所有内容都分组。 如何在readonly_fields模式下使用此字段的格式? 当不在readonly_fields时,问题不会发生。 谢谢!使用admin中的readonly_fields保留TextField中的格式文本
回答
的文本中的换行符通常由字符\n
或\r
或经常\r\n
(看看这个article on wikipedia获取更多信息)表示。
您遇到的问题是这些字符将用于在文本编辑字段中显示新行,但它们不代表html中的新行(它们将被忽略)。
如果您希望它们显示在只读字段中,那么您可以用<br/>
元素替换它们。
如果您可以将您的字符串标记为safe(即,如果您可以安全地添加html代码而没有任何人使用该字段添加恶意代码的风险),那么您可以覆盖模型上的保存方法以换出文本行减免HTML换行符 -
from django.utils.safestring import mark_safe
def save(self, *args, **kwargs):
self.text_field = mark_safe(self.text_field.replace("\n", "<br/>"))
super(YourModel, self).save(*args, **kwargs)
另一种方法是使用一个插件添加全文格式化功能,例如django-tinymce。
我最后的建议是用javascript来破解它。将admin文件夹添加到您的模板中,然后创建一个base_site.html文件,该文件扩展了原始文件并添加了一个简单的javascript函数(如here所述)。喜欢的东西 -
{% extends "admin/base.html" %}
{% block extrahead %}
<script type="text/javascript">
window.onload = function() {
var p_elements = document.getElementById('content-main').getElementsByTagName('p');
var unixNewLine = new RegExp("\n", "g");
for (var i = p_elements.length - 1; i >= 0; i--) {
p_elements[i].innerHTML = p_elements[i].innerHTML.replace(unixNewLine, '<br/>');
}
}
</script>
{% endblock %}
你需要添加一个replace
对每种类型的新线在你的文字(例如\r
,\r\n
)有。虽然这可能会做你所需要的,但它似乎是最糟糕的黑客。
当您查看页面的源代码时,会看到换行符。该空格在浏览器中显示为单个空格。您需要将所有换行符(\n
)转换为HTML换行符(<br />
)以使其看起来像您想要的样子。
选项1:jQuery来拯救。
事情是这样的:
<script type="text/javascript">
(function($) {
$(document).ready(function() {
// Adjustments for read-only fields:
// a) Convert quoted HTML entities back to HTML
$('.readonly').each(function() {
// Ensure there isn't valid html in the field
// The RegEx checks for any valid html opening tag
{% comment %}
TODO: It would be better to check against a special class name
on the widget
{% endcomment %}
if ($(this).html().match(/<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/) == null) {
$(this).html($(this).text());
$('ul', this).addClass('with_bullet');
$('li', this).addClass('with_bullet');
}
});
// b) Insert into empty <p>'s (m2m fields) so they don't break layout
// (see comment on text nodes: http://api.jquery.com/empty-selector/)
$('p.readonly:empty').each(function() { $(this).html(' ') })
});
})(django.jQuery);
</script>
(注:我们增加了“with_bullet”类,因为我们使用格拉佩利和UL的李的get风格没有子弹(列表样式类型:无)等等这是使它们重新出现在我们自己的CSS中的一种方式...) 还要注意最后的布局修复,我认为这在后来的grappelli版本中不需要。
选项2:猴补丁django.contrib.admin.helpers.AdminReadonlyField:
from django.contrib.admin import helpers
from django.contrib.admin.util import (lookup_field,
display_for_field, label_for_field, help_text_for_field)
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.fields.related import ManyToManyRel
from django.forms.util import flatatt
from django.template.defaultfilters import capfirst
from django.utils.encoding import force_unicode, smart_unicode
from django.utils.html import escape, conditional_escape
from django.utils.safestring import mark_safe
class BetterAdminReadonlyField(object):
def __init__(self, form, field, is_first, model_admin=None):
label = label_for_field(field, form._meta.model, model_admin)
# Make self.field look a little bit like a field. This means that
# {{ field.name }} must be a useful class name to identify the field.
# For convenience, store other field-related data here too.
if callable(field):
class_name = field.__name__ != '<lambda>' and field.__name__ or ''
else:
class_name = field
self.field = {
'name': class_name,
'label': label,
'field': field,
'help_text': help_text_for_field(class_name, form._meta.model)
}
self.form = form
self.model_admin = model_admin
self.is_first = is_first
self.is_checkbox = False
self.is_readonly = True
def label_tag(self):
attrs = {}
if not self.is_first:
attrs["class"] = "inline"
label = self.field['label']
contents = capfirst(force_unicode(escape(label))) + u":"
return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
"attrs": flatatt(attrs),
"contents": contents,
})
def contents(self):
from django.contrib.admin.templatetags.admin_list import _boolean_icon
from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
field, obj, model_admin = self.field['field'], self.form.instance, self.model_admin
try:
f, attr, value = lookup_field(field, obj, model_admin)
except (AttributeError, ValueError, ObjectDoesNotExist):
result_repr = EMPTY_CHANGELIST_VALUE
else:
if f is None:
boolean = getattr(attr, "boolean", False)
if boolean:
result_repr = _boolean_icon(value)
else:
result_repr = smart_unicode(value)
if getattr(attr, "allow_tags", False):
result_repr = mark_safe(result_repr)
else:
if value is None:
result_repr = EMPTY_CHANGELIST_VALUE
elif isinstance(f.rel, ManyToManyRel):
result_repr = ", ".join(map(unicode, value.all()))
else:
result_repr = display_for_field(value, f)
return conditional_escape(result_repr)
helpers.AdminReadonlyField = BetterAdminReadonlyField
你可以把这个文件夹中的 “monkeypatches”,并称之为 “admin_readonly_field.py”(不要忘了还添加一个空的__init__.py
使该文件夹成为一个模块)。 然后在你的应用程序的__init__.py
添加
from monkeypatches import admin_readonly_field
和你离开。
上面的代码只包含相关的导入和代码monkeypatch AdminReadonlyField(在这种情况下从Django 1.3复制)。没有什么实际上改变了原来的课程。改变你在你的情况下最有用的东西。
你的具体情况,你可以,也许这两行添加到第二个最后一个:
result_repr = display_for_field(value, f)
if isinstance(field, models.TextField):
result_repr = result_repr.replace('\n', '<br />')
(和from django.db import models
在顶部)
我很抱歉,但该类附带的Django如此糟糕,选项2是我推荐的方式。您的文本字段是不是唯一的领域,看起来以只读模式不好......
我喜欢重写管理域来改变显示的想法。从我+1。 –
jQuery的第一个选择提出了一个期望,即'ModelAdmin.readonly_fields'中列出的字段在呈现时自动获得'readonly' css类。这似乎并不是这样,至少在我使用的Django版本中(1.4.3)。 –
只是意识到你正在使用grappelli。我希望有一种比覆盖模板更简单的方法,或者将整个野兽进行修饰。基本上我只想添加一个css类,但这似乎不可能,'attrs'是硬编码的。我想知道为什么Django不使用(剥离)小部件。 –
我还在使用django 1.3,最后想出了一个解决方案。因此,如果其他人仍然在这艘船上:
覆盖模板fieldset.html(从pythondir/djangodir/django/contrib/admin/templates/admin/includes/fieldset.html复制到djangoprojectdir/templates/admin /包括/ fieldset.html)
它包含行:
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
他们更改为:
{% if field.is_readonly %}
<p>{{ field.contents|linebreaksbr }}</p>
这是试图丹尼的解决方案结束后翅因为从内容函数返回的文本被转义以替换具有转义码的标签(“<”等),然后阅读以下内容:https://code.djangoproject.com/ticket/19226。
- 1. 使用letterings.js保留文本的格式
- 2. 动态设置django中的readonly_fields admin
- 3. 文本框中的文本不保留其格式
- 4. 如何在JavaScript中保留getElementById的文本格式?
- 5. 提取文本和保留格式
- 6. 如何在XSL中调用模板时保留文本格式?
- 7. 如何格式化TextField的文本? JavaFX
- 8. Django的使用readonly_fields
- 9. textfield中的文本
- 10. 如何从richTextbox中读取文本并保留文本的格式?
- 11. 为未来版本保留django-admin更改的最佳方式?
- 12. 如何保留textarea表单文章中的空格和格式?
- 13. 将文本保留在表格单元格的中心底部
- 14. 如何在多行文本框中保留格式
- 15. 如何在OpenXML中使用格式保留字符串段落,运行,文本?
- 16. 在ActionScript 3.0中更改TextField的文本格式
- 17. 在使用JavaScript/HTML处理后保留文本文档的格式
- 18. 结合保留分隔符和格式的文本文件
- 19. ios中textfield中的十进制格式
- 20. 验证TextField中的文本
- 21. 如何使用XSL-FO保留格式(保留CR-LF字符)?
- 22. Excel中使用VBA的文本格式
- 23. 明确格的内容,但保留纯文本,使用jQuery
- 24. 如何在UIAlertController中的块中使用TextField中的文本?
- 25. 使用Crypto ++格式保留加密
- 26. 在文本文件中保留以模式开头的行
- 27. 如何在dateWithTimeIntervalSince1970中使用TextField文本?
- 28. 如何使用固定宽度格式化文本时保留空格?
- 29. 用c#保存XML文件并保留空元素的格式
- 30. 在UITextField中保留文本的视图
如果你保存br标签(它改变了数据),标准textarea不再有换行符,并且像django-tinymce这样的编辑器变得更加必要。如果你需要真正的换行符,你在另一个方向上面临同样的问题... –
是的,这是一个很好的观点。我认为解决方案实际上取决于数据的用途。 –
感谢您的答案,但txt文件的内容是由自定义命令编写的。使用JavaScript也失败了。任何其他想法?谢谢! – LinuxMan