def save(self, collection=None): """ Saves the validated, cleaned form data. If a submission already exists, the new data will be merged over the old data. """ # TODO: think about adding an "overwrite" argument to this function, default of False, # which will determine if an error should be thrown if the submission object already # exists, or if we should trust the data and overwrite the previous submission. # If there is no submission object, then this should just be a normal # Django form. No need to call the save method, so we will raise an exception if not hasattr(self, 'submission'): raise LookupError( "There is no submission object. Are your creating the form with 'retrun_class=True'? If so, no need to call save." ) if not self.cleaned_data: raise LookupError( "The is_valid() method must be called before saving a form") # Slightly evil, do type checking to see if submission is a Submission object or string # If Submission object is a slug if isinstance(self.submission, str) or isinstance( self.submission, unicode): submission_slug = self.submission # Get or create the object self.submission, was_created = Submission.objects.get_or_create( slug=submission_slug, collection=collection) # Otherwise it should be a submission model object, if not raise elif not isinstance(self.submission, Submission): raise AttributeError( 'Submission %s is not a valid submission object.' % self.submission) # We now have a submission object, so let's update the last_modified field self.submission.last_modified = datetime.datetime.now() self.submission.save() # Get the existing answers answers = Answer.objects.select_related('submission', 'data_from', 'field').filter( data_form__slug=self.slug, submission=self.submission) # Get the fields from the form post field_keys = [] for key in self.fields: # Mangle the key into the DB form, then get the right Field field_keys.append(_field_for_db(key)) # Get all fields that pertian to this dataform (from db) fields_from_db = self.query_data['field_query'] # Check for fields that aren't in the database and create a list of them fields_to_insert = [] for field in fields_from_db: has_answer = filter(lambda a: a.field.slug == field.slug, answers) if has_answer: continue else: fields_to_insert.append(field) # For these new fields, create answer objects for insertion, if any if fields_to_insert: new_answers = [] for field in fields_to_insert: # save the answer only if the field is in the form POST if field.slug in field_keys: # Create a new answer object answer = Answer() answer.submission = self.submission answer.data_form = self.query_data['dataform_query'] answer.field = field new_answers.append(answer) # Insert the new objects, if any if new_answers: insert_many(new_answers) # Get Answers again so that we have the pks if we had answers that were inserted answers = (Answer.objects.select_related( 'submission', 'data_from', 'field').filter(data_form__slug=self.slug, submission=self.submission)) # Get All possible choices from form models dict choices = Choice.objects.all() # Setup answer list so we can do a bulk update answer_objects = [] # We know answers exist now, so update them if needed. for answer in answers: # Delete the choices so we can re-insert AnswerChoice.objects.filter(answer=answer).delete() answer_obj, choice_relations = self._prepare_answer( answer, choices) answer_objects.append(answer_obj) # If there are choices, do mass insert on them for each answer. if choice_relations: answer_choices = [] for choice in choice_relations: answer_choice = AnswerChoice() answer_choice.answer = answer answer_choice.choice = choice answer_choices.append(answer_choice) insert_many(answer_choices) # Update the answers update_many(answer_objects, fields=['value']) # Return a submission so the collection or form can have this. return self.submission
def save(self, collection=None): """ Saves the validated, cleaned form data. If a submission already exists, the new data will be merged over the old data. """ # TODO: think about adding an "overwrite" argument to this function, default of False, # which will determine if an error should be thrown if the submission object already # exists, or if we should trust the data and overwrite the previous submission. # If there is no submission object, then this should just be a normal # Django form. No need to call the save method, so we will raise an exception if not hasattr(self, "submission"): raise LookupError( "There is no submission object. Are your creating the form with 'retrun_class=True'? If so, no need to call save." ) if not self.cleaned_data: raise LookupError("The is_valid() method must be called before saving a form") # Slightly evil, do type checking to see if submission is a Submission object or string # If Submission object is a slug if isinstance(self.submission, str) or isinstance(self.submission, unicode): submission_slug = self.submission # Get or create the object self.submission, was_created = Submission.objects.get_or_create(slug=submission_slug, collection=collection) # Otherwise it should be a submission model object, if not raise elif not isinstance(self.submission, Submission): raise AttributeError("Submission %s is not a valid submission object." % self.submission) # We now have a submission object, so let's update the last_modified field self.submission.last_modified = datetime.datetime.now() self.submission.save() # Get the existing answers answers = Answer.objects.select_related("submission", "data_from", "field").filter( data_form__slug=self.slug, submission=self.submission ) # Get the fields from the form post field_keys = [] for key in self.fields: # Mangle the key into the DB form, then get the right Field field_keys.append(_field_for_db(key)) # Get all fields that pertian to this dataform (from db) fields_from_db = self.query_data["field_query"] # Check for fields that aren't in the database and create a list of them fields_to_insert = [] for field in fields_from_db: has_answer = filter(lambda a: a.field.slug == field.slug, answers) if has_answer: continue else: fields_to_insert.append(field) # For these new fields, create answer objects for insertion, if any if fields_to_insert: new_answers = [] for field in fields_to_insert: # save the answer only if the field is in the form POST if field.slug in field_keys: # Create a new answer object answer = Answer() answer.submission = self.submission answer.data_form = self.query_data["dataform_query"] answer.field = field new_answers.append(answer) # Insert the new objects, if any if new_answers: insert_many(new_answers) # Get Answers again so that we have the pks if we had answers that were inserted answers = Answer.objects.select_related("submission", "data_from", "field").filter( data_form__slug=self.slug, submission=self.submission ) # Get All possible choices from form models dict choices = Choice.objects.all() # Setup answer list so we can do a bulk update answer_objects = [] # We know answers exist now, so update them if needed. for answer in answers: # Delete the choices so we can re-insert AnswerChoice.objects.filter(answer=answer).delete() answer_obj, choice_relations = self._prepare_answer(answer, choices) answer_objects.append(answer_obj) # If there are choices, do mass insert on them for each answer. if choice_relations: answer_choices = [] for choice in choice_relations: answer_choice = AnswerChoice() answer_choice.answer = answer answer_choice.choice = choice answer_choices.append(answer_choice) insert_many(answer_choices) # Update the answers update_many(answer_objects, fields=["value"]) # Return a submission so the collection or form can have this. return self.submission
def save(self, collection=None): """ Saves the validated, cleaned form data. If a submission already exists, the new data will be merged over the old data. """ # TODO: think about adding an "overwrite" argument to this function, default of False, # which will determine if an error should be thrown if the submission object already # exists, or if we should trust the data and overwrite the previous submission. # If there is no submission object, then this should just be a normal # Django form. No need to call the save method, so we will raise an exception if not hasattr(self, 'submission'): raise LookupError("There is no submission object. Are your creating the form with 'retrun_class=True'? If so, no need to call save.") if not self.cleaned_data: raise LookupError("The is_valid() method must be called before saving a form") # Slightly evil, do type checking to see if submission is a Submission object or string # If Submission object is a slug if isinstance(self.submission, str) or isinstance(self.submission, unicode): submission_slug = self.submission # Get or create the object self.submission, was_created = Submission.objects.get_or_create(slug=submission_slug, collection=collection) # Otherwise it should be a submission model object, if not raise elif not isinstance(self.submission, Submission): raise AttributeError('Submission %s is not a valid submission object.' % self.submission) # We now have a submission object, so let's update the last_modified field self.submission.last_modified = datetime.datetime.now() self.submission.save() # Delete Answers if they exist and start over ;) Answer.objects.select_related( 'submission', 'data_from', 'field').filter( data_form__slug=self.slug, submission=self.submission).delete() # If answers don't exist, create the records without answers so that # we can populate them later and save the relationships # This is more efficient then using the ORM #if not answers: field_keys = [] answers = [] for key in self.fields.keys(): # Mangle the key into the DB form, then get the right Field field_keys.append(_field_for_db(key)) # Get All Fields fields = self.query_data['fields_list'] for field in fields: # save the answer only if the field is in the form POST if field['slug'] in field_keys: # Create a new answer object answer = Answer() answer.submission = self.submission answer.data_form = self.query_data['dataform_query'] answer.field_id = field['id'] answers.append(answer) # Update the answers insert_many(answers) # Get Answers again so that we have the pks answers = Answer.objects.select_related('submission', 'data_from', 'field').filter(data_form__slug=self.slug, submission=self.submission) # Get All possible choices from form models dict choices = self.query_data['choice_query'] # Setup answer list so we can do a bulk update answer_objects = [] #Delete choice relations delete_many(answers, table='dataforms_answer_choice') # We know answers exist now, so update them if needed. for answer in answers: answer_obj, choice_relations = self._prepare_answer(answer, choices) answer_objects.append(answer_obj) if choice_relations: for choice_relation in choice_relations: answer.choice.add(choice_relation) # Update the answers update_many(answer_objects, fields=['value']) # Return a submission so the collection or form can have this. return self.submission