Chained select inputs using Django CBV

41 Views Asked by At

I am trying to create an interface for a teacher to set homework tasks. This homework includes a student, a chapter, and questions belonging to a selected chapter. Therein lies my problem, I would like for my chapter dropdown to limit the selection from my question dropdown.

Here is the current model, I added a chapter to simplify this process however ideally the chapter is not a necessary part of the homework, it only serves as a filter for the questions.

class Homework(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    chapter = models.ForeignKey(
        Chapter, on_delete=models.SET_NULL, null=True, related_name="chapter_homework"
        )
    question = models.ForeignKey(
        Question, on_delete=models.CASCADE, related_name="homework"
        )
    agenda = models.ForeignKey(
        Agenda, on_delete=models.CASCADE, related_name="homeworks"
        )

This is the CreationView I have modified :

class HomeworkCreationView(CreateView):
    template_name = "agenda/homework_create.html"
    form_class = HomeworkForm
    success_url = reverse_lazy("agenda:create_homework")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['chapters'] = Chapter.objects.filterByAuthor(self.request.user)
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs["user"] = self.request.user
        return kwargs

And this is a function based view which is meant to asynchronously update the question choices :

def loadQuestions(request):
    chapter_id = request.GET.get('chapter')
    questions = Question.objects.filterByChapterID(chapter_id).order_by('title')
    return render(request, 'agenda/question_dropdown_list_options.html', {'questions':questions})

Here is the form :

class HomeworkForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        user = kwargs.pop("user", None)
        super().__init__(*args, **kwargs) 
        teacher = user.userToTeacher()

        self.fields["chapter"].queryset = Chapter.objects.filterByAuthor(teacher)

        self.fields['question'].queryset = Question.objects.none()


class Meta:
    model = Homework
    fields = [ "chapter", "question", "due_date", "agenda"]

URLS.py :

app_name = "agenda"

urlpatterns = [
    path("homework", HomeworkCreationView.as_view(), name="create_homework"),
    path('homework/load-questions/', loadQuestions, name='load_questions'),
]

Here is the HTML and JS for the form page homework_create.html :

{% extends "base.html" %}

{% block title %}Create Homework{% endblock %}

{% block content %}
  <h1>Give your students homework</h1>
  <p>Choose a chapter and then select a question to add to your students agenda</p>

  <form method="post" id="homeworkForm" data-questions-url="{% url 'agenda:load_questions' %}">
    {% csrf_token %}
    <table>
      {{ form.as_table }}
    </table>
    <button type="submit">Save</button>
  </form>
{% endblock %}

<script>
  document.getElementById("id_chapter").addEventListener("change", function() {
    var formElement = document.getElementById("homeworkForm");
    var url = formElement.getAttribute("data-questions-url");
    var chapterID = this.value;

    var xhr = new XMLHttpRequest();
    xhr.open("GET", url + "?chapter=" + chapterID, true);
    xhr.onload = function() {
      if (xhr.status === 200) {
        document.getElementById("id_question").innerHTML = xhr.responseText;
      }
    };
    xhr.send(); 
  });
</script>

Finally here is the question_dropdown_list_options.html used for loading the questions :

<option value="">---------</option>
{% for question in questions %}
  <option value="{{ question.id }}">{{ question.title }}</option>
{% endfor %}

I have found multiple tutorials and solutions that I can't quite get to work using simple Django form template. I'd also like to use "vanilla" JS (no ajax or jquery). Finally I have seen smart-select is an option but I would like to keep my models unchanged apart for getting rid of chapter in homework if possible.

0

There are 0 best solutions below