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

基于Django实现单页餐厅数据库下拉查询功能求助

Hey there! Let's get that single-page restaurant search sorted out for you. Here's a step-by-step approach to add those dropdown filters right in restaurants.html without needing a separate page:

1. Create a Search Form

First, add a new form class to your forms.py (you already have ReviewForm, so just append this):

from django import forms
from .models import Restaurant

class RestaurantSearchForm(forms.Form):
    # Reuse the choices from your Restaurant model for food and city
    food = forms.ChoiceField(choices=Restaurant.FOOD, required=False, label="Food Type")
    city = forms.ChoiceField(choices=Restaurant.CITY, required=False, label="City")
    # Add a dropdown for minimum average rating (since it's a calculated value)
    average_rating = forms.ChoiceField(
        choices=[('', 'Any'), (1, '1 Star & Up'), (2, '2 Stars & Up'), (3, '3 Stars & Up'), (4, '4 Stars & Up')],
        required=False,
        label="Minimum Average Rating"
    )

2. Update the restaurant_list View

Modify your views.py to handle form submissions and filter the restaurant results:

from .forms import ReviewForm, RestaurantSearchForm  # Import the new form

def restaurant_list(request):
    # Initialize form with any GET parameters from the request
    form = RestaurantSearchForm(request.GET)
    # Start with all restaurants, ordered by name
    restaurant_list = Restaurant.objects.order_by('-name')

    # Apply filters if form data is valid
    if form.is_valid():
        food_filter = form.cleaned_data.get('food')
        city_filter = form.cleaned_data.get('city')
        min_rating = form.cleaned_data.get('average_rating')

        if food_filter:
            restaurant_list = restaurant_list.filter(food=food_filter)
        if city_filter:
            restaurant_list = restaurant_list.filter(city=city_filter)
        if min_rating:
            # Since average_rating is a model method, we filter via list comprehension
            # For large datasets, consider storing average rating as a database field
            restaurant_list = [r for r in restaurant_list if r.average_rating() >= int(min_rating)]

    context = {
        'restaurant_list': restaurant_list,
        'form': form  # Pass the form to the template
    }
    return render(request, 'restaurants.html', context)

Note: Since average_rating is a computed method, we can't use Django's ORM filter() directly on it. The list comprehension works well for small datasets—if you have hundreds of restaurants, you’ll want to add a database field to store precomputed average ratings and update it whenever a review is added.

3. Update restaurants.html with Bootstrap-Styled Filters

Replace your existing search section with this Bootstrap 4-friendly code, and tweak the results table to show human-readable values:

{% extends 'base.html' %}
{% load staticfiles %}
{% load custom_filters %} <!-- Add this if you use the add_class filter below -->
{% block content %}
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <h3 class="text-center">Search Criteria</h3>
            <hr>
            <!-- Use GET method to keep filters in the URL -->
            <form method="get" class="form-inline justify-content-center">
                {{ form.food|add_class:"form-control mr-2" }}
                {{ form.city|add_class:"form-control mr-2" }}
                {{ form.average_rating|add_class:"form-control mr-2" }}
                <button type="submit" class="btn btn-primary">Search</button>
            </form>
        </div>
    </div>
</div>

<div class="container mt-4">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <h3 class="text-center">Search Results</h3>
            <hr>
            {% if restaurant_list %}
                <div class="table-responsive">
                    <table class="table table-bordered table-hover text-center">
                        <caption class="text-center">Restaurants matching your criteria</caption>
                        <thead>
                            <tr>
                                <th>Name</th>
                                <th>Description</th>
                                <th>Food Type</th>
                                <th>City</th>
                                <th>Average Rating</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for restaurant in restaurant_list %}
                            <tr>
                                <td class="text-left">
                                    <a href="{% url 'restaurants:restaurant_detail' restaurant.id %}">
                                        <strong>{{ restaurant.name }}</strong>
                                    </a>
                                </td>
                                <td class="text-left">{{ restaurant.desc }}</td>
                                <!-- Show human-readable food type instead of integer -->
                                <td>{{ restaurant.get_food_display }}</td>
                                <td>{{ restaurant.get_city_display }}</td>
                                <td>
                                    {% with avg_rating=restaurant.average_rating %}
                                        {% if avg_rating %}
                                            {{ avg_rating|floatformat:1 }} Stars
                                        {% else %}
                                            No Reviews
                                        {% endif %}
                                    {% endwith %}
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            {% else %}
                <p class="text-center">No restaurants match your search criteria.</p>
            {% endif %}
        </div>
    </div>
</div>
{% endblock %}

To apply Bootstrap's form-control class to form fields easily, create a templatetags folder in your app, add __init__.py and custom_filters.py:

from django import template

register = template.Library()

@register.filter(name='add_class')
def add_class(field, css_class):
    return field.as_widget(attrs={'class': css_class})

That's all! Now your restaurants.html will have three functional dropdown filters, handle searches on the same page, and display results with clean Bootstrap styling. You’ll see human-readable labels for food types and cities instead of raw integers, and the average rating will show up nicely (or note if there are no reviews).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:32