Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a django formset that dynamically adds fields have persistent data?

I am making a formset in python/django and need to dynamically add more fields to a formset as a button is clicked. The form I'm working on is for my school asking students who they would like to disclose certain academic information to, and the button here allows them to add more fields for entering family members/people they want to disclose to.

I have the button working to the point where the extra fields show up, and you can add as many as you like. Problem is, the data that was previously entered into the already existing fields gets deleted. However, only the things in the formset get deleted. Everything else that was filled out earlier in the form stays persistent.

Is there any way to make the formset keep the data that was entered before the button was pressed?

form.py:

from django import forms
from models import Form, ParentForm, Contact
from django.core.exceptions import ValidationError

def fff (value):
    if value == "":
        raise ValidationError(message = 'Must choose a relation', code="a")

# Create your forms here.
class ModelForm(forms.ModelForm):   
    class Meta:
        model = Form
        exclude = ('name', 'Relation',)

class Parent(forms.Form):
    name = forms.CharField()

    CHOICES3 = (    
    ("", '-------'),
    ("MOM", 'Mother'),
    ("DAD", 'Father'),
    ("GRAN", 'Grandparent'),
    ("BRO", 'Brother'),
    ("SIS", 'Sister'),
    ("AUNT", 'Aunt'),
    ("UNC", 'Uncle'),
    ("HUSB", 'Husband'),
    ("FRIE", 'Friend'),
    ("OTHE", 'Other'),
    ("STEP", 'Stepparent'),
    )
    Relation = forms.ChoiceField(required = False, widget = forms.Select, choices = CHOICES3, validators = [fff])

models.py

from django.db import models
from django import forms
from content.validation import *
from django.forms.models import modelformset_factory

class Contact(models.Model):
    name = models.CharField(max_length=100)

class Form(models.Model):
    CHOICES1 = (
        ("ACCEPT", 'I agree with the previous statement.'),
        )
    CHOICES2 = (
        ("ACADEMIC", 'Academic Records'),
        ("FINANCIAL", 'Financial Records'),
        ("BOTH", 'I would like to share both'),
        ("NEITHER", 'I would like to share neither'),
        ("OLD", "I would like to keep my old sharing settings"),
        )

    Please_accept = models.CharField(choices=CHOICES1, max_length=200)
    Which_information_would_you_like_to_share = models.CharField(choices=CHOICES2, max_length=2000)
    Full_Name_of_Student = models.CharField(max_length=100)
    Carthage_ID_Number = models.IntegerField(max_length=7)
    I_agree_the_above_information_is_correct_and_valid = models.BooleanField(validators=[validate_boolean])
    Date = models.DateField(auto_now_add=True)
    name = models.ManyToManyField(Contact, through="ParentForm")

class ParentForm(models.Model):
    student_name = models.ForeignKey(Form)
    name = models.ForeignKey(Contact)

    CHOICES3 = (
    ("MOM", 'Mother'),
    ("DAD", 'Father'),
    ("GRAN", 'Grandparent'),
    ("BRO", 'Brother'),
    ("SIS", 'Sister'),
    ("AUNT", 'Aunt'),
    ("UNC", 'Uncle'),
    ("HUSB", 'Husband'),
    ("FRIE", 'Friend'),
    ("OTHE", 'Other'),
    ("STEP", 'Stepparent'),
    )
    Relation = models.CharField(choices=CHOICES3, max_length=200)
    def __unicode__(self):
        return 'name: %r, student_name: %r' % (self.name, self.student_name)

and views.py

from django.shortcuts import render
from django.http import HttpResponse
from form import ModelForm, Parent
from models import Form, ParentForm, Contact
from django.http import HttpResponseRedirect
from django.forms.formsets import formset_factory

def create(request):
    ParentFormSet = formset_factory(Parent, extra=1)
    if request.POST:        
        Parent_formset = ParentFormSet(request.POST, prefix='Parent_or_Third_Party_Name')
        if 'add' in request.POST:
            list=[]
            for kitties in Parent_formset:
                list.append({'Parent_or_Third_Party_Name-0n-ame': kitties.data['Parent_or_Third_Party_Name-0-name'], 'Parent_or_Third_Party_Name-0-Relation': kitties.data['Parent_or_Third_Party_Name-0-Relation']})
            Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name', initial= list)
        form = ModelForm(request.POST)
        if form.is_valid() and Parent_formset.is_valid():
            form_instance = form.save()

            for f in Parent_formset:
                if f.clean():
                    (obj, created) = ParentForm.objects.get_or_create(name=f.cleaned_data['name'], Relation=f.cleaned_data['Relation'])

            return HttpResponseRedirect('http://Google.com')
    else:
        form = ModelForm()
        Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name')

    return render(request, 'content/design.html', {'form': form, 'Parent_formset': Parent_formset})
def submitted(request):
    return render(request, 'content/design.html')

Thank you in advance!

like image 707
Riot Goes Woof Avatar asked Aug 01 '13 14:08

Riot Goes Woof


3 Answers

I've had trouble with dynamically adding fields in Django before and this stackoverflow question helped me: dynamically add field to a form

To be honest, I'm not entirely sure what you mean by "persistent" in your case - are the values of your forms being removed as you add inputs? Are you sure it isn't something with your JS?

like image 95
Temuz Avatar answered Nov 15 '22 15:11

Temuz


A coworker of mine finally figured it out. Here is the revised views.py:

from django.shortcuts import render
from django.http import HttpResponse
from form import ModelForm, Parent
from models import Form, ParentForm, Contact
from django.http import HttpResponseRedirect
from django.forms.formsets import formset_factory

def create(request):
    ParentFormSet = formset_factory(Parent, extra=1)
    boolean = False
    if request.POST:        
        Parent_formset = ParentFormSet(request.POST, prefix='Parent_or_Third_Party_Name')
        if 'add' in request.POST:
            boolean = True
            list=[]
            for i in range(0,int(Parent_formset.data['Parent_or_Third_Party_Name-TOTAL_FORMS'])):
                list.append({'name': Parent_formset.data['Parent_or_Third_Party_Name-%s-name' % (i)], 'Relation': Parent_formset.data['Parent_or_Third_Party_Name-%s-Relation' % (i)]})
            Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name', initial= list)
        form = ModelForm(request.POST)
        if form.is_valid() and Parent_formset.is_valid():
            form_instance = form.save()                 

            for f in Parent_formset:
                if f.clean():
                    (contobj, created) = Contact.objects.get_or_create(name=f.cleaned_data['name'])
                    (obj, created) = ParentForm.objects.get_or_create(student_name=form_instance, name=contobj, Relation=f.cleaned_data['Relation'])

            return HttpResponseRedirect('http://Google.com')
    else:
        form = ModelForm()
        Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name')

    return render(request, 'content/design.html', {'form': form, 'Parent_formset': Parent_formset, 'boolean':boolean})
def submitted(request):
    return render(request, 'content/design.html')

Thank you for your input, those of you who answered :)

like image 29
Riot Goes Woof Avatar answered Nov 15 '22 15:11

Riot Goes Woof


I was once trying to do something like this, and was directed to django-crispy-forms by a man much wiser than I. I never finished the project so I can't offer more help than that, but it could be a starting point.

like image 23
TylerLubeck Avatar answered Nov 15 '22 16:11

TylerLubeck