[Django]-Emulating a ManyToManyField with multiple radio buttons

2πŸ‘

βœ…

It doesn’t actually let the user select more than one radio button at
once. On the other hand, if I name the radio buttons answers[0] and
answers[1], in POST, it sends two separate entities with those names
instead of sending a combined answers.

This doesn’t fullfil your requirements, but atleast resolve one mystery. When you use answers[] as name, backend will recognize it as array and join all values into array. This is possible with any input type except single (radio/select).

And this is js solution you can use, but your situation shows that model you are using is not optimal for this case. Ofc course it can be solved hacky way like bellow, but you will always have to solve workarounds when you meet this code..

So my advice: change approach in backend

document.getElementById('answers').onsubmit = function(e) {
  e.preventDefault(); //prevent submit;
  let clone = this.cloneNode(true);
  let inputs = clone.querySelectorAll('input[type=radio]');
  let formData = new FormData(clone); // HTML5
  // dumb check for validity
  if (Array.from(formData.values()).length != clone.querySelectorAll('fieldset').length) {
  	alert('Invalid form!')
  	return false;
  }  
  for (let i=0;i<inputs.length;i++) {
    inputs[i].type = "checkbox";
    inputs[i].name = "answers[]";
  }
  // only for snippet
  formData = new FormData(clone);
  console.log(Array.from(formData.entries()));
  // commented in snippet
  //clone.submit(); 
}

/* This is cleaner submit by JS without reload
document.getElementById('answers').onsubmit = function(e) {
	let formData = new FormData(this); // HTML5
  let answers = Array.from(formData.values());
  // dumb check for validity
  if (answers.length != this.querySelectorAll('fieldset').length) {
  	alert('Invalid form!')
  	return false;
  }
  let newFormData = new FormData();
  newFormData.set('answers', answers);
  let request = new XMLHttpRequest();
	request.open(this.method || "POST", this.action || '/default/post/link');
	request.send(newFormData);
  return false;
}
*/
<form action="" method="post" id="answers">
    <fieldset>
        <legend>Question 1</legend>
        <input name="question_1" id="id_1" value="1" type="radio">
        <label for="id_1">Answer 1</label>
        <br>

        <input name="question_1" id="id_2" value="2" type="radio">
        <label for="id_2">Answer 2</label>
        <br>

        <input name="question_1" id="id_3" value="3" type="radio">
        <label for="id_3">Answer 3</label>
        <br>
    </fieldset>
    <fieldset>
        <legend>Question 2</legend>
        <input name="question_2" id="id_4" value="4" type="radio">
        <label for="id_4">Answer 1</label>
        <br>
        <input name="question_2" id="id_5" value="5" type="radio">
        <label for="id_5">Answer 2</label>
        <br>
    </fieldset>
    <button type="submit">Submit</button>
</form>
πŸ‘€bigless

0πŸ‘

Changing the radio buttons to checkboxes should allow you to select multiple values.

<form action="" method="post">
    <fieldset>
        <legend>Question 1</legend>
        <input name="answers" id="id_1" value="1" type="checkbox">
        <label for="id_1">Answer 1</label>
        <br>

        <input name="answers" id="id_2" value="2" type="checkbox">
        <label for="id_2">Answer 2</label>
        <br>

        <input name="answers" id="id_3" value="3" type="checkbox">
        <label for="id_3">Answer 3</label>
        <br>
    </fieldset>
    <fieldset>
        <legend>Question 2</legend>
        <input name="answers" id="id_4" value="4" type="checkbox">
        <label for="id_4">Answer 1</label>
        <br>
        <input name="answers" id="id_5" value="5" type="checkbox">
        <label for="id_5">Answer 2</label>
        <br>
    </fieldset>
</form>

The HTTP POST generated by this form should be exactly the same as the example you gave above with the select tag.

Leave a comment