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

Django报错:Generic detail view需在URLconf传入pk或slug求助

解决Django DetailView URL关联错误:"Generic detail view must be called with either an object pk or a slug"

问题根源

Django的DetailView默认要求URL中传入对象的pk或slug参数定位单个对象,但你的视图是通过location_slug和date组合筛选数据,仅重写get_queryset无法覆盖DetailView的默认对象查找逻辑,因此触发错误。

修复步骤

1. 修正URL中的日期转换器

在urls.py中,将<date>改为<date:date>,让Django自动将URL中的日期字符串转换为date对象:

# urls.py
urlpatterns = [
    path("<slug:location_slug>/<date:date>/", DailyForecastDetailView.as_view(), name="daily_forecast_detail"),
    path("<slug:location_slug>/", DailyForecastTodayView.as_view(), name="daily_forecast_today"),
    path("<slug:location_slug>/<date:date>/<int:hour>/", HourlyForecastDetailView.as_view(), name="hourly_forecast_detail"),
]

2. 重写DetailView的get_object方法

替换原来的get_queryset为get_object,直接返回筛选后的单个对象:

修改DailyForecastDetailView

# views.py
class DailyForecastDetailView(DetailView):
    model = DailyForecast
    template_name = "forecast/daily_forecast_detail.html"
    context_object_name = "forecast"

    def get_object(self, queryset=None):
        location_slug = self.kwargs["location_slug"]
        target_date = self.kwargs["date"]
        location = get_object_or_404(Location, slug=location_slug)
        return get_object_or_404(DailyForecast, location=location, date=target_date)

修改DailyForecastTodayView

# views.py
class DailyForecastTodayView(DetailView):
    model = DailyForecast
    template_name = "forecast/daily_forecast_detail.html"
    context_object_name = "forecast"

    def get_object(self, queryset=None):
        location_slug = self.kwargs["location_slug"]
        location = get_object_or_404(Location, slug=location_slug)
        return get_object_or_404(DailyForecast, location=location, date=date.today())

修正HourlyForecastDetailView的筛选条件

模型中没有hour字段,需通过time__hour筛选小时,同时重写get_object:

# views.py
class HourlyForecastDetailView(DetailView):
    model = HourlyForecast
    template_name = "forecast/hourly_forecast_detail.html"
    context_object_name = "forecast"

    def get_object(self, queryset=None):
        location_slug = self.kwargs["location_slug"]
        target_date = self.kwargs["date"]
        target_hour = self.kwargs["hour"]
        location = get_object_or_404(Location, slug=location_slug)
        # 筛选指定日期和小时的逐小时预报
        return get_object_or_404(
            HourlyForecast,
            location=location,
            time__date=target_date,
            time__hour=target_hour
        )

3. 可选:为DailyForecast添加唯一约束

确保同一个地点同一天只有一条预报数据,避免get_object_or_404返回多个对象:

# models.py
class DailyForecast(Forecast):
    # ... 原有字段 ...
    class Meta:
        verbose_name_plural = "daily forecasts"
        unique_together = ("location", "date")  # 添加唯一约束

验证

重新启动服务后,访问以下URL即可正常显示:

  • 带日期:http://127.0.0.1:8000/forecast/narnia/2023-03-26/
  • 不带日期(显示今日预报):http://127.0.0.1:8000/forecast/narnia/

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:09:57