Django: split form in pages using formtools and save to data base





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I've a form that has 3 sections:



1) tamanios (sizes), 2) cantidades (quantities), 3) archivos subidos (Uploaded Image).



I need to separate 1 & 2 in one page, and 3 in a different page, and save form data to data base.



As far as I've investigated this is possible using formtools. But using formtools I've had to split my model into 2 models: a) TamaniosCantidades, b) ArchivosSubidos, so they can be rendered in different "steps".



Nevertheless, I'd prefer to have only 1 model. But it's ok if the solution contains some ForeingKey to connect both splitted models.



What I need to do in order to save the form as a model object in data base?



I can't think of on how to write the 'done' method in my Wizard Class.



Original model:



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))


tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
imagenes = models.FileField(upload_to='imagenes/')
uploaded_at = models.DateTimeField(auto_now_add=True)


Modified models (splited result):



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
# imagenes = models.FileField(upload_to='imagenes/')
# uploaded_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.tamanios


class ArchivosSubidos(models.Model):
# imagenes = models.FileField(upload_to='imagenes/') #commented because I was having problems uploading files with formtools
imagenes = models.CharField(max_length=100) #using charfield to test splitting
uploaded_at = models.DateTimeField(auto_now_add=True)


views.py



class ContactWizard(SessionWizardView):
template_name = "main_app/contact_form.html"
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'imagenes'))

def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)

return HttpResponseRedirect('/')
# return HttpResponseRedirect('/done.html')
# return render('main_app/done.html', {'form_data':form_data})


def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]

return form_data


urls.py



app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
# path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('contact/', ContactWizard.as_view([TamaniosCantidadesForm, ArchivosSubidosForm]))
]


UPDATE 1: stacktrace



2x2 #printed from print(kwargs.get('tamanios', None)) in  def save
Internal Server Error: /step-three/
Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/views.py", line 195, in form_valid
return super(StepThreeView, self).form_valid(form)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 125, in form_valid
self.object = form.save()
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/forms.py", line 55, in save
instance.save()
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 718, in save
force_update=force_update, update_fields=update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 748, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 812, in _save_table
forced_update)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 861, in _do_update
return filtered._update(values) > 0
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/query.py", line 712, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1383, in execute_sql
cursor = super().execute_sql(result_type)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios
[17/Nov/2018 03:53:44] "POST /step-three/ HTTP/1.1" 500 178292









share|improve this question

























  • Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

    – WayBehind
    Nov 11 '18 at 19:46











  • @WayBehind ty. May you post and answer to guide me on this?

    – Omar Gonzales
    Nov 11 '18 at 19:54











  • There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

    – WayBehind
    Nov 11 '18 at 20:00











  • So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

    – Omar Gonzales
    Nov 11 '18 at 20:04













  • Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

    – WayBehind
    Nov 11 '18 at 20:16


















0















I've a form that has 3 sections:



1) tamanios (sizes), 2) cantidades (quantities), 3) archivos subidos (Uploaded Image).



I need to separate 1 & 2 in one page, and 3 in a different page, and save form data to data base.



As far as I've investigated this is possible using formtools. But using formtools I've had to split my model into 2 models: a) TamaniosCantidades, b) ArchivosSubidos, so they can be rendered in different "steps".



Nevertheless, I'd prefer to have only 1 model. But it's ok if the solution contains some ForeingKey to connect both splitted models.



What I need to do in order to save the form as a model object in data base?



I can't think of on how to write the 'done' method in my Wizard Class.



Original model:



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))


tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
imagenes = models.FileField(upload_to='imagenes/')
uploaded_at = models.DateTimeField(auto_now_add=True)


Modified models (splited result):



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
# imagenes = models.FileField(upload_to='imagenes/')
# uploaded_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.tamanios


class ArchivosSubidos(models.Model):
# imagenes = models.FileField(upload_to='imagenes/') #commented because I was having problems uploading files with formtools
imagenes = models.CharField(max_length=100) #using charfield to test splitting
uploaded_at = models.DateTimeField(auto_now_add=True)


views.py



class ContactWizard(SessionWizardView):
template_name = "main_app/contact_form.html"
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'imagenes'))

def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)

