ruchej
@ruchej
Конструктор мебели. Пишу макросы для К3-Мебель

Как загрузить несколько файлов из формы в DJANGO?

В тостере есть такой вопрос, но нет решения.
Пример по ссылке мне известен.
Вопросы таковы:
  • какая правильная модель для загрузки много файлов для одного контакта?
  • как правильно загрузить полученный список файлов?


На данный момент последним вариантом было следующее.
model.py
from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length=50, verbose_name='Имя')
    phone = models.CharField(max_length=50, verbose_name='Телефон')
    email = models.EmailField(max_length=50, blank=True, verbose_name='email')
    body = models.TextField(verbose_name='Текст сообщения')

    class Meta:
        verbose_name = "Контакт"
        verbose_name_plural = "Контакты"

    def __str__(self):
        return "{} {}".format(self.name, self.phone)

class Files(models.Model):
    file = models.FileField(upload_to='contact', blank=True, null=True, verbose_name='Файл')
    contact = models.ForeignKey(Contact, blank=True, null=True, on_delete=models.CASCADE)

    class Meta:
        verbose_name = "Файлы"
        verbose_name_plural = "Файлы"

    def __str__(self):
        return self.file

forms.py
from django import forms

from .models import Contact

class ContactForm(forms.ModelForm):

    # files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

    class Meta:
        model = Contact
        fields = ('name', 'phone', 'email', 'body')
        # widgets = {
        #     'files': forms.ClearableFileInput(attrs={'multiple': True}),
        # }

view.py
from django.views.generic.edit import FormView
from .forms import ContactForm
from pprint import pprint

class ContactView(FormView):
    form_class = ContactForm
    template_name = 'contact.html'
    success_url = '#' # адрес страницы успеха отправки формы

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('files')
        if form.is_valid():
            pprint(files)
            # for f in files:
                # ...  # Do something with each file.
            return self.form_valid(form)
        else:
            return self.form_invalid(form)



Так же загвоздка в последнем варианте, что я поле для файлов вынес в отдельную модель. Как в одну форму подключить поле с файлом? Создать ещё один класс формы с файлом и унаследовать форму от контактов?
_____________________
Благодарю!
  • Вопрос задан
  • 5382 просмотра
Решения вопроса 1
ruchej
@ruchej Автор вопроса
Конструктор мебели. Пишу макросы для К3-Мебель
Принял такое решение данной задачи. За основу был взять пример из документации.
Суть решения.
Есть две модели: одна это поля для формы связи, вторая хранение файлов.
В файле forms.py пишем класс на основе модели contact. Добавляем поле files со свойствами мультизагрузки.
В представлении получаем список файлов files = request.FILES.getlist('files'). После проверки правильности заполнения формы if form.is_valid() сохраняем содержимое в базу и получаем id этой записи id = form.save().pk. Далее получаем объект contact согласно полученному id - contact = Contact.objects.get(pk=id). Для этого объекта, циклом записываем полученные файлы fl = Files(contact=contact, file = f).
models.py
from django.db import models


class Contact(models.Model):

    name = models.CharField(max_length=50, verbose_name='Имя')
    phone = models.CharField(max_length=50, verbose_name='Телефон')
    email = models.EmailField(max_length=50, blank=True, verbose_name='email')
    body = models.TextField(verbose_name='Текст сообщения')

    class Meta:
        verbose_name = "Контакт"
        verbose_name_plural = "Контакты"

    def __str__(self):
        return "{} {}".format(self.name, self.phone)



class Files(models.Model):

    file = models.FileField(upload_to='contact', blank=True, null=True, verbose_name='Файл')
    contact = models.ForeignKey(Contact, blank=True, null=True, on_delete=models.CASCADE)

    class Meta:
        verbose_name = "Файлы"
        verbose_name_plural = "Файлы"

    def __str__(self):
        return self.file.name

view.py
from django.views.generic.edit import FormView
from .forms import ContactForm
from .models import Contact, Files
import pdb # pdb.set_trace()

class ContactView(FormView):
    form_class = ContactForm
    template_name = 'contact.html'
    success_url = '#' # адрес страницы успеха отправки формы

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('files')
        if form.is_valid():
            id = form.save().pk
            contact = Contact.objects.get(pk=id)
            if files:
                for f in files:
                    fl = Files(contact=contact, file = f)
                    fl.save()
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

forms.py
from django import forms

from .models import Contact


class ContactForm(forms.ModelForm):

    files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}), required=False)

    class Meta:
        model = Contact
        fields = ('name', 'phone', 'email', 'body')

Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Astrohas
@Astrohas
Python/Django Developer
Ответ написан
Комментировать
@ShipOmsk
Пробуйте widget:

forms.py
....
class FileFieldForm(forms.Form):
file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы