docs: def blast(request, blast_form, template_init, template_result, blast_commandline, sample_fasta_path,
            extra_context=None):
      """
      Process blastn/tblastn (blast+) query or set up initial blast form.
      """
  
      if request.method == 'POST':
  
          form = blast_form(request.POST)
  
          if form.is_valid():
  
              query_file_object_tmp = form.cleaned_data['sequence_in_form']
              evalue = float(form.cleaned_data['evalue_in_form'])
              word_size = int(form.cleaned_data['word_size_in_form'])
              database_path = str(form.cleaned_data['blast_db_in_form'])
  
              standard_opt_dic = {'query': query_file_object_tmp, 'evalue': evalue, 'outfmt': 5, 'db': database_path,
                                  'word_size': word_size}
              annotated = utils.get_annotation(database_path, BLAST_DB_NUCL_LIST)
  
              # none standard options:
              try:
                  matrix = str(form.cleaned_data['matrix_in_form'])
                  standard_opt_dic["matrix"] = matrix
              except:
                  pass
  
              sensitivity_opt_dic = ast.literal_eval(str(form.cleaned_data['search_sensitivity_in_form']))
  
              blast_records__file_xml = None
              try:
  
                  # blast search, parse results from temp file, put them into template for rendering.
                  blast_records__file_xml, blast_error = utils.run_blast_commands(blast_commandline,
                                                                                  **dict(standard_opt_dic,
                                                                                         **sensitivity_opt_dic))
  
                  if len(blast_error) > 0:
                      return render(request=request, template_name=template_result,
                                    context={"blast_record": '', blast_error: BLAST_CORRECT_PARAMS})
  
                  else:
  
                      # converts blast results into objects and pack into list
                      blast_records_in_object_and_list = utils.blast_records_to_object(
                          list(NCBIXML.parse(blast_records__file_xml)))
  
                      # user defined function to modify blast results
                      # e.g. join blast results with external database in template
                      if extra_context is not None:
                          blast_records_in_object_and_list = extra_context(blast_records_in_object_and_list)
  
                      return render(request=request, template_name=template_result,
                                    context={'application': blast_records_in_object_and_list[0].application,
                                             'version': blast_records_in_object_and_list[0].version,
                                             'blast_records': blast_records_in_object_and_list,
                                             'annotated': annotated})
  
              finally:
                  # remove result - temporary file
                  if blast_records__file_xml is not None:
                      os.remove(blast_records__file_xml.name)
  
      else:
          form = blast_form(initial={'sequence_in_form': '', 'evalue_in_form': EVALUE_BLAST_DEFAULT})
  
      return render(request=request, template_name=template_init,
                    context={'form': form, 'sequence_sample_in_fasta': utils.get_sample_data(sample_fasta_path),
                             "blast_max_number_seq_in_input": BLAST_MAX_NUMBER_SEQ_IN_INPUT, })