Django项目中HTML Select组件无法加载选中选项问题求助
Django ListView中产品筛选下拉框无法保留选中状态问题
问题描述
在首个Django项目中,使用ListView结合Foundation框架实现多下拉框筛选表格数据。设置筛选条件后数据展示正常,但产品Select组件无法加载上次选中的选项,始终默认显示第一个“Todos”选项。已确认productselect参数在请求中正常传递,但HTML始终加载默认选项。
相关代码
ListView代码
class ListSales(LoginRequiredMixin, ListView): template_name = "sales/list.html" context_object_name = 'sales' login_url = reverse_lazy('users_app:user-login') paginate_by = 5 def get_queryset(self): client = self.request.GET.get("clientselect", "") payment_method = self.request.GET.get("paymentselect", "") date1 = self.request.GET.get("date1", '') date2 = self.request.GET.get("date2", '') product = self.request.GET.get("productselect", '') if date1 == '': date1 = datetime.date.today() if date2 == '': date2 = datetime.date.today() queryset = Sale.objects.get_sales_list( date1, date2, client, payment_method) qty_total_product = 0 if product != '0' and product != '': print(Product.objects.get(id=product).full_name) print(queryset) for querysale in queryset: print(querysale) for query_sale_detail in querysale.sale_details(): print(query_sale_detail.product.full_name + " " + str(query_sale_detail.count)) if str(query_sale_detail.product.id) == product: qty_total_product += query_sale_detail.count print(qty_total_product) obj_sales_list_filter, created_obj_sales_list_filter = SalesListFilters.objects.get_or_create( id=1, defaults={ 'datefrom': date1, 'dateTo': date2, 'client': Client.objects.search_id(client), 'payment_method': PaymentMethod.objects.search_id(payment_method) }) if not created_obj_sales_list_filter: obj_sales_list_filter.datefrom = date1 obj_sales_list_filter.dateTo = date2 obj_sales_list_filter.client = Client.objects.search_id(client) obj_sales_list_filter.payment_method = PaymentMethod.objects.search_id( payment_method) obj_sales_list_filter.save() return queryset def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["clients"] = Client.objects.all().order_by('full_name') context["payment_methods"] = PaymentMethod.objects.all() context["products"] = Product.objects.all().order_by('full_name') sales_list_filters = SalesListFilters.objects.all() if sales_list_filters is None or sales_list_filters == {} or not sales_list_filters: context["date1"] = str(datetime.date.today()) context["date2"] = str(datetime.date.today()) else: sales_list_filters = SalesListFilters.objects.get(id=1) context["date1"] = str(sales_list_filters.datefrom) context["date2"] = str(sales_list_filters.dateTo) if(sales_list_filters.client is None): context["clientselect"] = 0 else: context["clientselect"] = sales_list_filters.client.id if(sales_list_filters.payment_method is None): context["paymentselect"] = 0 else: context["paymentselect"] = sales_list_filters.payment_method.id current_sale_info = CurrentSaleInfo.objects.get(id=1) if current_sale_info is None or current_sale_info == {} or current_sale_info.invoice_number is None: context["current_sale_info"] = False else: context["current_sale_info"] = True product = self.request.GET.get("productselect", '') print("el producto seleccionado es:"+product+" "+str(type(product))) if(product == '' or product == '0'): print("Entro por defecto") context["product_select"] = 0 else: print("Entro por valor") context["product_select"] = int(product) return context
HTML模板代码
{% extends "panel.html" %} {% load static %} {% block panel-content %} <div class="grid-x medium-10"> <h3 class="cell medium-12" style="text-align: center;">Ventas</h3> <div class="cell medium-12">  </div> <form class="cell medium-12" method="GET">{% csrf_token %} <div class="input-group grid-x medium-12"> <div class="input-group cell medium-2 grid-x"> <label class="cell medium-12">Desde:</label> <span class="input-group-label"><i class="fi-calendar"></i></span> <input type="date" id="date1" name="date1" class="input-group-field" type="date" value={{date1}}> </div>     <div class="input-group cell medium-2 grid-x"> <label class="cell medium-12">Hasta:</label> <span class="input-group-label"><i class="fi-calendar"></i></span> <input type="date" id="date2" name="date2" class="input-group-field" type="date" value={{date2}}> </div>                   <div class="input-group cell medium-2 grid-x"> <label class="cell medium-12">Cliente:</label> <span class="input-group-label"><i class="fi-torso"></i></span> <select id="clientselect" name="clientselect" class="input-group-field"> <option value="0" id="option0" name="option0" {% if clientselect is 0 %} selected {% endif %}>Todos</option> <option value="-1" id="option-1" name="option-1" {% if clientselect is -1 %} selected {% endif %}>Sin Cliente</option> {% for client in clients %} <option value="{{client.pk}}" id="option{{client.pk}} " name="option{{client.pk}}" {% if clientselect is client.pk %} selected {% endif %}>{{client.full_name}}</option> {% endfor %} </select> </div>     <div class="input-group cell medium-2 grid-x"> <label class="cell medium-12">Método de Pago:</label> <span class="input-group-label"><i class="fi-dollar-bill"></i></span> <select id="paymentselect" name="paymentselect" class="input-group-field"> <option value="0" id="option0" name="option0" {% if paymentselect is 0 %} selected {% endif %}>Todos</option> {% for pm in payment_methods %} <option value="{{pm.pk}}" id="option{{pm.pk}} " name="option{{pm.pk}}" {% if paymentselect is pm.pk %} selected {% endif %}>{{pm.full_name}}</option> {% endfor %} </select> </div>    <div class="input-group cell medium-3 grid-x"> <label class="cell medium-12">Producto:</label> <span class="input-group-label"><i class="fi-list"></i></span> <select id="productselect" name="productselect" class="input-group-field"> <option value="0" id="option0" name="option0" {% if product_select is 0 %} selected {% endif %}>Todos</option> {% for prod in products %} <option value="{{prod.pk}}" id="option{{prod.pk}} " name="option{{prod.pk}}" {% if product_select is prod.pk %} selected {% endif %}>{{prod.full_name}}</option> {% endfor %} </select> </div> <div class="cell medium-1"> <button type="submit" class="button cell medium-4"><i class="fi-filter"></i>  Filtrar</button> </div> <div class="cell medium-1"> <h5>{{product_text}}</h5> </div> </div> </form> <div class="cell medium-12"> </div> <table class="cell medium-12"> <thead> <th>Fecha</th> <th>Nro Factura</th> <th>Cliente</a></th> <th>Método de Pago</a></th> <th>Monto</th> <th>Acciones</th> </thead> <tbody> {% for sale in sales %} <tr> <td>{{ sale.show_date }}</td> <td>{{ sale.invoice_number }}</td> <td>{{ sale.client.full_name }}</td> <td>{{ sale.payment_method }}</td> <td>${{ sale.amount_with_discount}}</td> <td> <div class="button-group"> <a href="#" class="button warning tiny" data-toggle="modalView{{sale.pk}}"><i class="fi-eye"></i></a> </td> </div> </tr> <div class="tiny reveal" id="modalView{{sale.pk}}" style="background-color:rgb(51,51,51);" data-reveal data-close-on-click="true" data-animation-in="spin-in" data-animation-out="spin-out"> <h4 class="cell" style="text-align: center;">Detalle de Venta</h4> <br> {% for sale_detail in sale.sale_details %} <h5 style="text-align: center;">{{sale_detail.product.full_name}} X {{sale_detail.count}} : $ {{sale_detail.sale_detail_total}}</h5> {% endfor %} <h5 style="text-align: center;">--------------------------------------------------</h5> <h5 style="text-align: center;">SUB TOTAL: $ {{sale.amount}}</h5> <h5 style="text-align: center;">DESCUENTO: $ {{sale.discount}}</h5> <h4 style="text-align: center;" class="detailtag">TOTAL: $ {{sale.amount_with_discount}}</h5> <button class="close-button" data-close aria-label="Close modal" type="button"> <span aria-hidden="true">×</span> </button> </div> {% endfor %} </tbody> </table> {% if is_paginated %} <ul class="pagination cell medium-12"> {% if page_obj.has_previous %} <li><a href="?page={{ page_obj.previous_page_number }}&{{ view.urlencode_filter }}" style="color: wheat;">«</a></li> {% else %} <li class="disabled"><span style="color: wheat;">«</span></li> {% endif %} {% for i in paginator.page_range %} {% if page_obj.number == i %} <li class="active"> <span style="color: wheat;">{{ i }} <span class="sr-only">(actual)</span></span> </li> {% else %} <li><a href="?page={{ i }}&{{ view.urlencode_filter }}" style="color: wheat;">{{ i }}</a></li> {% endif %} {% endfor %} {% if page_obj.has_next %} <li><a href="?page={{ page_obj.next_page_number }}&{{ view.urlencode_filter }}" style="color: wheat;">»</a></li> {% else %} <li class="disabled"><span style="color: wheat;">»</span></li> {% endif %} </ul> {% endif %} </div> {% endblock panel-content %}
问题截图
- 筛选前:

