Retaining data on a webpage after a Django POST

Hi,

I’m looking for help maintaining the nested dictionary list event_info. In the radio button table I place this information I place this data in clears when I select an input and submit it. I want to maintain the data in the table so a user can choose another option after they have processed their previous selection.

{% extends 'main.html' %}

{% load static %}

{% block content %}
<style>
  .tableFixHead2 {
    overflow-y: scroll; /* make the table scrollable if height is more than 200 px  */
    height: 200px; /* gives an initial height of 200px to the table */
  }
  .tableFixHead2 thead th {
    position: sticky; /* make the table heads sticky */
    top: 0px; /* table head will be placed from the top of the table and sticks to it */
  }
  .tableFixHead2 table {
    border-collapse: collapse; /* make the table borders collapse to each other */
    width: 33%;
  }
  th,
  td {
    padding: 8px 16px;
    border: 1px solid #ccc;
  }
  th {
    background: #eee;
  }
</style>
<style>
  .tableFixHead {
    overflow-y: scroll; /* make the table scrollable if height is more than 200 px  */
    height: 300px; /* gives an initial height of 200px to the table */
  }
  .tableFixHead thead th {
    position: sticky; /* make the table heads sticky */
    top: 0px; /* table head will be placed from the top of the table and sticks to it */
  }
  .tableFixHead table {
    border-collapse: collapse; /* make the table borders collapse to each other */
    width: 100%;
  }
  th,
  td {
    padding: 8px 16px;
    border: 1px solid #ccc;
  }
  th {
    background: #eee;
  }
</style>

<h1>{{participant.participant_id}}</h1>
<br>
<ul>
    <li>Location: {{participant.location}}</li>
    <li>Isansys File Path: {{participant.isansys_file_path}}</li>
    <li>Processed File Path: {{participant.processed_file_path}}</li>
    <li>Reports File Path: {{participant.report_file_path}}</li>
</ul>
<br>
<h3>Isansys Files available for processing:</h3>
<form name="isansysForm" id="isansysForm" action="" method="POST">
    {% csrf_token %}
    <div class="tableFixHead2">
      <table>
        <thead>
          <tr>
            <th>Select</th>
            <th>Isansys Filename</th>
          </tr>
        </thead>
        <tbody>
          {% for isansys_file in isansys_file_list %}
          <tr>
            <td><input type="radio" name="isansys_file" value="{{ isansys_file }}" id="{{ isansys_file }}"></td>
            <td><label for="{{ isansys_file }}">{{ isansys_file }}</label></td>
          </tr>  
          {% endfor %}
        </tbody>
      </table>
    </div>
    <input type="submit" name="{{ isansys_file }}" class="btn btn-primary" value="Process" onclick="submitForm(event)" />
</form>
<br>
<h3>WFDB Files available for reporting:</h3>
<form id="wfdbForm" method="POST" action="">
  {% csrf_token %}
  <div class="tableFixHead">
    <table id="eventTable">
      <thead>
        <tr>
          <th>Select</th>
          <th>Event Name</th>
          <th>Event No.</th>
          <th>Start Time</th>
          <th>Classification</th>
          <th>Dropped Events</th>
          <th>Short Event</th>
        </tr>
      </thead>
      <tbody>
        {% for row in event_info %}
        <tr>
          <td><input type="radio" name="event_info" value="{{ row.name }}" id="{{ row.name }}"></td>
          <td><label for="{{ row.name }}">{{ row.name }}</label></td>
          <td>{{row.id}}</td>
          <td>{{row.timestamp}}</td>
          <td>{{row.classification}}</td>
          <td>{{row.drop}}</td>
          <td>{{row.short}}</td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
  <input type="submit" name="processed_file" class="btn btn-primary" value="Process" onclick="submitForm2(event2)" />
</form>

<script>
  function submitForm(event) {
    event.preventDefault();
    document.getElementById("isansysForm").submit();
    document.querySelector('input[type="submit"]').value = "Processing...";
    document.querySelector('input[type="submit"]').disabled = true;
  }
</script>

<script>
  const eventInfo = event_info;
  console.log("Here is event_info: ")
  console.log(eventInfo);
</script>

<script>
  function submitForm2(event2) {
    event2.preventDefault();
    document.getElementById("wfdbForm").submit();
    document.querySelector('input[type="submit"]').value = "Processing...";
    document.querySelector('input[type="submit"]').disabled = true;
  }
</script>

{% endblock content %}

We’ll also need to see the view(s) that are originally rendering this template and processing the submission.

Basically, you would need to initialize the objects being rendered by that view with whatever data is currently saved for those objects.

Thanks, Ken, here is the view I’m using:

@login_required(login_url="login")
def participant(request, pk):
    form = ProcessedDataFileForm
    participant = Participant.objects.get(id=pk)
    isansys_path = str(participant.isansys_file_path)
    processed_path = str(participant.processed_file_path)
    isansys_file_list = os.listdir(isansys_path)
    processed_file_list = [s for s in os.listdir(processed_path) if s.endswith('.dat')]
    event_info = []

    if request.method == 'POST':
        isansys_file = request.POST.get('isansys_file', '')
        processed_file = request.POST.get('event_info', '')
        if isansys_file != '' and processed_file == '':
            print(isansys_file)
            event_info = OnIsansys(isansys_file, isansys_path, processed_path)
            processed_file_list = [s for s in os.listdir(processed_path) if s.endswith('.dat')]

        elif processed_file != '' and isansys_file == '':
            print(processed_file)
            processed_file = processed_file
            ann_processed_file = processed_file
            print(ann_processed_file)
            processed_record = os.path.join(processed_path, processed_file)
            processed_annotation = os.path.join(processed_path, ann_processed_file)
            record = rdrecord(processed_record, physical=True)
            anno = rdann(processed_annotation, 'atr')
            plot_wfdb(record=record, annotation=anno, plot_sym=True, time_units='seconds',
                       title=processed_file, figsize=(10, 4), ecg_grids='all')


    context = {
        'participant': participant,
        'isansys_file_list': isansys_file_list,
        'processed_file_list': processed_file_list,
        'event_info': event_info,
        'form': form
    }
    return render(request, 'participants/single-participant.html', context)

Couple things:

  • You’re defining a form (actually, you’re getting a reference to a form class - you’re not even creating an instance of the form) and passing it into the context of your template, but I don’t see where you’re otherwise using it.

  • You’re rendering the event_info list, but you’re not “prepopulating” it with your data on a GET - this is why it’s showing blank.

Thanks, Ken,

On your first point can you explain how this will affect my template? I don’t kow the intricacies of a form method compared to a form class. What am I doing wrong here. The code worked fine until I started adding JavaScript code to disble buttons during the processing of my selected data files. This ties into your second point at it all worked until I added the JavaScript and the table clears after my first selection and I have to start with selecting a file to process and it repopulates the table. Does any of this make sense??

All the best,

Paul

It won’t. My point is that you’re defining a reference to a form class, but you’re not using it as far as I can tell. You could remove it with absolutely no side effects.

However, I do recommend that you review the docs at Working with forms | Django documentation | Django to start to learn what forms can do for you.

What I generally recommend in cases like this is that you refactor your code to use a form (and in the case of the file_list and event_info lists, a formset). But that’s not required - it’s just a suggestion.

Hi Ken,

Fair enough, point made. The form was from an earlier attempt, as I was figuring things out and it all grew arms and legs as I realised what I needed from my template. Once I understand why the table started to clear after selecting an option I will go back and look at how to use the form now I know everything that is required to make the template work how I want.

Thanks again,

Paul