Как загрузить файлы через CreateView, используя встроенный набор форм? - PullRequest
0 голосов
/ 11 мая 2019

Я не могу получить файлы для загрузки через CreateView, используя встроенный набор форм.

В идеале, это должно быть несколько файлов, похожих на поведение на странице администратора, но на данный момент я пытаюсь получить хотя бы один файл. В следующем примере одна мастерская должна иметь несколько файлов.

При загрузке все сохраняет кроме файла конечно

models.py

...


class Workshop (models.Model):
    title = models.CharField(max_length=120)
    created_by = models.ForeignKey(User)
    slug = models.SlugField(blank=True, null=True, unique=True)

    def __str__(self):
        return self.title

...

def upload_workshop_file_loc(instance, filename):
    slug = instance.workshop.slug
    if not slug:
        slug = unique_slug_generator(instance.workshop)
    location = "workshop/{}/".format(slug)
    return location + filename


class WorkshopFile(models.Model):
    workshop = models.ForeignKey(Workshop, related_name='files', on_delete=models.CASCADE)
    name = models.CharField()
    file = models.FileField(
        upload_to=upload_workshop_file_loc,
        null=True,
        validators=[FileExtensionValidator
(allowed_extensions=['pdf', 'ppt'])]
    )

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

...

forms.py

from django import forms
from .models import Workshop, WorkshopFile
from django.forms.models import inlineformset_factory


class AddWorkshopForm(forms.ModelForm):

    class Meta:
        model = Workshop
        exclude = []


FileFormSet = inlineformset_factory(Workshop,
WorkshopFile,
fields=['workshop','name', 'file'],
exclude=[], 
extra=1, 
can_delete=True
)

Скорее всего виновник

views.py

...
class AddWorkshopView(LoginRequiredMixin, CreateView):

    model = Workshop
    form_class = AddWorkshopForm
    template_name = "modules/add-workshop.html"
    success_url = "/modules/workshop-list/"

    def post(self, request, *args, **kwargs):
        form = AddWorkshopForm(request.POST, request.FILES)
        workshop = form.save(commit=False)
        workshop.save()
        workshop.created_by = request.user
        return redirect('modules:workshop', workshop.slug)


    def get_context_data(self, **kwargs):
        data = super(AddWorkshopView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['files'] = FileFormSet(self.request.POST)
        else:
            data['files'] = FileFormSet()
        return data


    def form_valid(self, form):
        context = self.get_context_data()
        files = context['files']

        with transaction.atomic():
            form.instance.created_by = self.request.user
            form.instance.updated_by = self.request.user
            self.object = form.save()

        if files.is_valid():
            files.instance = self.object
            files.save()

        return super(AddWorkshopView, self).form_valid(form)
...

надстройка workshop.html

...
  <div>
    <form method="post" action='' enctype='multipart/form-data'>
{% csrf_token %}
      {{ form | crispy }}
      <hr/>
        <div>
        {{ files | crispy }}
        </div>

      <input type="submit" class="btn btn-primary btn-md float-left" value="Save" />
    </form>
  </div>
...

1 Ответ

0 голосов
/ 11 мая 2019

Вы не должны переопределять post метод - он вызывает form_valid за сценой, поэтому он не обрабатывает форму.Другое дело, что ваш FileFormSet не получает request.FILES - поэтому форма для файлов не обрабатывает его.

views.py:

class AddWorkshopView(LoginRequiredMixin, CreateView):

    model = Workshop
    form_class = AddWorkshopForm
    template_name = "modules/add-workshop.html"
    success_url = "/modules/workshop-list/"

    def get_context_data(self, **kwargs):
        data = super(AddWorkshopView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['files'] = FileFormSet(self.request.POST, self.request.FILES)
        else:
            data['files'] = FileFormSet()
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        files = context['files']

        with transaction.atomic():
            form.instance.created_by = self.request.user
            form.instance.updated_by = self.request.user
            self.object = form.save()

            if files.is_valid():
                files.instance = self.object
                files.save()

        return super(AddWorkshopView, self).form_valid(form)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...