return HttpResponseRedirect('/')
# return HttpResponseRedirect('/done.html')
# return render('main_app/done.html', {'form_data':form_data})


def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]

return form_data


urls.py



app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
# path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('contact/', ContactWizard.as_view([TamaniosCantidadesForm, ArchivosSubidosForm]))
]


UPDATE 1: stacktrace



2x2 #printed from print(kwargs.get('tamanios', None)) in  def save
Internal Server Error: /step-three/
Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/views.py", line 195, in form_valid
return super(StepThreeView, self).form_valid(form)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 125, in form_valid
self.object = form.save()
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/forms.py", line 55, in save
instance.save()
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 718, in save
force_update=force_update, update_fields=update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 748, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 812, in _save_table
forced_update)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 861, in _do_update
return filtered._update(values) > 0
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/query.py", line 712, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1383, in execute_sql
cursor = super().execute_sql(result_type)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios
[17/Nov/2018 03:53:44] "POST /step-three/ HTTP/1.1" 500 178292









share|improve this question

























  • Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

    – WayBehind
    Nov 11 '18 at 19:46











  • @WayBehind ty. May you post and answer to guide me on this?

    – Omar Gonzales
    Nov 11 '18 at 19:54











  • There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

    – WayBehind
    Nov 11 '18 at 20:00











  • So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

    – Omar Gonzales
    Nov 11 '18 at 20:04













  • Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

    – WayBehind
    Nov 11 '18 at 20:16














0












0








0


1






I've a form that has 3 sections:



1) tamanios (sizes), 2) cantidades (quantities), 3) archivos subidos (Uploaded Image).



I need to separate 1 & 2 in one page, and 3 in a different page, and save form data to data base.



As far as I've investigated this is possible using formtools. But using formtools I've had to split my model into 2 models: a) TamaniosCantidades, b) ArchivosSubidos, so they can be rendered in different "steps".



Nevertheless, I'd prefer to have only 1 model. But it's ok if the solution contains some ForeingKey to connect both splitted models.



What I need to do in order to save the form as a model object in data base?



I can't think of on how to write the 'done' method in my Wizard Class.



Original model:



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))


tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
imagenes = models.FileField(upload_to='imagenes/')
uploaded_at = models.DateTimeField(auto_now_add=True)


Modified models (splited result):



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
# imagenes = models.FileField(upload_to='imagenes/')
# uploaded_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.tamanios


class ArchivosSubidos(models.Model):
# imagenes = models.FileField(upload_to='imagenes/') #commented because I was having problems uploading files with formtools
imagenes = models.CharField(max_length=100) #using charfield to test splitting
uploaded_at = models.DateTimeField(auto_now_add=True)


views.py



class ContactWizard(SessionWizardView):
template_name = "main_app/contact_form.html"
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'imagenes'))

def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)

return HttpResponseRedirect('/')
# return HttpResponseRedirect('/done.html')
# return render('main_app/done.html', {'form_data':form_data})


def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]

return form_data


urls.py



app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
# path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('contact/', ContactWizard.as_view([TamaniosCantidadesForm, ArchivosSubidosForm]))
]


UPDATE 1: stacktrace



2x2 #printed from print(kwargs.get('tamanios', None)) in  def save
Internal Server Error: /step-three/
Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/views.py", line 195, in form_valid
return super(StepThreeView, self).form_valid(form)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 125, in form_valid
self.object = form.save()
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/forms.py", line 55, in save
instance.save()
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 718, in save
force_update=force_update, update_fields=update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 748, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 812, in _save_table
forced_update)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 861, in _do_update
return filtered._update(values) > 0
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/query.py", line 712, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1383, in execute_sql
cursor = super().execute_sql(result_type)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios
[17/Nov/2018 03:53:44] "POST /step-three/ HTTP/1.1" 500 178292









share|improve this question
















I've a form that has 3 sections:



1) tamanios (sizes), 2) cantidades (quantities), 3) archivos subidos (Uploaded Image).



I need to separate 1 & 2 in one page, and 3 in a different page, and save form data to data base.



As far as I've investigated this is possible using formtools. But using formtools I've had to split my model into 2 models: a) TamaniosCantidades, b) ArchivosSubidos, so they can be rendered in different "steps".



