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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:42:44