Django’ da Ajax ile Dinamik Açılır Liste Nasıl Yapılır?

Django projelerinde kategori ve buna bağlı alt kategorili verilerimiz olabilir. Bunu kullanıcı arayüzünde açılır listeler ile formlarda sunabiliriz. Bu yazıda seçilen kategoriye göre bağlı alt kategorileri sayfayı yenilemeden dinamik olarak ajax ile backenden nasıl çekilir bunu anlatacağım.

Yazılım dillerini tutacağımız subject adında bir üst kategori ve bu kategoriye bağlı dillerin içeriklerini tutacak topic adında alt kategorilerinin olduğu bir veritabanı yapısı var.

Aşağıdaki html templatimizde de görüldüğü gibi sayfayı render ederken subjects verimizle birlikte render ediyoruz. Açılır listeden seçilen subject‘ e göre Topic açılır listemizi, backende yapacağımız ajax requestle verilerimizi çekip güncelliyeceğiz.

{% csrf_token %}
<div class="col-md-6">
  <div class="form-group">
    <label for="inputStatus">Subject</label>
    <select id="question-subject" class="form-control-sm custom-select">
      <option selected disabled>Choose a subject</option>
      {% for subject in subjects%}
      <option value="{{subject.id}}">{{subject.title}}</option>
      {% endfor %}
    </select>
  </div>
</div>
<div class="col-md-6">
  <div class="form-group">
    <label for="inputStatus">Topic</label>
    <select id="question-topic" class="form-control-sm custom-select" name="topic">
      <option selected disabled>Choose a topic</option>
    </select>
  </div>
</div>

Ajax requesti yapmak için ilk önce jquery kütüphanesini sayfamıza eklememiz gerekiyor.

Subject açılır listemize id="question-subject" idsini veriyoruz. Jquery selector ile bu listeyi seçip bu listede olan bir değişimi change eventi ile algılıyoruz. Seçilen subject’in ID‘ sini bir değişkene atıyoruz. Daha sonra get_topics_ajax ismindeki adrese ajax request yapıp requestten dönen veriler ile topic listemizi yeniliyoruz.

{% block javascript %}
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script>
    $("#question-subject").change(function () {
        const subjectId = $(this).val();  // Seçilen subject' in ID' sini değişkene atama 
        $.ajax({                       // AJAX request' başlatma
            type: "POST",
            url: '{% url "get_topics_ajax" %}',
            data: {
                'subject_id': subjectId,       // POST parameterlerine subject id' yi ekleme
                'csrfmiddlewaretoken':$('input[name=csrfmiddlewaretoken]').val(),
            },
            success: function (data) {   // `get_topics_ajax` view fonksiyonundan dönen veri
                let html_data = '<option value="">---------</option>';
                data.forEach(function (data) {
                    html_data += `<option value="${data.id}">${data.title}</option>`
                });
                $("#question-topic").html(html_data); // Serverden gelen veri ile topic listesinin içeriğini değiştirme
            }
        });
    });
</script>
{% endblock javascript %}

Backendde urls.py de ajax requestinin yapılacağı url tanımlayalım.

 path('get-topics-ajax/', get_topics_ajax, name="get_topics_ajax"),

Gelen url isteğine göre çalışacak fonksiyonumuzu view.py de aşağıdaki gibi tanımlıyoruz. subject_id ye göre ona bağlı topic‘ leri veritabanından çekiyoruz. Topic’ leri json verisi olarak frontende gönderiyoruz. Eğer bir problem olursa frontende error mesajı gönderiyoruz.

from quiz.models import Question, Topic, Subject
from django.http import JsonResponse,

def get_topics_ajax(request):
    if request.method == "POST":
        subject_id = request.POST['subject_id']
        try:
            subject = Subject.objects.filter(id = subject_id).first()
            topics = Topic.objects.filter(subject = subject)
        except Exception:
            data['error_message'] = 'error'
            return JsonResponse(data)
        return JsonResponse(list(topics.values('id', 'title')), safe = False) 

Başarılar Dilerim.