Nevertheless, I'd prefer to have only 1 model. But it's ok if the solution contains some ForeingKey to connect both splitted models.



What I need to do in order to save the form as a model object in data base?



I can't think of on how to write the 'done' method in my Wizard Class.



Original model:



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))


tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
imagenes = models.FileField(upload_to='imagenes/')
uploaded_at = models.DateTimeField(auto_now_add=True)


Modified models (splited result):



class TamaniosCantidades(models.Model):
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
# imagenes = models.FileField(upload_to='imagenes/')
# uploaded_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.tamanios


class ArchivosSubidos(models.Model):
# imagenes = models.FileField(upload_to='imagenes/') #commented because I was having problems uploading files with formtools
imagenes = models.CharField(max_length=100) #using charfield to test splitting
uploaded_at = models.DateTimeField(auto_now_add=True)


views.py



class ContactWizard(SessionWizardView):
template_name = "main_app/contact_form.html"
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'imagenes'))

def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)

return HttpResponseRedirect('/')
# return HttpResponseRedirect('/done.html')
# return render('main_app/done.html', {'form_data':form_data})


def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]

return form_data


urls.py



app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
# path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('contact/', ContactWizard.as_view([TamaniosCantidadesForm, ArchivosSubidosForm]))
]


UPDATE 1: stacktrace



2x2 #printed from print(kwargs.get('tamanios', None)) in  def save
Internal Server Error: /step-three/
Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 142, in post
return self.form_valid(form)
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/views.py", line 195, in form_valid
return super(StepThreeView, self).form_valid(form)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/views/generic/edit.py", line 125, in form_valid
self.object = form.save()
File "/home/ogonzales/Escritorio/web_proyects/gallito/main_app/forms.py", line 55, in save
instance.save()
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 718, in save
force_update=force_update, update_fields=update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 748, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 812, in _save_table
forced_update)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/base.py", line 861, in _do_update
return filtered._update(values) > 0
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/query.py", line 712, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1383, in execute_sql
cursor = super().execute_sql(result_type)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ogonzales/Escritorio/projects_envs/gallito_env/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: main_app_tamanioscantidades.tamanios
[17/Nov/2018 03:53:44] "POST /step-three/ HTTP/1.1" 500 178292






django






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 '18 at 4:54







Omar Gonzales

















asked Nov 8 '18 at 2:25









Omar GonzalesOmar Gonzales

58331642




58331642













  • Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

    – WayBehind
    Nov 11 '18 at 19:46











  • @WayBehind ty. May you post and answer to guide me on this?

    – Omar Gonzales
    Nov 11 '18 at 19:54











  • There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

    – WayBehind
    Nov 11 '18 at 20:00











  • So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

    – Omar Gonzales
    Nov 11 '18 at 20:04













  • Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

    – WayBehind
    Nov 11 '18 at 20:16



















  • Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

    – WayBehind
    Nov 11 '18 at 19:46











  • @WayBehind ty. May you post and answer to guide me on this?

    – Omar Gonzales
    Nov 11 '18 at 19:54











  • There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

    – WayBehind
    Nov 11 '18 at 20:00











  • So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

    – Omar Gonzales
    Nov 11 '18 at 20:04













  • Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

    – WayBehind
    Nov 11 '18 at 20:16

















Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

– WayBehind
Nov 11 '18 at 19:46





Just want to say that you dont have to split your model as you can process multiple forms and pages for the same model and each page or form can handle only some data of the same model. I think you are missing the customization and usability of Django forms.py.

– WayBehind
Nov 11 '18 at 19:46













@WayBehind ty. May you post and answer to guide me on this?

– Omar Gonzales
Nov 11 '18 at 19:54





@WayBehind ty. May you post and answer to guide me on this?

– Omar Gonzales
Nov 11 '18 at 19:54













There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

– WayBehind
Nov 11 '18 at 20:00





There are many "Django Forms Tutorials" available on the internet and they will do better than me fixing one form. Also look up docs.djangoproject.com/en/2.1/topics/forms

– WayBehind
Nov 11 '18 at 20:00













So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

– Omar Gonzales
Nov 11 '18 at 20:04







So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary using formtools? (and using a single model?)

– Omar Gonzales
Nov 11 '18 at 20:04















Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

– WayBehind
Nov 11 '18 at 20:16





Correct. In your forms.py folder create a form mypageform.py for each page and specify the fields you want to handle by that form. Then, you will just import the form into your view.py of just do from myapp.forms import * Here: pydanny.com/core-concepts-django-modelforms.html

– WayBehind
Nov 11 '18 at 20:16












1 Answer
1






active

oldest

votes


















2





+50









Using formtools may not be a good option(IMHO: it gives less control over your form), instead you can use Django Form and Modelform for multistep forms, and use django session to store the data in each step. In final step, you can pop those session data and store it in model. For example:



# Lets declare our choices in a global scope rather than inside models
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

# Declare Forms
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS)

class StepTwoForm(forms.Form):
cantidades = forms.ChoiceField(choices=CANTIDADES)

# Third step is attached to the model directly, we will do some tweaks inside the save method of this form
class StepThreeForm(forms.ModelForm):
class Meta:
model = TamaniosCantidades
fields = ('imagenes',)

# Views
# First Two steps are basic FormViews, because it will be used just to store data in session
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'step_one.html'
success_url = '/step-two/'

def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
return initial

def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
return HttpResponseRedirect(self.get_success_url())


class StepTwoView(FormView):
form_class = StepTwoForm
template_name = 'step_two.html'
success_url = '/step-three/'


def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial

def form_valid(self, form):
# same as StepOneView
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'step_three.html'
success_url = '/thank-you/'

def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)

# template
# step_one.html, step_two.html, step_three.html can be all the same as following code
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>

# urls

path('step-one/', StepOneView.as_view()),
path('step-two/', StepTwoView.as_view()),
path('step-three/', StepThreeView.as_view()),
path('thank-you/', TemplateView.as_view(template_name="thank-you.html")),


In this approach, you don't need to split the model, and store the data in last step. FYI: its untested code, but I hope it will put you in right direction for implementation.






share|improve this answer


























  • Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

    – ruddra
    Nov 13 '18 at 16:54






  • 1





    this is the approach that you should take if you are open to not using formtools.

    – rchurch4
    Nov 13 '18 at 20:00











  • @ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

    – Omar Gonzales
    Nov 17 '18 at 1:28











  • @OmarGonzales I have added an example template in the codes.

    – ruddra
    Nov 17 '18 at 1:35











  • updated my answer with the urls but I am assuming you have already figured it out on your own :)

    – ruddra
    Nov 17 '18 at 2:47












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53200686%2fdjango-split-form-in-pages-using-formtools-and-save-to-data-base%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2





+50









Using formtools may not be a good option(IMHO: it gives less control over your form), instead you can use Django Form and Modelform for multistep forms, and use django session to store the data in each step. In final step, you can pop those session data and store it in model. For example:



# Lets declare our choices in a global scope rather than inside models
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

# Declare Forms
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS)

class StepTwoForm(forms.Form):
cantidades = forms.ChoiceField(choices=CANTIDADES)

# Third step is attached to the model directly, we will do some tweaks inside the save method of this form
class StepThreeForm(forms.ModelForm):
class Meta:
model = TamaniosCantidades
fields = ('imagenes',)

# Views
# First Two steps are basic FormViews, because it will be used just to store data in session
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'step_one.html'
success_url = '/step-two/'

def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
return initial

def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
return HttpResponseRedirect(self.get_success_url())


class StepTwoView(FormView):
form_class = StepTwoForm
template_name = 'step_two.html'
success_url = '/step-three/'


def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial

def form_valid(self, form):
# same as StepOneView
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'step_three.html'
success_url = '/thank-you/'

def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)

# template
# step_one.html, step_two.html, step_three.html can be all the same as following code
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>

# urls

path('step-one/', StepOneView.as_view()),
path('step-two/', StepTwoView.as_view()),
path('step-three/', StepThreeView.as_view()),
path('thank-you/', TemplateView.as_view(template_name="thank-you.html")),


In this approach, you don't need to split the model, and store the data in last step. FYI: its untested code, but I hope it will put you in right direction for implementation.






