2013-02-04 2 views
4

admin의 txt 파일에 텍스트가있는 TextField가 있습니다. 내 txt에는 줄무늬가 있습니다. 문제는 TextField가 readonly_fields에 있고, 모든 linebreaks가 dissaper되고 모든 내용이 그룹화 될 때입니다. readonly_fields 모드에서이 필드를 사용하여 형식을 유지하는 방법은 무엇입니까? readonly_fields가 아닌 경우 문제가 발생하지 않습니다. 감사합니다.admin에서 readonly_fields를 사용하여 TextField에 형식 텍스트 유지

답변

1

줄 바꿈은 일반적으로 문자 \n 또는 \r 또는 자주 \r\n (자세한 내용은이 article on wikipedia 체크 아웃)에 의해 표현된다 ... 읽기 전용 모드에서 나쁜 보이는 필드의 유일한 종류가 아닙니다.

문제는 이러한 문자가 텍스트 편집 필드에 새 줄을 표시하는 데 사용되지만 html의 새 줄을 나타내지 않는다는 것입니다 (무시됩니다).

읽기 전용 필드에 표시하려면 <br/> 요소로 바꿀 수 있습니다.

문자열을 safe으로 표시 할 수있는 경우 (즉, 필드를 사용하여 악성 코드를 추가하는 위험없이 html 코드를 안전하게 추가 할 수있는 경우) 모델의 save 메소드를 재정 의하여 텍스트 행을 바꿀 수 있습니다 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로 해킹하는 것입니다. 템플릿에 관리자 폴더를 추가 한 다음 원본을 확장하고 간단한 자바 스크립트 함수 (here)를 추가하는 base_site.html 파일을 만듭니다. 당신은 당신이 당신의 텍스트 (예를 들어 \r, \r\n)에있는 새로운 라인의 모든 유형에 대한 replace를 추가해야합니다

{% 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 %} 

-처럼 뭔가. 이것이 당신이 필요로하는 것을 할 수있는 동안, 모두의 가장 더러운 선전 같이 보인다.

+0

데이터를 변경하는 br 태그를 저장하면 표준 텍스트 영역에 줄 바꿈이 더 이상 나타나지 않으며 django-tinymce와 같은 편집기가 필요합니다. 실제 줄 바꿈이 필요한 경우 다른 방향으로 같은 문제가 발생합니다. –

+0

예, 좋은 지적입니다. 솔루션은 실제로 데이터가 무엇인지에 달려 있다고 생각합니다. –

+0

해답을 보내 주셔서 감사하지만 txt 파일의 내용은 사용자 지정 명령에 의해 작성되었습니다. 자바 스크립트 사용도 실패했습니다. 다른 아이디어? 감사! – LinuxMan

2

페이지 원본을 볼 때 줄 바꿈이 표시됩니다. 그 공백은 단일 공간처럼 브라우저에 표시됩니다. 원하는 줄을보기 위해 모든 줄 바꿈 (\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 &nbsp; 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('&nbsp;') }) 
     }); 
     })(django.jQuery); 
    </script> 

(NB : 우리가 grappelli 사용하는과 UL의 및 선형의 GET 총알 (목록 스타일 타입없이 스타일 때문에 우리가 "with_bullet"클래스를 추가 : 없음) 그래서 이것은 우리 CSS로 다시 나타나게하는 방법입니다 ...) 마지막에 레이아웃을 수정했는데 그 이후 버전의 grappelli에는 필요하지 않습니다.

옵션 2 : monkeypatch 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 

을 추가로 당신은 멀리있어.

위 코드는 AdminReadonlyField (이 경우 Django 1.3에서 복사 됨)를 monkeypatch하는 관련 가져 오기 및 코드 만 포함합니다. 실제로 원래 수업에서 변경된 것은 없습니다. 자신의 상황에서 가장 유용하다고 생각되는 것을 변경하십시오.

특정 경우에 당신은 아마 두 번째 마지막으로이 두 줄을 추가 할 수 있습니다

 result_repr = display_for_field(value, f) 

     if isinstance(field, models.TextField): 
      result_repr = result_repr.replace('\n', '<br />') 

(그리고 from django.db import models 상단)

미안하지만 클래스 그 배를 장고와 함께 그렇게 나쁘다면, 옵션 2가 이것을 권장하는 나의 방법입니다. 당신의 텍스트 필드는 텍스트

+0

관리자 필드를 재정의하여 표시를 변경하는 것이 좋습니다. +1. –

+0

jQuery로 첫 번째 옵션을 사용하면'ModelAdmin.readonly_fields'에 나열된 필드가 렌더링 될 때 자동으로'readonly' css 클래스를 가져올 것이라는 기대가 높아집니다. 적어도 내가 사용하고있는 장고 버전에서는 그렇지 않다. (1.4.3). –

+0

그냥 당신이 grappelli를 사용하고 있다는 것을 깨달았습니다. 템플릿을 무시하거나 전체 짐승을 monkeypatch하는 것보다 쉬운 방법이 있었으면합니다. 기본적으로 나는 단지 CSS 클래스를 추가하고 싶지만 가능하지는 않을 것입니다.'attrs'는 하드 코딩되어 있습니다. Django가 이것을 위해 (위장 처리 된) 위젯을 사용하지 않는 이유가 궁금합니다. –

3

저는 여전히 django 1.3을 사용 중이며 결국 해결책을 찾아 냈습니다. 이 보트에 아직 다른 사람이있는 경우 :

python/djangodir/django/contrib/admin/templates/admin/includes/fieldset.html에서 djangoprojectdir/templates/admin/templates로 복사 된 fieldset.html 템플릿을 덮어 씁니다. 이 대니의 솔루션 엔드 핀을 시도 이후

     {% if field.is_readonly %} 
          <p>{{ field.contents|linebreaksbr }}</p> 

:에

     {% if field.is_readonly %} 
          <p>{{ field.contents }}</p> 

변경 :/fieldset.html)

이 포함 된 라인을 포함 contents 함수에서 반환 된 텍스트가 이스케이프 코드 ("<"등의 경우 "<")로 태그를 바꾸기 위해 이스케이프 처리 된 다음 작동하지 않는다고 표시 한 후이 내용을 읽습니다. https://code.djangoproject.com/ticket/19226.

관련 문제