- 筛选后:

解决方案
问题根源
- 产品筛选条件未持久化到
SalesListFilters模型,仅依赖request.GET参数,分页或页面刷新时参数易丢失 - Django模板中使用
is进行数值比较,is用于对象身份判断,数值比较应使用==
修复步骤
- 更新
SalesListFilters模型:新增产品字段保存筛选条件
class SalesListFilters(models.Model): datefrom = models.DateField() dateTo = models.DateField() client = models.ForeignKey(Client, on_delete=models.SET_NULL, null=True, blank=True) payment_method = models.ForeignKey(PaymentMethod, on_delete=models.SET_NULL, null=True, blank=True) product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True, blank=True) # 新增字段
- 修改ListView的
get_queryset方法:保存产品筛选条件到数据库
def get_queryset(self): # ... 现有代码 ... product = self.request.GET.get("productselect", "") # ... 现有代码 ... obj_sales_list_filter, created_obj_sales_list_filter = SalesListFilters.objects.get_or_create( id=1, defaults={ 'datefrom': date1, 'dateTo': date2, 'client': Client.objects.search_id(client), 'payment_method': PaymentMethod.objects.search_id(payment_method), 'product': Product.objects.search_id(product) if product != '' and product != '0' else None }) if not created_obj_sales_list_filter: obj_sales_list_filter.datefrom = date1 obj_sales_list_filter.dateTo = date2 obj_sales_list_filter.client = Client.objects.search_id(client) obj_sales_list_filter.payment_method = PaymentMethod.objects.search_id(payment_method) obj_sales_list_filter.product = Product.objects.search_id(product) if product != '' and product != '0' else None obj_sales_list_filter.save() # ... 现有代码 ...
- 修改
get_context_data方法:优先读取当前请求参数,再回退到数据库保存的历史条件
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # ... 现有代码 ... sales_list_filters = SalesListFilters.objects.all() if sales_list_filters is None or sales_list_filters == {} or not sales_list_filters: # ... 现有代码 ... context["product_select"] = 0 else: sales_list_filters = SalesListFilters.objects.get(id=1) # ... 现有代码 ... # 读取保存的产品筛选条件 if sales_list_filters.product is None: context["product_select"] = 0 else: context["product_select"] = sales_list_filters.product.id # 优先处理当前请求的筛选参数 product = self.request.GET.get("productselect", '') if product != '' and product != '0': context["product_select"] = int(product) # ... 现有代码 ... return context
- 修正模板判断逻辑:将
is改为==进行数值比较
<select id="productselect" name="productselect" class="input-group-field"> <option value="0" {% if product_select == 0 %} selected {% endif %}>Todos</option> {% for prod in products %} <option value="{{prod.pk}}" {% if product_select == prod.pk %} selected {% endif %}>{{prod.full_name}}</option> {% endfor %} </select>
内容的提问来源于stack exchange,提问作者Guillermo Zooby
相关产品推荐
相关产品推荐

