Фон: У меня есть две модели: SellingItem и SellingItemImages. SellingItemImages имеет собственный FileField, который может принимать несколько файлов. Поместив две формы (itemform и imageform) в один элемент (enctype = "multipart / form-data"), я смог позволить пользователям загружать несколько изображений. Теперь я хочу включить оптимизацию изображений на стороне клиента и улучшенный пользовательский интерфейс. Я опробовал filepond, но столкнулся с некоторыми проблемами. Я организовал этот пост по
- , показывающему код django без filepond
- , показывающий код с filepond, что
- Я достиг с filepond
- вопросов почто делать дальше
** 1) код django без filepond. ** models.py
# models.py
class SellingItem(models.Model):
seller = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
description = models.CharField(max_length= 500, null=True, blank=True)
price = models.IntegerField(default=0)
class SellingItemImages(models.Model):
sellingitem = models.ForeignKey(SellingItem, default = None, on_delete=models.CASCADE, related_name='images')
image = ContentTypeRestrictedFileField(content_types=['image/png', 'image/jpeg','image/jpg'],blank=True,
max_upload_size=5242880)
#ContentTypeRestrictedFileField is a custom FileField.
вот Forms.py
class SellingItemForm(forms.ModelForm):
class Meta:
model = SellingItem
fields = ('name', 'description', 'price')
class SellingItemImagesForm(forms.ModelForm):
class Meta:
model = SellingItemImages
fields= ('image',)
widgets = {
'image': forms.FileInput(attrs={'multiple':True,}),
}
Вот так выглядит views.py
@login_required
def post_newitem(request):
if request.method == 'POST':
itemform = SellingItemForm(request.POST)
imageform = SellingItemImagesForm(request.POST, request.FILES)
if '_cancel' in request.POST:
itemform = SellingItemForm()
imageform = SellingItemImagesForm()
return render(request, 'market/post_newitem.html',
{'itemform': itemform, 'imageform': imageform})
else:
if '_publish' in request.POST:
print('hit publish')
if itemform.is_valid() and imageform.is_valid():
print('two forms are valid')
sellingitem = itemform.save(commit=False)
sellingitem.seller = request.user
sellingitem.published_date = timezone.now()
sellingitem.save()
files = request.FILES.getlist('image')
for f in files:
photo = SellingItemImages(sellingitem=sellingitem, image=f)
photo.save()
return redirect('market_home')
else:
print(itemform.errors, imageform.errors)
else:
itemform = SellingItemForm()
imageform = SellingItemImagesForm(request.POST)
return render(request, 'market/post_newitem.html',
{'itemform': itemform, 'imageform': imageform})
Вот шаблон post_newitem.html. Здесь я поместил две формы под одним элементом.
{% extends 'market/marketbase.html' %}
{% block content %}
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in itemform.hidden_fields %}
{{ hidden }}
{% endfor %}
{% load widget_tweaks %}
<table>
<tr>
<td>{{ itemform.name |add_class:"name_form_field"}}</td>
</tr>
<tr>
<td>{{ itemform.description |add_class:"description_form_field" }}</td>
</tr>
<tr>
<td>{{ itemform.price |add_class:"price_form_field" }}</td>
</tr>
{% for hidden in imageform.hidden_fields %}
{{ hidden }}
{% endfor %}
<tr>
<td>
{{ imageform.image |add_class:"image_form_field" }}
</td>
</tr>
</table>
<input class='edit-delete-buttons' type="submit" name="_publish">
<input class='edit-delete-buttons' type="submit" name="_cancel">
</form>
{% endblock %}
Приведенный выше код позволяет пользователям загружать несколько изображений. Как упоминалось ранее, для улучшения пользовательского интерфейса и оптимизации изображений на стороне клиента я обратился к этой прекрасной библиотеке JavaScript, filepond.
2) с filepond
<script>
document.addEventListener('DOMContentLoaded', function() {
// Create FilePond object
const inputElement = document.querySelector('input[type="file"]');
const pond = FilePond.create(inputElement, {
// track addfile event
onaddfile: (err, fileItem) => {
console.log(err, fileItem.getMetadata('resize'));
},
// to see whether all files are processed
onprocessfiles: () => {
console.log('process finished for all files');
},
// show when a file is reverted
onprocessfilerevert: (fileItem) => {
console.log(fileItem + 'is reverted');
},
});
});
FilePond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginImageCrop,
FilePondPluginImageTransform,
FilePondPluginFileValidateType,
FilePondPluginImageResize);
var csrf_token="{{ csrf_token }}";
FilePond.setOptions({
imagePreviewHeight: 100,
allowMultiple: true,
imageCropAspectRatio: 1,
imageResizeTargetWidth: 256,
imageResizeMode: 'contain',
imageTransformOutputQuality: 80,
maxFiles: 4,
server: {
// url, none, because endpoints located on the same server
process: {
headers: {"X-CSRFToken":csrf_token,},
url: '/media/',
method: 'POST',
},
revert: {
headers: {
"X-CSRFToken":csrf_token,
},
url: '/media/',
method: 'DELETE',
},
fetch: null,
load: null,
}
});
</script>
3) что я сделал с filepond до сих пор
С помощью приведенного выше кода я смог a. показать область перетаскивания filepond b. показать предварительный просмотр изображения c. filepond, показывающий, что загрузка завершена, как показано на следующем рисунке d. в консоли Chrome Develop Tools, показывая «процесс завершен для всех файлов»
изображение, показывающее область перетаскивания filepond после выбора двух файлов
4) вопросы о том, чтосделать следующее
a: связанный с сервером: Я понимаю, что зеленая подсветка с надписью "загрузка завершена" предназначена для пользователей. Это не обязательно означает, что файл загружен на сервер.
Были ли файлы загружены на сервер? Является ли мой сервер конфигурации. верный? Как узнать, загружены ли файлы на сервер (с помощью консоли)?
b: django связанный: как только файлы загружены на сервер, как можно получить эти файлы и указать нужные модели django (вмой случай, SellingItemsImages)?
Я попытался files = request.FILES.getlist ('filepond'), как показано в этом сообщении , но файлы вернули пустой список. Я не знаю, если это потому, что этот фрагмент не работает, или это потому, что у меня нет загруженных файлов для начала.
c: django форма связана: как упомянуто в фоновом режиме, у меня есть дваформы, одна обычная форма с именем, ценой и т. д .;еще один для загрузки изображений. Без filepond я отправлял обе формы с помощью одной кнопки отправки в одном представлении post_newitem. С filepond, я думаю, у меня есть несколько вариантов: - вариант 1: отправлять обычную форму с кнопкой отправки, а отправлять файлы filepond асинхронно. - вариант 2: позволить filepond оптимизировать изображения (через transmpmpgin) и отправлять изображения и другие области формы (имя, цена и т. д.) в виде FormData.
Я надеюсь получить некоторую информацию о плюсах и минусах этих двух вариантови как поступить с этими двумя вариантами.