django-crispy-forms для загрузки файла jasny

Я использую django-crispy-forms (http://django-crispy-forms.readthedocs.org/), и я пытаюсь использовать загрузку файла Jasny Bootstrap (http://jasny.github.io/bootstrap/javascript.html#fileupload), чтобы моя веб-страница выглядела лучше.

Насколько мне известно, формы Crispy из коробки не поддерживают загрузку файла Jasny. Поскольку я не очень опытен, я пытаюсь использовать все, что доступно в формах Crispy, а не создавать свои собственные объекты макета. Тем не менее, я пытался в течение нескольких дней, и это не работает.

Я знаю, что это неправильный способ сделать это, но моя попытка до сих пор состояла в том, чтобы попытаться использовать Div Crispy-form в forms.py, чтобы заставить django генерировать что-то похожее на пример кода для загрузки файла Jasny.

Код из загрузки файла Jasny:

<div class="fileupload fileupload-new" data-provides="fileupload">
    <div class="fileupload-new thumbnail" style="width: 200px; height: 150px;"><img src="http://www.placehold.it/200x150/EFEFEF/AAAAAA&text=no+image" /></div>
    <div class="fileupload-preview fileupload-exists thumbnail" style="max-width: 200px; max-height: 150px; line-height: 20px;"></div>
    <div>
        <span class="btn btn-file"><span class="fileupload-new">Select image</span><span class="fileupload-exists">Change</span><input type="file" /></span>
    <a href="#" class="btn fileupload-exists" data-dismiss="fileupload">Remove</a>
    </div>
</div>

Выдержка из моего form.py:

       Div(
           HTML("""<div class="fileupload fileupload-new" data-provides="fileupload">
<div class="fileupload-new thumbnail" style="width: 200px; height: 150px;"><img src="http://www.placehold.it/200x150/EFEFEF/AAAAAA&text=no+image" /></div>
        <div class="fileupload-preview fileupload-exists thumbnail" style="max-width: 200px; max-height: 150px; line-height: 20px;"></div>
        <div class"smalltest">
            <span class="btn btn-file"><span class="fileupload-new">Select image</span><span class="fileupload-exists">Change</span>
    """),
          Field('photo1'),
          HTML("""</span><a href="#" class="btn fileupload-exists" data-dismiss="fileupload">Remove</a></div></div>"""),
          css_class = 'photofield'
         ),

Это очень уродливый код, и он не работает, потому что я все еще получаю оригинальную кнопку «Выбрать файл» внутри новых кнопок.

Я очень благодарна всем, кто может помочь! Я очень расстроился и вырвал много волос, пытаясь заставить это работать :(

Большое спасибо.


person soo ling    schedule 25.04.2013    source источник


Ответы (2)


Я думал, что поделюсь своим решением, основанным на нескольких других ответах SO.

Во-первых, вам не следует пытаться использовать Layout из Crispy Forms, потому что HTML из Jasny слишком отличается от стандартного шаблона Crispy Form. Сначала мы создаем шаблон Crispy Form, который работает с Jasny. Это в основном просто шаблон field.html, обновленный Jasny HTML.

file_field.html :

{# Custom Crispy Forms template for rendering an image field. #}
{% load crispy_forms_field %}

{% if field.is_hidden %}
    {{ field }}
{% else %}
    {% if field|is_checkbox %}
        <div class="form-group">
        {% if label_class %}
            <div class="controls col-{{ bootstrap_device_type }}-offset-{{ label_size }} {{ field_class }}">
        {% endif %}
    {% endif %}
    <{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" {% if not field|is_checkbox %}class="form-group{% else %}class="checkbox{% endif %}{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors%}{% if field.errors %} has-error{% endif %}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
        {% if field.label and not field|is_checkbox and form_show_labels %}
            <label for="{{ field.id_for_label }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
                {{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
            </label>
        {% endif %}

        {% if field|is_checkboxselectmultiple %}
            {% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
        {% endif %}

        {% if field|is_radioselect %}
            {% include 'bootstrap3/layout/radioselect.html' %}
        {% endif %}

        {% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
            {% if field|is_checkbox and form_show_labels %}
                <label for="{{ field.id_for_label }}" class="{% if field.field.required %} requiredField{% endif %}">
                    {% crispy_field field %}
                    {{ field.label|safe }}
                    {% include 'bootstrap3/layout/help_text_and_errors.html' %}
                </label>
            {% else %}
                <div class="controls {{ field_class }}">
                  <div class="fileinput fileinput-{% if field.value and field.value.url %}exists{% else %}new{% endif %}" data-provides="fileinput">
                    <div class="fileinput-new thumbnail" style="width: 200px; height: 150px;">
                      <img data-src="holder.js/100%x100%" alt="100%x100%" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTAiIGhlaWdodD0iMTQwIj48cmVjdCB3aWR0aD0iMTkwIiBoZWlnaHQ9IjE0MCIgZmlsbD0iI2VlZSIvPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9Ijk1IiB5PSI3MCIgc3R5bGU9ImZpbGw6I2FhYTtmb250LXdlaWdodDpib2xkO2ZvbnQtc2l6ZToxMnB4O2ZvbnQtZmFtaWx5OkFyaWFsLEhlbHZldGljYSxzYW5zLXNlcmlmO2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjE5MHgxNDA8L3RleHQ+PC9zdmc+" style="height: 100%; width: 100%; display: block;">
                    </div>
                    <div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px; line-height: 10px;">
                      {% if field.value and field.value.url %}
                      <img src="{{ field.value.url }}">
                      {% endif %}
                    </div>
                    {# imgfileinput, imgselect, imremove used for removing image #}
                    <div id="imgfileinput">
                      <span id="imgselect" class="btn btn-default btn-file">
                        <span class="fileinput-new">Select image</span>
                        <span class="fileinput-exists">Change</span>
                        <input id="imgfile" type="file" name="{{ field.name }}">
                      </span>&nbsp
                      <a id="imgremove" href="#" class="btn btn-default fileinput-exists" data-dismiss="fileinput">Remove</a>
                    </div>
                  </div>

                    {# removed {% crispy_field field %} #}
                    {% include 'bootstrap3/layout/help_text_and_errors.html' %}
                </div>
            {% endif %}
        {% endif %}
    </{% if tag %}{{ tag }}{% else %}div{% endif %}>
    {% if field|is_checkbox %}
        {% if label_class %}
            </div>
        {% endif %}
        </div>
    {% endif %}
{% endif %}

Во-вторых, ссылайтесь на шаблон при определении макета формы:

from crispy_forms.layout import Layout, Fieldset, Div, Submit, Reset, HTML, Field, Hidden
class UserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Field('avatar', template='file_field.html'),
            'username',
            'first_name',
            'last_name',
        )

В-третьих, по умолчанию нет возможности легко очистить изображение с помощью Jasny и Django. Краткое описание поведения Jasny можно найти здесь. В основном Jasny отправляет None или пустую строку в зависимости от того, не было ли изображение обновлено или удалено. Django интерпретирует оба из них как изображение, которое не обновляется, а не удаляется.

Django использует виджет ClearableFileInput, который добавляет флажок, который следует установить, если вы хотите удалить файл. Чтобы имитировать эту функциональность, я просто добавил некоторый jQuery, чтобы добавить этот ввод, когда выбрана кнопка удаления, и удалить ввод, когда выбрана кнопка изменения или вставки:

<script>
  // Allow image to be deleted
  $('#imgremove').on('click', function() {
  field_name = $('#imgfile')[0].getAttribute('name');
    $('#imgfileinput').append('<input id="imgclear" type="hidden" name="'+field_name+'-clear" value="on">');
  })
  $('#imgselect').on('click', function() {
    $('#imgclear').remove();
  })
</script>

Вы заметите, что мой HTML-код Jasny выше был немного изменен, чтобы включить идентификаторы для интересующих тегов, чтобы упростить выбор.

Кажется, что это большая работа, но как только она будет сделана, ее так же легко использовать, как и обычные хрустящие формы.

person freb    schedule 19.08.2014
comment
обратите внимание, что самая последняя версия хрустящих форм затрудняет обращение к пользовательскому шаблону из-за форматирования строк. Мне пришлось изменить ссылку на шаблон на template='%s/file_field.html' и поместить файл file_field.html в папку bootstrap3 по пути к шаблону. - person freb; 18.09.2014
comment
Я использовал тот же подход для ClearableFileInput. Хотя это больно, на данный момент это единственный разумный вариант, так как все мое приложение основано на хрустящих формах (изменение его сейчас и реализация форм вручную займет много времени, так что, возможно, в будущем :-)). - person druc0d3s; 08.01.2017

В итоге я не использовал django-crispy-forms, теперь я пишу свой собственный собственный шаблон формы с использованием языка шаблонов Django. загрузка файла Jasny Bootstrap работает таким образом.

person soo ling    schedule 06.08.2013