Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form Wizard doesn't save File #204

Open
Samoht1 opened this issue Nov 30, 2021 · 2 comments
Open

Form Wizard doesn't save File #204

Samoht1 opened this issue Nov 30, 2021 · 2 comments

Comments

@Samoht1
Copy link

Samoht1 commented Nov 30, 2021

I have a 5 step form wizard, each their own form. I have a FileField in the first, but something is going wrong. When I reach the final step and press submit, my model gets saved but the file field is empty in my database. It's not "null", but actually empty. I created the "file_storage" variable but that only stores the file temporarily, it get's deleted as soon as I submit the form

this is my wizard class:

import json
import logging
import os

import keyboard
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.core.mail import EmailMessage
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from formtools.wizard.views import SessionWizardView

from .forms import *

logger = logging.getLogger('django')

FORMS = [
    ("company", CompanyForm),
    ("addresses", AddressesForm),
    ("references", ReferenceFormSet),
    ("contacts", ContactFormSet),
    ("payment", PaymentForm),
    # ("upload", DocumentForm),

]

TEMPLATES = {
    "company":    "form/step-1.html",
    "addresses":  "form/step-2.html",
    "references": "form/step-3.html",
    "contacts":   "form/step-4.html",
    "payment":    "form/step-5.html",
    # "upload":     "form/step-6.html",

}

form_data = []
form_data2 = {}

class RegisterWizard(SessionWizardView):
    file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'temp'))

    def get_context_data(self, form, **kwargs):
        context = super().get_context_data(form=form, **kwargs)
        context.update({'callme_forms': CallMeForms(prefix='callme')})

        return context

    @property
    def first_step_files(self):
        return self.storage.get_step_files(self.steps.first)

    def process_step(self, form):
        data = {}
        form_data.extend(self.get_form_step_data(form))
        for attr, value in self.get_form_step_data(form).items():
            if 'reference' not in attr:
                if 'company-' in attr:
                    attr = attr.replace('company-', '')
                if 'addresses-' in attr:
                    attr = attr.replace('addresses-', '')
                if 'payment-' in attr:
                    attr = attr.replace('payment-', '')
                if 'document-' in attr:
                    attr = attr.replace('document-', '')
                if value == 'on':
                    value = True
                if value == 'off':
                    value = False

                data[attr] = value if value else data.get(attr)

            if 'reference' not in attr or 'contact' not in attr:
                try:
                    form_data2.update(data)
                except e:
                    logger.error(e)
        return self.get_form_step_data(form)

    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

    def render_goto_step(self, *args, **kwargs):
        form = self.get_form(data=self.request.POST, files=self.request.FILES)
        self.storage.set_step_data(self.steps.current, self.process_step(form))
        self.storage.set_step_files(self.steps.first, self.process_step_files(form))

        return super().render_goto_step(*args, **kwargs)

    def done(self, form_list, **kwargs):
        data = {}
        data2 = {}

        form_data2.pop('csrfmiddlewaretoken')
        form_data2.pop('register_wizard-current_step')

        try:
            data2.update(form_data2)

            for k, v in form_data2.items():
                if 'reference' in k:
                    data2.pop(k)
                if 'contact' in k:
                    data2.pop(k)

            form_data2.clear()
            form_data2.update(data2)

            form_data2.pop('wizard_goto_step')

            if 'using_mail_address' in form_data2:
                form_data2.pop('using_mail_address')
            if 'different_invoice_address' in form_data2:
                form_data2.pop('different_invoice_address')
            else:
                data['invoice_street'] = form_data2.get('delivery_street')
                data['invoice_zip'] = form_data2.get('delivery_zip')
                data['invoice_city'] = form_data2.get('delivery_city')
                data['invoice_house_number'] = form_data2.get('delivery_number')
                form_data2.update(data)

            form_data2.pop('toa')
            instance = Customer()
            customer = Customer.objects.create(**form_data2)

            form_data_sets = [form.cleaned_data for form in form_list]

            for form in form_list[2].save(commit=False):
                form.customer_id = customer.id
                form.save()

            for form in form_list[3].save(commit=False):
                form.customer_id = customer.id
                form.save()

            form_data2.clear()
            kwargs.clear()
            Customer.objects.all().none()
        except e:
            logger.error(e)
        finally:
            return HttpResponseRedirect('/thank-you')`
@sergioisidoro
Copy link

sergioisidoro commented Feb 10, 2022

I'm having the same issue for a few hours now, and I can't find the cause.

(Pdb) self.request.FILES
<MultiValueDict: {}>
(Pdb) form_dict['profile_info'].files
<MultiValueDict: {}>
(Pdb) form_dict['profile_info'].data
<MultiValueDict: {.... 'onboarding_wizard-current_step': ['profile_info'], 'profile_info-avatar_file': ['242434811_582079809594246_1047266963691802278_n.jpg'], 'profile_info-short_description': ['dasd'], 'profile_info-description': ['adad'], 'profile_info-facebook': [''], 'profile_info-soundcloud': [''], 'profile_info-youtube': [''], 'profile_info-instagram': ['']}>

As we can see the 'profile_info-avatar_file': ['242434811_582079809594246_1047266963691802278_n.jpg'] shows a file, but everything else is empty.

I'm using

class OnboardingWizard(LoginRequiredMixin, SessionWizardView):
    file_storage = default_storage

but I also tried other approaches with the SystemFileStorage without any luck.
Did you figure it out @Samoht1 ?

SOLUTION

Adding enctype="multipart/form-data" to the form worked for me

<form enctype="multipart/form-data" action="" method="post">

@nerdoc
Copy link

nerdoc commented Mar 15, 2024

@Samoht1 could this be closed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants