Django: split form in pages using formtools and save to data base
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
add a comment |
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
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 Djangoforms.py
.
– WayBehind
Nov 11 at 19:46
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 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 at 20:00
So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary usingformtools
? (and using a single model?)
– Omar Gonzales
Nov 11 at 20:04
Correct. In yourforms.py
folder create a formmypageform.py
for each page and specify the fields you want to handle by that form. Then, you will just import the form into yourview.py
of just dofrom myapp.forms import *
Here: pydanny.com/core-concepts-django-modelforms.html
– WayBehind
Nov 11 at 20:16
add a comment |
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
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
django
edited Nov 17 at 4:54
asked Nov 8 at 2:25
Omar Gonzales
50621440
50621440
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 Djangoforms.py
.
– WayBehind
Nov 11 at 19:46
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 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 at 20:00
So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary usingformtools
? (and using a single model?)
– Omar Gonzales
Nov 11 at 20:04
Correct. In yourforms.py
folder create a formmypageform.py
for each page and specify the fields you want to handle by that form. Then, you will just import the form into yourview.py
of just dofrom myapp.forms import *
Here: pydanny.com/core-concepts-django-modelforms.html
– WayBehind
Nov 11 at 20:16
add a comment |
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 Djangoforms.py
.
– WayBehind
Nov 11 at 19:46
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 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 at 20:00
So, if I understand correctly. I can splitt a form into different pages with built-in form propierties. Not necessary usingformtools
? (and using a single model?)
– Omar Gonzales
Nov 11 at 20:04
Correct. In yourforms.py
folder create a formmypageform.py
for each page and specify the fields you want to handle by that form. Then, you will just import the form into yourview.py
of just dofrom myapp.forms import *
Here: pydanny.com/core-concepts-django-modelforms.html
– WayBehind
Nov 11 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 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 at 19:46
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 at 19:54
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 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 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 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 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 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 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 at 20:16
add a comment |
1 Answer
1
active
oldest
votes
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.
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 at 2:47
|
show 11 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 at 2:47
|
show 11 more comments
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.
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 at 2:47
|
show 11 more comments
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.
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.
edited Nov 17 at 7:17
answered Nov 13 at 16:52
ruddra
11.6k32648
11.6k32648
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 at 2:47
|
show 11 more comments
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 at 2:47
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
Maybe unrelated, but you can look into this repository where there is a simple multistep form is implemented.
– ruddra
Nov 13 at 16:54
1
1
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 at 20:00
this is the approach that you should take if you are open to not using formtools.
– rchurch4
Nov 13 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 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 at 1:28
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 at 1:35
@OmarGonzales I have added an example template in the codes.
– ruddra
Nov 17 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 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 at 2:47
|
show 11 more comments
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 at 19:46
@WayBehind ty. May you post and answer to guide me on this?
– Omar Gonzales
Nov 11 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 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 at 20:04
Correct. In your
forms.py
folder create a formmypageform.py
for each page and specify the fields you want to handle by that form. Then, you will just import the form into yourview.py
of just dofrom myapp.forms import *
Here: pydanny.com/core-concepts-django-modelforms.html– WayBehind
Nov 11 at 20:16