在Django中创建视图展示外键数据:理发师可用日期查询
Django 实现理发师与可用日期的关联查询视图
嘿,我来帮你搞定这个需求!首先看你给的models.py代码没写完,咱们先把模型补全——要实现理发师和可用日期的关联,得加一个专门存理发师可用日期的模型,这样才能建立外键关联关系。
第一步:完善模型定义
先把Barber模型补全,再新增BarberAvailability模型来关联理发师和他们的可用日期:
from django.db import models from datetime import date, time class Barber(models.Model): BARBERS = ( ('KK', 'Kim Kardashian'), ('CJ', 'Caitlin Jenner'), ('KW', 'Kanye West') ) LOCATION = ( ('CL', 'Central Detroit'), ('NL', 'North Detroit'), ('SL', 'South Detroit'), # 补全你未写完的选项 ) code = models.CharField(max_length=2, choices=BARBERS, unique=True) name = models.CharField(max_length=50) location = models.CharField(max_length=2, choices=LOCATION) def __str__(self): return self.name # 新增:存储理发师的可用日期模型 class BarberAvailability(models.Model): barber = models.ForeignKey(Barber, on_delete=models.CASCADE, related_name='available_dates') available_date = models.DateField() # 可选:添加时间段字段,细化可用时间范围 available_start_time = models.TimeField(default=time(9, 0)) available_end_time = models.TimeField(default=time(18, 0)) class Meta: # 确保同一个理发师在同一天只有一条记录,避免重复 unique_together = ('barber', 'available_date') def __str__(self): return f"{self.barber.name} - {self.available_date}"
第二步:编写视图函数
接下来写两个视图,分别实现你的两个核心需求:
1. 查询指定理发师的可用日期
这个视图接收理发师的code(比如KK),返回该理发师所有的可用日期:
from django.shortcuts import render, get_object_or_404 from .models import Barber, BarberAvailability def barber_available_dates(request, barber_code): # 获取指定理发师,不存在则返回404页面 barber = get_object_or_404(Barber, code=barber_code) # 过滤该理发师的所有可用日期,并按日期排序 available_dates = BarberAvailability.objects.filter(barber=barber).order_by('available_date') context = { 'barber': barber, 'available_dates': available_dates } return render(request, 'barber_available_dates.html', context)
2. 查询指定日期的可用理发师
这个视图接收日期参数(比如2024-05-20),返回当天所有有空的理发师:
from django.shortcuts import render from .models import Barber from datetime import date def available_barbers_by_date(request): # 从GET参数中获取目标日期 target_date_str = request.GET.get('date') context = {'error': None} if not target_date_str: context['error'] = '请指定查询日期,格式为YYYY-MM-DD' return render(request, 'available_barbers.html', context) try: # 将字符串转换为date对象,处理格式错误的情况 target_date = date.fromisoformat(target_date_str) except ValueError: context['error'] = '日期格式错误,请使用YYYY-MM-DD格式' return render(request, 'available_barbers.html', context) # 过滤当天可用的理发师,用select_related优化查询性能 available_barbers = Barber.objects.filter( available_dates__available_date=target_date ).select_related('available_dates').distinct() context.update({ 'target_date': target_date, 'available_barbers': available_barbers }) return render(request, 'available_barbers.html', context)
第三步:配置URL路由
在你的app的urls.py里添加这两个视图的路由映射:
from django.urls import path from . import views urlpatterns = [ # 查询指定理发师的可用日期,示例URL:/barber/KK/available-dates/ path('barber/<str:barber_code>/available-dates/', views.barber_available_dates, name='barber_available_dates'), # 查询指定日期的可用理发师,示例URL:/available-barbers/?date=2024-05-20 path('available-barbers/', views.available_barbers_by_date, name='available_barbers_by_date'), ]
第四步:编写模板示例
简单写两个模板来展示查询结果:
模板1:barber_available_dates.html
<h1>{{ barber.name }} 的可用日期</h1> <p>工作地点:{{ barber.get_location_display }}</p> {% if available_dates %} <ul> {% for availability in available_dates %} <li>{{ availability.available_date }}({{ availability.available_start_time }} - {{ availability.available_end_time }})</li> {% endfor %} </ul> {% else %} <p>该理发师目前没有可预约的日期</p> {% endif %}
模板2:available_barbers.html
<h1>{{ target_date }} 可预约的理发师</h1> {% if error %} <p style="color: red;">{{ error }}</p> {% elif available_barbers %} <ul> {% for barber in available_barbers %} <li>{{ barber.name }}({{ barber.get_location_display }})</li> {% endfor %} </ul> {% else %} <p>当天没有可预约的理发师</p> {% endif %}
小优化建议
- 用
select_related/prefetch_related减少数据库查询次数,提升页面加载速度 - 如果需要支持时间段筛选,可以在视图中添加时间参数的过滤逻辑
- 可以将视图改写为Django类视图(比如
DetailView/ListView),让代码更简洁规范
内容的提问来源于stack exchange,提问作者Davtho1983
相关产品推荐
相关产品推荐