share|improve this answer


























  • Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

    – ruddra
    Nov 13 '18 at 16:54






  • 1





    this is the approach that you should take if you are open to not using formtools.

    – rchurch4
    Nov 13 '18 at 20:00











  • @ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

    – Omar Gonzales
    Nov 17 '18 at 1:28











  • @OmarGonzales I have added an example template in the codes.

    – ruddra
    Nov 17 '18 at 1:35











  • updated my answer with the urls but I am assuming you have already figured it out on your own :)

    – ruddra
    Nov 17 '18 at 2:47
















2





+50









Using formtools may not be a good option(IMHO: it gives less control over your form), instead you can use Django Form and Modelform for multistep forms, and use django session to store the data in each step. In final step, you can pop those session data and store it in model. For example:



# Lets declare our choices in a global scope rather than inside models
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

# Declare Forms
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS)

class StepTwoForm(forms.Form):
cantidades = forms.ChoiceField(choices=CANTIDADES)

# Third step is attached to the model directly, we will do some tweaks inside the save method of this form
class StepThreeForm(forms.ModelForm):
class Meta:
model = TamaniosCantidades
fields = ('imagenes',)

# Views
# First Two steps are basic FormViews, because it will be used just to store data in session
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'step_one.html'
success_url = '/step-two/'

def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
return initial

def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
return HttpResponseRedirect(self.get_success_url())


class StepTwoView(FormView):
form_class = StepTwoForm
template_name = 'step_two.html'
success_url = '/step-three/'


def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial

def form_valid(self, form):
# same as StepOneView
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'step_three.html'
success_url = '/thank-you/'

def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)

# template
# step_one.html, step_two.html, step_three.html can be all the same as following code
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>

# urls

path('step-one/', StepOneView.as_view()),
path('step-two/', StepTwoView.as_view()),
path('step-three/', StepThreeView.as_view()),
path('thank-you/', TemplateView.as_view(template_name="thank-you.html")),


In this approach, you don't need to split the model, and store the data in last step. FYI: its untested code, but I hope it will put you in right direction for implementation.






share|improve this answer


























  • Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

    – ruddra
    Nov 13 '18 at 16:54






  • 1





    this is the approach that you should take if you are open to not using formtools.

    – rchurch4
    Nov 13 '18 at 20:00











  • @ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

    – Omar Gonzales
    Nov 17 '18 at 1:28











  • @OmarGonzales I have added an example template in the codes.

    – ruddra
    Nov 17 '18 at 1:35











  • updated my answer with the urls but I am assuming you have already figured it out on your own :)

    – ruddra
    Nov 17 '18 at 2:47














2





+50







2





+50



2




+50





Using formtools may not be a good option(IMHO: it gives less control over your form), instead you can use Django Form and Modelform for multistep forms, and use django session to store the data in each step. In final step, you can pop those session data and store it in model. For example:



# Lets declare our choices in a global scope rather than inside models
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

# Declare Forms
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS)

class StepTwoForm(forms.Form):
cantidades = forms.ChoiceField(choices=CANTIDADES)

# Third step is attached to the model directly, we will do some tweaks inside the save method of this form
class StepThreeForm(forms.ModelForm):
class Meta:
model = TamaniosCantidades
fields = ('imagenes',)

# Views
# First Two steps are basic FormViews, because it will be used just to store data in session
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'step_one.html'
success_url = '/step-two/'

def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
return initial

def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
return HttpResponseRedirect(self.get_success_url())


class StepTwoView(FormView):
form_class = StepTwoForm
template_name = 'step_two.html'
success_url = '/step-three/'


def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial

def form_valid(self, form):
# same as StepOneView
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'step_three.html'
success_url = '/thank-you/'

def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)

# template
# step_one.html, step_two.html, step_three.html can be all the same as following code
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>

# urls

path('step-one/', StepOneView.as_view()),
path('step-two/', StepTwoView.as_view()),
path('step-three/', StepThreeView.as_view()),
path('thank-you/', TemplateView.as_view(template_name="thank-you.html")),


In this approach, you don't need to split the model, and store the data in last step. FYI: its untested code, but I hope it will put you in right direction for implementation.






