tôi nghĩ rằng tôi muốn chia sẻ giải pháp của tôi dựa trên một vài SO câu trả lời khác.
Trước tiên, bạn không nên cố gắng và sử dụng Giao diện từ hình thức chiên giòn vì HTML từ Jasny là quá khác với mẫu Crispy Form mặc định. ăn một mẫu Crispy Form làm việc với Jasny. Về cơ bản, đây chỉ là mẫu field.html được cập nhật với mã HTML của Jasny.
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 %}
Thứ hai, tham khảo mẫu khi xác định bố trí cho hình của bạn:
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',
)
Thứ ba, theo mặc định không có cách nào để dễ dàng xóa các hình ảnh với Jasny và Django. Bạn có thể tìm thấy bản tóm tắt về hành vi của Jasny here. Về cơ bản Jasny gửi một Không có, hoặc một chuỗi trống tùy thuộc vào nếu hình ảnh không được cập nhật hoặc loại bỏ. Django giải thích cả hai hình ảnh này là hình ảnh không được cập nhật, không phải hình ảnh bị xóa.
Django sử dụng tiện ích ClearableFileInput có thêm hộp kiểm cần được chọn nếu bạn muốn xóa tệp. Để bắt chước chức năng này, tôi chỉ cần thêm một số jQuery để thêm vào này khi nút remove được chọn và loại bỏ các đầu vào khi thay đổi hoặc nút chèn được chọn:
<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>
Bạn sẽ nhận thấy Jasny HTML của tôi ở trên đã được hơi được sửa đổi để bao gồm id cho các thẻ quan tâm để làm cho việc lựa chọn dễ dàng hơn.
Có vẻ như rất nhiều công việc nhưng sau khi hoàn thành, nó dễ sử dụng như các hình thức giòn đơn giản.
lưu ý rằng phiên bản mới nhất của các biểu mẫu giòn khiến cho việc tham chiếu một mẫu tùy chỉnh trở nên khó khăn hơn do định dạng chuỗi. Tôi đã phải thay đổi tham chiếu mẫu thành "template = '% s/file_field.html'" và đặt tệp file_field.html trong thư mục bootstrap3 trên đường dẫn mẫu. – freb
Tôi đã làm theo cách tiếp cận tương tự cho ClearableFileInput. Mặc dù đó là một nỗi đau, vì lúc này nó là lựa chọn hợp lý vì toàn bộ ứng dụng của tôi dựa trên các hình thức giòn (thay đổi nó ngay bây giờ và thực hiện các biểu mẫu thủ công sẽ mất rất nhiều thời gian, vì vậy có lẽ trong tương lai :-)). – 4ndr23j