You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JavaScript与Django模型过滤结果失效的问题求助

Let's get your city filtering working properly—let's break down the issues and fix them step by step:

1. Fix the Initial Session Setup Bug in JavaScript

First, your initial code has a typo that breaks setting the default city, which means your backend never gets a valid initial session value. Let's fix that and clean up the logic:

/* Ciudades */
if(localStorage.getItem("cities") == null){
 $.ajax({
 url: "/api/cities",
 method: "GET",
 dataType: "json",
 async: false
 })
 .done(function(data, status){
 localStorage.setObject("cities", data);
 })
 .fail(function(data, status){
 });
}
$.each(localStorage.getObject("cities"), function(i, c){
 template = '<li><a href="" class="header-city-option" data-id="' + c.id + '" data-name="' + c.name + '">' + c.name + '</a></li>';
 $("#header-city-list").append(template);
});

// Fix the typo and properly initialize default city
if(localStorage.getItem("city-id") == null){
 const firstCityLink = $("#header-city-list li:first-child a");
 const defaultCityName = firstCityLink.data("name");
 const defaultCityId = firstCityLink.data("id");
 
 localStorage.setItem("city-name", defaultCityName);
 localStorage.setItem("city-id", defaultCityId);
 setCityInServer(defaultCityName, defaultCityId, false);
}

$("#header-city").html(localStorage.getItem("city-name") + ' <span class="caret"></span>');
$.each($(".city-filter-input") , function(i, v){
 $(v).val(localStorage.getItem("city-id"));
 changeHomepageByCity(localStorage.getItem("city-name"), localStorage.getItem("city-id"), false);
});
$(".header-city-option").click(function(ev){
 ev.preventDefault();
 var city = $(this).data("name");
 var id = $(this).data("id");
 localStorage.setItem("city-name", city);
 localStorage.setItem("city-id", id);
 $("#header-city").html(city + ' <span class="caret"></span>');
 $.each( $(".city-filter-input") , function(i, v){
 $(v).val(id);
 });
 setCityInServer(city, id, true);
});
function changeHomepageByCity(city, id, isClicked){
 changeBackground(city);
 changeText(city);
 setCityInServer(city, id, isClicked);
}
function changeBackground(city){
 var urlBackground;
 switch(city){
 case "Manchester":
 urlBackground = "/static/img/fondo_main.jpg";
 break;
 case "Liverpool":
 urlBackground = "/static/img/liverpool_background.jpg";
 break;
 }
 $("#main").css("background-image", "url(" + urlBackground + ")");
}
function changeText(city){
 switch(city){
 case "Manchester":
 $("#main h2").html("Live the languages with Milingual in Manchester");
 $("#main p").html("We organize language conversation groups in the best venues in Manchester");
 break;
 case "Liverpool":
 $("#main h2").html("Live the languages with Milingual in Liverpool");
 $("#main p").html("We organize language conversation groups in the best venues in Liverpool");
 break;
 }
}
function setCityInServer(city, id, isClicked){
 var token = $("input[name*='csrfmiddlewaretoken']")[0].value;
 $.ajax({
 type: "POST",
 url: "set-city-session",
 data: { cityName: city, cityId: id, csrfmiddlewaretoken: getCookie('csrftoken') },
 success: function(){
 if(isClicked) location.reload();
 }
 });
}

The key fixes here:

  • Corrected the typo li:first-childa a to li:first-child a
  • Properly defined and passed the default city values to setCityInServer
  • Removed the redundant location.reload() call before the AJAX request

2. Add Session Fallback & Implement City Filtering in Django Views

Your main issue with the KeyError is that you're trying to access session values that might not exist yet. Use request.session.get() to safely retrieve values with defaults, then apply the city filter to your queries:

def IndexPage(request):
    # Get city from session, use a default if it doesn't exist (e.g., Manchester or first city in DB)
    default_city = City.objects.first()  # Fallback to first city in your database
    city_name = request.session.get('city-name', default_city.name)
    city_id = request.session.get('city-id', default_city.id)

    # Filter venues to only the current city
    venues = ProfileVenue.objects.filter(city__name=city_name)
    
    # Optimize occurrence query to avoid N+1 database hits
    oc_list = Occurrence.objects.filter(
        date__gte=timezone.now(),
        event__location__in=venues
    ).select_related('event__location')[:3]

    # Filter teachers to the current city
    teachers_list = ProfileTeacher.objects.filter(
        published=True,
        city__name=city_name
    )[:3]

    languages = Language.objects.all()
    levels = LanguageLevel.objects.all()
    events = EventType.objects.all()

    context = {
        'venues_today': oc_list,
        'teachers': teachers_list,
        'languages': languages,
        'levels': levels,
        'events': events
    }
    return render(request, "index.html", context)

def SetCitySession(request):
    if request.method == "POST":
        # Safely set session values
        request.session['city-name'] = request.POST.get('cityName', '')
        request.session['city-id'] = request.POST.get('cityId', '')
        return JsonResponse({})

def GetCitySession(request):
    if request.method == "GET":
        default_city = City.objects.first()
        # Return fallback values if session is empty
        cityName = request.session.get('city-name', default_city.name)
        cityId = request.session.get('city-id', default_city.id)
        context = { "cityName": cityName, "cityId": cityId }
        return JsonResponse(context)

Key improvements here:

  • Used request.session.get() to avoid KeyError when session values don't exist
  • Added a database fallback to the first city in your City model for robustness
  • Optimized queries to avoid looping and N+1 database requests
  • Applied city filters to both venues and teachers

3. Verify URL Routing

Make sure your set-city-session endpoint is correctly mapped in urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.IndexPage, name='index'),
    path('set-city-session/', views.SetCitySession, name='set-city-session'),
    path('get-city-session/', views.GetCitySession, name='get-city-session'),
    # Add other URLs as needed
]

How It Works Now

  1. On first load: The frontend grabs the first city from your API, sets it in localStorage, and sends it to the backend to store in the session. The view uses this city to filter all data.
  2. When a user selects a city: The frontend updates localStorage, sends the new city to the backend to update the session, then reloads the page. The view now uses the new city to filter results.
  3. On page refresh: The frontend pulls the city from localStorage, and the view pulls it from the session—keeping everything in sync.

内容的提问来源于stack exchange,提问作者fmakawa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:58:04