share|improve this answer















Using formtools may not be a good option(IMHO: it gives less control over your form), instead you can use Django Form and Modelform for multistep forms, and use django session to store the data in each step. In final step, you can pop those session data and store it in model. For example:



# Lets declare our choices in a global scope rather than inside models
TAMANIOS = (('2x2', '2" x 2"',), ('3x3', '3" x 3"',),
('4x4', '4" x 4"',), ('5x5', '5" x 5"',))

CANTIDADES = (('50', '50',), ('100', '100',),
('150', '150',))

# Declare Forms
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS)

class StepTwoForm(forms.Form):
cantidades = forms.ChoiceField(choices=CANTIDADES)

# Third step is attached to the model directly, we will do some tweaks inside the save method of this form
class StepThreeForm(forms.ModelForm):
class Meta:
model = TamaniosCantidades
fields = ('imagenes',)

# Views
# First Two steps are basic FormViews, because it will be used just to store data in session
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'step_one.html'
success_url = '/step-two/'

def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
return initial

def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
return HttpResponseRedirect(self.get_success_url())


class StepTwoView(FormView):
form_class = StepTwoForm
template_name = 'step_two.html'
success_url = '/step-three/'


def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial

def form_valid(self, form):
# same as StepOneView
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())


# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'step_three.html'
success_url = '/thank-you/'

def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)

# template
# step_one.html, step_two.html, step_three.html can be all the same as following code
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>

# urls

path('step-one/', StepOneView.as_view()),
path('step-two/', StepTwoView.as_view()),
path('step-three/', StepThreeView.as_view()),
path('thank-you/', TemplateView.as_view(template_name="thank-you.html")),


In this approach, you don't need to split the model, and store the data in last step. FYI: its untested code, but I hope it will put you in right direction for implementation.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 17 '18 at 7:17

























answered Nov 13 '18 at 16:52









ruddraruddra

17.1k42951




17.1k42951













  • Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

    – ruddra
    Nov 13 '18 at 16:54






  • 1





    this is the approach that you should take if you are open to not using formtools.

    – rchurch4
    Nov 13 '18 at 20:00











  • @ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

    – Omar Gonzales
    Nov 17 '18 at 1:28











  • @OmarGonzales I have added an example template in the codes.

    – ruddra
    Nov 17 '18 at 1:35











  • updated my answer with the urls but I am assuming you have already figured it out on your own :)

    – ruddra
    Nov 17 '18 at 2:47



















  • Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

    – ruddra
    Nov 13 '18 at 16:54






  • 1





    this is the approach that you should take if you are open to not using formtools.

    – rchurch4
    Nov 13 '18 at 20:00











  • @ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

    – Omar Gonzales
    Nov 17 '18 at 1:28











  • @OmarGonzales I have added an example template in the codes.

    – ruddra
    Nov 17 '18 at 1:35











  • updated my answer with the urls but I am assuming you have already figured it out on your own :)

    – ruddra
    Nov 17 '18 at 2:47

















Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

– ruddra
Nov 13 '18 at 16:54





Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.

– ruddra
Nov 13 '18 at 16:54




1




1





this is the approach that you should take if you are open to not using formtools.

– rchurch4
Nov 13 '18 at 20:00





this is the approach that you should take if you are open to not using formtools.

– rchurch4
Nov 13 '18 at 20:00













@ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

– Omar Gonzales
Nov 17 '18 at 1:28





@ruddra could you tell me how to generate the template: template_name = 'step_one.html'? I usually send and empy form, but not idea how to do that with this FormView.

– Omar Gonzales
Nov 17 '18 at 1:28













@OmarGonzales I have added an example template in the codes.

– ruddra
Nov 17 '18 at 1:35





@OmarGonzales I have added an example template in the codes.

– ruddra
Nov 17 '18 at 1:35













updated my answer with the urls but I am assuming you have already figured it out on your own :)

– ruddra
Nov 17 '18 at 2:47





updated my answer with the urls but I am assuming you have already figured it out on your own :)

– ruddra
Nov 17 '18 at 2:47




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53200686%2fdjango-split-form-in-pages-using-formtools-and-save-to-data-base%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python