Как реализовать страницу предварительного просмотра с файлами Django?
У меня есть модель News:
class News(models.Model):
subject = models.CharField(max_length=30)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
У меня также есть модель File для хранения файлов и модель NewsFile для связи моделей друг с другом:
class File(models.Model):
file = models.FileField(
'файл'
)
class NewsFile(models.Model):
file = models.ForeignKey(
File,
on_delete=models.CASCADE,
verbose_name='файл',
related_name='news_files'
)
news = models.ForeignKey(
News,
on_delete=models.CASCADE,
verbose_name='новость',
related_name='files'
)
Вот моя новостная форма:
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = single_file_clean(data, initial)
return result
class NewsForm(forms.ModelForm):
files = MultipleFileField(required=False)
class Meta:
model = News
fields = ('subject', 'text')
Хочу сделать страницу с предпросмотром новостей и кнопками для публикации или редактирования новостей. Я начал реализовывать кнопку публикации, но не могу передать файлы через форму. Мой взгляд:
def form_valid(self, form):
files = form.cleaned_data.get('files')
if self.request.GET.get('save') == 'true':
res = super().form_valid(form)
for file in files:
file_obj = File.objects.create(file=file)
NewsFile.objects.create(news=self.object, file=file_obj)
return res
img_files = []
non_img_files = []
for file in files:
if file.name.split('.')[-1] in settings.IMAGE_FORMATS:
img_files.append(file)
else:
non_img_files.append(file)
images = []
for file in img_files:
encoded = b64encode(file.read())
b64str = encoded.decode('utf-8')
mime = 'image/jpeg'
mime = mime + ";" if mime else ";"
images.append('data:%sbase64,%s' % (mime, b64str))
context = {
'form': form,
'images': images,
'non_img_files': non_img_files,
'date': datetime.datetime.now()
}
return render(
self.request,
'news/news_preview.html',
context=context
)
Форма отображается в HTML без файлов.
<nav class="navbar">
<div class="container">
<a class="btn btn-secondary grey-btn" href="#">edit</a>
<form method="post" enctype="multipart/form-data" action="{% url 'news:news_create' %}?save=true">
{% csrf_token %}
{% for field in form %}
{{ field|hidden }}
{% endfor %}
<button type="submit" class="btn btn-secondary grey-btn">publish</button>
</form>
</div>
</nav>
Надеюсь, я достаточно ясно объяснил суть проблемы. Прошу прощения за языковые ошибки.
Я думаю о сохранении новостей без их публикации или кэшировании файлов, но я не думаю, что это хороший подход.