Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to save form_list form instances to the database?

I am using a SessionWizardView to divide a small survey over multiple pages.

My problem is that the data from each page of the survey is saved onto a different row in my database, where there are multiple input fields on the one page that information is getting saved on the same row. This is making my DB very cumbersome.

enter image description here

I isolated the issue to my save() function which is getting executed each time there is a form in my form_list, thus adding new lines in the DB each time.

def done(self, form_list, **kwargs):

    for form in form_list:
        form.save()

    return render(self.request, 'Return_to_Prolific_Academic.html', {
        'form_data': [form.cleaned_data for form in form_list],            
    })  

I have tried to execute save directly on the form_list via form_list.save() but I get the error:

'list' object has no attribute 'save'

I have also tried both join() and chain() to see if I could join together all of the form instances to see if I could save them at the same time but was unsuccessful.

I would like to simplify my current solution so that each participants data is saved on a single line in the DB, can anyone tell me how I might go about doing it? Thanks

Edit

Example of some of my models.py and forms.py

models.py

class Person(models.Model):
    ....
    ....

    sender = models.EmailField(null=True, blank=True, verbose_name='What is your email address?')     

    birthdate = models.DateField(null=True, blank=True) #overwritten in forms.py so passed no more arguments

    SEX = (
        ('1', 'Male'),
        ('2', 'Female'))    
    sex = models.CharField(null=True, blank=True, max_length=100, choices=SEX, verbose_name='What sex are you?')

    MARITAL_STATUS = (
        ('SINGLE', "Single"),
        ('INARELATIONSHIP', "In a relationship"),
        ('MARRIED', "Married"),
        ('DIVORCED', "Divorced"),
        ('SEPARATED', "Separated"),
        ('WIDOWED', "Widowed"),)    
    marital_status = models.CharField(null=True, blank=True, max_length=100, choices=MARITAL_STATUS, verbose_name='What is your marital status?')             

    INTERNET_USAGE = (
        ('INTERNET_LESS_THAN_ONE_HOUR_A_DAY', 'Less than one hour a day'),
        ('INTERNET_ONE_TO_TWO_HOURS_A_DAY', '1 - 2 hours a day'),
        ('INTERNET_TWO_TO_FOUR_HOURS_A_DAY', '2 - 4 hours a day'),
        ('INTERNET_FOUR_TO_SIX_HOURS_A_DAY', '4 - 6 hours a Day'),
        ('INTERNET_SIX_TO_EIGHT_HOURS_A_DAY', '6 - 8 hours a day'),
        ('INTERNET_EIGHT_PLUS_HOURS_A_DAY', '8 + hours a day'), )
    internet_usage = models.CharField(null=True, blank=True, max_length=100, default=None, choices=INTERNET_USAGE)

    SMART_PHONE_OWNERSHIP = (
        ('YES_SMARTPHONE', 'Yes'),
        ('NO_SMARTPHONE', 'No'),)    
    smart_phone_ownership = models.CharField(null=True, max_length=100, blank=True, choices=SMART_PHONE_OWNERSHIP, verbose_name='Do you own a Smartphone?')

forms.py

class SurveyFormIT1(forms.ModelForm):      
    class Meta:
        model = Person    
        fields = ['instruction_task_one_value', 'instruction_task_one_image']
        widgets = {'instruction_task_one_value' : forms.HiddenInput,
                   'instruction_task_one_image' : forms.HiddenInput}       

class SurveyFormIT2(forms.ModelForm):      
    class Meta:
        model = Person    
        fields = ['instruction_task_two_value', 'instruction_task_two_image']
        widgets = {'instruction_task_two_value' : forms.HiddenInput,
                   'instruction_task_two_image' : forms.HiddenInput}      

class Start(forms.ModelForm):      
    class Meta:
        model = Person    
        fields = ['start']
        widgets = {'start' : forms.HiddenInput}

class SurveyFormA(forms.ModelForm):

    birthdate = forms.DateField(widget=extras.SelectDateWidget(years=range(1920, 1998)), required=True)

    class Meta:
        model = Person
        fields = ['prolific_academic_ID', 'sender', 'birthdate', 'sex', 'marital_status', 'state']

class SurveyFormB(forms.ModelForm): 
    class Meta:
        model = Person
        fields = ['internet_usage', 'smart_phone_ownership', 'smart_phone_usage']        
        widgets = {'internet_usage' : RadioSelectNotNull,
                   'smart_phone_ownership' : RadioSelectNotNull,
                   'smart_phone_usage' : RadioSelectNotNull,}
like image 481
Deepend Avatar asked Oct 19 '22 05:10

Deepend


1 Answers

Try this solution:

def done(self, form_list, **kwargs):
    data = {k: v for form in form_list for k, v in form.cleaned_data.items()}
    instance = Person.objects.create(**data)
    return render(self.request, 'Return_to_Prolific_Academic.html', {
        'form_data': [form.cleaned_data for form in form_list],            
    })
like image 160
nikita.koshelev Avatar answered Oct 22 '22 01:10

nikita.koshelev