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

如何在Django Rest Framework类视图中通过slug而非ID获取详情页

如何在Django Rest Framework中通过Slug访问详情API端点

我正在使用Django Rest Framework构建API,现有/api/localities端点用于展示数据库中的所有地区对象。现在想创建单个地区的详情端点,要求通过slug而非ID访问,例如/api/localities/munich。目前使用类视图只能通过ID(如/api/localities/2)获取详情页,请问如何修改为使用slug?

以下是我的代码:

models.py

class Localities(models.Model):
        id_from_api = models.IntegerField()
        city = models.CharField(max_length=255, null=True, blank=True)
        slug = models.CharField(max_length=255, null=True, blank=True)
        postal_code = models.CharField(max_length=20, null=True, blank=True)
        country_code = models.CharField(max_length=10, null=True, blank=True)
        lat = models.CharField(max_length=255, null=True, blank=True)
        lng = models.CharField(max_length=255, null=True, blank=True)
        google_places_id = models.CharField(max_length=255, null=True, blank=True)
        search_description = models.CharField(max_length=500, null=True, blank=True)
        seo_title = models.CharField(max_length=255, null=True, blank=True)

        def __str__(self):
             return self.city

serializers.py

from rest_framework import serializers
from .models import Localities

class LocalitiesSerializers(serializers.ModelSerializer):
    class Meta:
        model = Localities
        fields = (
            "id",
            "id_from_api",
            "city",
            "slug",
            "postal_code",
            "country_code",
            "lat",
            "lng",
            "google_places_id",
            "search_description",
            "seo_title",
        )

views.py

from django.shortcuts import render
from django.http import HttpResponse
from wagtail.core.models import Page
from .models import LocalityPage, Localities
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import generics

import json
import requests

from .models import Localities
from .serializers import LocalitiesSerializers


class LocalitiesAll(generics.ListCreateAPIView):
    queryset = Localities.objects.all()
    serializer_class = LocalitiesSerializers


class LocalitiesDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Localities.objects.all()
    serializer_class = LocalitiesSerializers

urls.py

from django.urls import path
from . import views

urlpatterns = [  
    path('reload', views.convert_json),  # app homepage
    path("localities/", views.LocalitiesAll.as_view()),
    path("localities/<int:pk>/", views.LocalitiesDetail.as_view()),
] 

修改步骤

1. 优化Slug字段(可选但强烈推荐)

当前slug字段允许为空和重复,这会导致通过slug查询时可能找不到对象或返回多个对象。建议将其修改为唯一、非空的SlugField:

# models.py
slug = models.SlugField(max_length=255, unique=True, null=False, blank=False)

注:SlugField会自动处理字符串格式(转小写、替换特殊字符为横杠),如果需要保留原有格式,也可以继续用CharField但必须添加unique=True约束。

2. 配置视图使用Slug查询

在LocalitiesDetail视图类中添加lookup_field属性,指定用slug字段作为查询依据:

# views.py
class LocalitiesDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Localities.objects.all()
    serializer_class = LocalitiesSerializers
    lookup_field = 'slug'  # 核心修改:用slug替代默认的pk

3. 更新URL路由

将URL中的<int:pk>替换为<slug:slug>(如果是普通CharField可以用<str:slug>),匹配slug格式的参数:

# urls.py
urlpatterns = [  
    path('reload', views.convert_json),  # app homepage
    path("localities/", views.LocalitiesAll.as_view()),
    path("localities/<slug:slug>/", views.LocalitiesDetail.as_view()),  # 修改此处
] 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:53:19