Myślałam dzielę rozwiązanie opiera się na kilku innych SO odpowiedzi.
Po pierwsze, nie należy próbować i używać układu z Crispy formularzy HTML, ponieważ jest od Jasnego zbyt różni się od domyślnego szablonu formularza Crispy Form zjadł szablon Crispy Form, który współpracuje z Jasnym. Jest to w zasadzie po prostu szablon field.html zaktualizowany za pomocą Jasnego 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> 
<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 %}
drugie, szablon odniesienia przy określaniu układ dla swojej postaci:
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',
)
trzecie, domyślnie nie ma sposobu, aby łatwo usunąć zdjęcie z Jasnym i Django. Podsumowanie zachowania Jasnego here. Zasadniczo Jasny przesyła Brak lub pusty ciąg w zależności od tego, czy obraz nie został zaktualizowany, czy usunięty. Django interpretuje oba te elementy jako obraz, który nie jest aktualizowany, a nie usuwany obraz.
Django używa widgetu ClearableFileInput, który dodaje pole wyboru, które powinno być zaznaczone, jeśli chcesz usunąć plik. Do naśladowania tej funkcji, po prostu dodaje trochę jQuery aby dodać wejście po wybraniu przycisku Usuń i Usuń wejście gdy zmiana lub przycisk wstawić wybrano:
<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>
Zauważysz moją Jasny HTML powyżej została nieznacznie zmodyfikowane, aby uwzględnić identyfikatory dla interesujących tagów, aby ułatwić wybór.
Wydaje się, że jest dużo pracy, ale po jej zakończeniu jest tak łatwy w użyciu, jak zwykłe, chrupiące formy.
Należy pamiętać, że najnowsza wersja chrupiących formularzy utrudnia odniesienie do niestandardowego szablonu z powodu formatowania ciągów znaków. Musiałem zmienić odniesienie do szablonu "template = '% s/file_field.html'" i umieścić plik file_field.html w folderze bootstrap3 na ścieżce szablonu. – freb
Zastosowałem to samo podejście do ClearableFileInput. Chociaż to jest ból, na razie jest to jedyna rozsądna opcja, ponieważ moja cała aplikacja opiera się na chrupiących formach (zmiana teraz i ręczne wprowadzanie formularzy zajęłoby dużo czasu, więc być może w przyszłości :-)). – 4ndr23j